Skip to content

cc-wrapper: always include libc++ in the search path#445095

Merged
reckenrode merged 2 commits intoNixOS:stagingfrom
reckenrode:push-qqkpmoymspzl
Oct 9, 2025
Merged

cc-wrapper: always include libc++ in the search path#445095
reckenrode merged 2 commits intoNixOS:stagingfrom
reckenrode:push-qqkpmoymspzl

Conversation

@reckenrode
Copy link
Contributor

@reckenrode reckenrode commented Sep 22, 2025

I found this was necessary when working on the Swift 6.x update. The libc++ headers are expected to be found in the sysroot when clang is invoked for C++ code.

Always making them available improves compatibility with build systems
like Bazel and SwiftPM, which try to compile C++ code with clang.

Things done

  • Built on platform:
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • Tested, as applicable:
  • Ran nixpkgs-review on this PR. See nixpkgs-review usage.
  • Tested basic functionality of all binary files, usually in ./result/bin/.
  • Nixpkgs Release Notes
    • Package update: when the change is major or breaking.
  • NixOS Release Notes
    • Module addition: when adding a new NixOS module.
    • Module update: when the change is significant.
  • Fits CONTRIBUTING.md, pkgs/README.md, maintainers/README.md and other READMEs.

Add a 👍 reaction to pull requests you find important.

@ofborg ofborg bot added the 6.topic: darwin Running or building packages on Darwin label Sep 22, 2025
@nixpkgs-ci nixpkgs-ci bot added 10.rebuild-linux: 501+ This PR causes many rebuilds on Linux and should normally target the staging branches. 10.rebuild-darwin: 501+ This PR causes many rebuilds on Darwin and should normally target the staging branches. 10.rebuild-linux-stdenv This PR causes stdenv to rebuild on Linux and must target a staging branch. 10.rebuild-darwin-stdenv This PR causes stdenv to rebuild on Darwin and must target a staging branch. 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. 10.rebuild-linux: 5001+ This PR causes many rebuilds on Linux and must target the staging branches. labels Sep 22, 2025
@nix-owners nix-owners bot requested a review from Ericson2314 September 22, 2025 00:19
Comment on lines +151 to +152
# This duplicates the behavior of a native toolchain, which can find the
# libc++ headers but requires `-lc++` to be specified explicitly when linking.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn’t quite seem right:

shion:/v/f/1/j/T/tmp.FU3kWEOHHp
❭ clang foo.c
foo.c:1:10: fatal error: 'cstdint' file not found
    1 | #include <cstdint>
      |          ^~~~~~~~~
1 error generated.

Even #include <c++/v1/cstdint> fails, because it tries to include other headers without that prefix.

We should certainly make clang -x c work, but I’m not sure this header behaviour is quite right?

BTW, there’s a -stdlib++-isystem and -cxx-isystem that probably do exactly what we want here, but they’re Clang‐only.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you testing? Aside from my Swift branch, which worked, this is what I get when I nix develop something early in the bootstrap (like libiconv-1.17; because I haven’t bootstrapped) and try to compile a C++ file with clang.

$ cat test.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <cstdint>

int main() {
	std::array<std::int32_t, 4> x = { 1, 2, 3, 4 };

	std::for_each(x.begin(), x.end(), [](int32_t& val) {
		std::cout << "value: " << val << std::endl;
	});
}
$ clang test.cpp -c -o test.o
$ clang test.o -o test -lc++
$ ./test
value: 1
value: 2
value: 3
value: 4

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, there’s a -stdlib++-isystem and -cxx-isystem that probably do exactly what we want here, but they’re Clang‐only.

The issue is Clang expects the headers to be in the sysroot, but they’re not there. It has to be told where to find them by the wrapper, but the wrapper only does that when it thinks you’re compiling for C++. Always making the headers available accomplishes (mostly) the same thing as having them there.

It would be so much better if we generated a sysroot that compilers could be directed use. It would even work with unwrapped compilers (provided they were set up correctly).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My test was with Xcode Clang – I thought that was the native toolchain being compared to:

Apple clang version 17.0.0 (clang-1700.3.19.1)
Target: arm64-apple-darwin25.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

The issue is Clang expects the headers to be in the sysroot, but they’re not there. It has to be told where to find them by the wrapper, but the wrapper only does that when it thinks you’re compiling for C++.

-stdlib++-isystem is precisely there to tell Clang where the headers for the C++ standard library are. I think it would make -x c++ work exactly as expected. But it’s not an option with GCC.

Copy link
Contributor Author

@reckenrode reckenrode Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My test was with Xcode Clang

Is SYSROOT or DEVELOPER_DIR set and pointing to an SDK in the store? It works for me with a native toolchain.

$ command -v clang
/usr/bin/clang
$ xcrun --find clang
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
$ clang -v
Apple clang version 17.0.0 (clang-1700.3.19.1)
Target: arm64-apple-darwin25.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$ clang test.cpp -c -o test.o
$ clang test.o -o test -lc++
$ ./test
value: 1
value: 2
value: 3
value: 4

-stdlib++-isystem is precisely there to tell Clang where the headers for the C++ standard library are. I think it would make -x c++ work exactly as expected. But it’s not an option with GCC.

This change is leveraging the wrapper’s support for sourcing the libc++ flags in nix-support/libcxx-cxxflags. If using -stdlib++-isystem is the correct way to specify the location to the C++ headers, the wrapper should be updated to use that instead with Clang, but that’s more appropriately done in another PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is SYSROOT or DEVELOPER_DIR set and pointing to an SDK in the store? It works for me with a native toolchain.

No, it was with the normal Xcode SDK, outside of any Nix environment. But I see what’s going on here – it’s the file extension:

shion:/v/f/1/j/T/tmp.L6mt2HOXnQ
❭ cat test.c
#include <cstdint>

int main() {}

shion:/v/f/1/j/T/tmp.L6mt2HOXnQ
❭ clang test.c
test.c:1:10: fatal error: 'cstdint' file not found
    1 | #include <cstdint>
      |          ^~~~~~~~~
1 error generated.

shion:/v/f/1/j/T/tmp.L6mt2HOXnQ  1
❭ mv test.c test.cpp

shion:/v/f/1/j/T/tmp.L6mt2HOXnQ
❭ clang test.cpp

shion:/v/f/1/j/T/tmp.L6mt2HOXnQ
❭ 

So, the native toolchain does behave as I expected – it’ll use the C++ library include directory, but only for code that it thinks is C++, whether from -x c++ or file extension. With your change here, C code would be able to see C++ headers directly too, which would be a divergence from the native toolchain.

The reason I brought up -cxx-isystem and -stdlib++-isystem is because they let us solve this problem:

shion:/v/f/1/j/T/tmp.exLD7JRuOy
❭ cat test.c
#include "test.h"

int main() {}

shion:/v/f/1/j/T/tmp.exLD7JRuOy
❭ ls cxxinclude
test.h

shion:/v/f/1/j/T/tmp.exLD7JRuOy
❭ clang -cxx-isystem cxxinclude test.c
test.c:1:10: fatal error: 'test.h' file not found
    1 | #include "test.h"
      |          ^~~~~~~~
1 error generated.

shion:/v/f/1/j/T/tmp.exLD7JRuOy  1
❭ mv test.c test.cpp

shion:/v/f/1/j/T/tmp.exLD7JRuOy
❭ clang -cxx-isystem cxxinclude test.cpp

shion:/v/f/1/j/T/tmp.exLD7JRuOy
❭ 

All we would need to do is use -cxx-isystem rather than -isystem in libcxx-cxxflags when the compiler is Clang, and we should match the native toolchain’s behaviour. -stdlib++-isystem would be the same except it’d respond to -nostdinc++ – so that would be even closer to native toolchain behaviour.

Unfortunately, this wouldn’t help for GCC. I suppose that passing --with-gxx-libcxx-include-dir=${lib.getInclude darwin.libcxx}/include/c++/v1 in configureFlags would probably do the trick there well enough – depending on how it interacts with -nostdinc, possibly.

Copy link
Member

@emilazy emilazy Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Also I do think we should do this for all Clang, since it’s just a nice move in the direction of less wrapper logic and more telling the compiler drivers what we actually want. I’m happy to run Linux builds to test the effect there, and Darwin builds too.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using -stdlib++-isystem causes xz to fail to build. Using -cxx-isystem works. (Still bootstrapping.)

clang: warning: argument unused during compilation: '-stdlib++-isystem /nix/store/sj56s86jwq7cjdy0af2f3vy24pkh3zfy-bootstrap-stage0-libcxx/include/c++/v1' [-Wunused-command-line-argument]

github-actions[bot]

This comment was marked as resolved.

@reckenrode reckenrode changed the base branch from master to staging September 22, 2025 02:17
@nixpkgs-ci nixpkgs-ci bot closed this Sep 22, 2025
@nixpkgs-ci nixpkgs-ci bot reopened this Sep 22, 2025
@github-actions github-actions bot dismissed their stale review September 22, 2025 02:18

All good now, thank you!

@reckenrode
Copy link
Contributor Author

I updated the PR to use -cxx-isystem. Currently building up to Rust, but the bootstrap worked.

@reckenrode
Copy link
Contributor Author

Rust built.

@nixpkgs-ci nixpkgs-ci bot added the 12.approvals: 1 This PR was reviewed and approved by one person. label Sep 30, 2025
reckenrode added a commit to reckenrode/nixpkgs that referenced this pull request Nov 18, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
@reckenrode
Copy link
Contributor Author

@quyse Can you test against #462747? It should fix your issue.

@quyse
Copy link
Contributor

quyse commented Nov 18, 2025

@quyse Can you test against #462747? It should fix your issue.

@reckenrode Yes it fixes it, thank you!

nixpkgs-ci bot pushed a commit that referenced this pull request Nov 18, 2025
This is necessary after #445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.

(cherry picked from commit d46fa26)
vkleen pushed a commit to vkleen/nixpkgs that referenced this pull request Nov 25, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
Mast3rwaf1z pushed a commit to Mast3rwaf1z/nixpkgs that referenced this pull request Nov 30, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.

(cherry picked from commit d46fa26)
mattkang pushed a commit to mattkang/nixpkgs that referenced this pull request Dec 1, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
alejo7797 added a commit to alejo7797/nixpkgs that referenced this pull request Dec 11, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.

(cherry picked from commit NixOS@d46fa26)
Mast3rwaf1z pushed a commit to Mast3rwaf1z/nixpkgs that referenced this pull request Dec 16, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.

(cherry picked from commit d46fa26)
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 22, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 22, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
gernotfeichter pushed a commit to gernotfeichter/nixpkgs that referenced this pull request Dec 23, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.

(cherry picked from commit d46fa26)
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 23, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 24, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 24, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 24, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 25, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 25, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 26, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 27, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
al3xtjames pushed a commit to al3xtjames/nixpkgs that referenced this pull request Dec 28, 2025
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/clang-clang-and-clangd-cant-find-headers-even-with-compile-commands-json/54657/13

pseudocc pushed a commit to pseudocc/nixpkgs that referenced this pull request Jan 9, 2026
This is necessary after NixOS#445095,
which moved libc++ to -cxx-isystem to improve compatibility with build
systems that invoke `clang` to compile C++ code.

(cherry picked from commit d46fa26)
ryanofsky added a commit to ryanofsky/libmultiprocess that referenced this pull request Jan 9, 2026
Without this change, building with -DMP_ENABLE_IWYU=ON and newer versions of
nixpkgs (after 2025-11-12) fails with mysterious errors that look like:

make[2]: *** [CMakeFiles/mputil.dir/build.make:79: CMakeFiles/mputil.dir/src/mp/util.cpp.o] Error 1

with no other error messages. The are no messages because cmake -E
__run_co_compile hides the output from IWYU and does not display anything itself.

The actual problem is missing include directories on the compiler command line,
and the fix here is to extend a workaround previously added for clang-tidy to
be used for IWYU as well.

Breakage seems to have been caused by
NixOS/nixpkgs@76a8ffa
from NixOS/nixpkgs#445095, which I found by bisecting
with --first-parent to a change between the following merge commit:

https://github.com/NixOS/nixpkgs/commits/de21549a840be528ef4763dd7dca2006caf9c11f (bad)
https://github.com/NixOS/nixpkgs/commits/c4d1151093af5d483d1900d9214a65e68bc21560 (good)

If you check out the bad commit above (or any later commit) and revert
NixOS/nixpkgs@76a8ffa
the problem disappears.

I suspect the problem happens because cmake is not handling -cxx-isystem
properly, but did not debug further.
@ghpzin ghpzin mentioned this pull request Jan 10, 2026
3 tasks
ryanofsky added a commit to ryanofsky/libmultiprocess that referenced this pull request Jan 13, 2026
Without this change, building with -DMP_ENABLE_IWYU=ON and newer versions of
nixpkgs (after 2025-11-12) fails with mysterious errors that look like:

make[2]: *** [CMakeFiles/mputil.dir/build.make:79: CMakeFiles/mputil.dir/src/mp/util.cpp.o] Error 1

with no other error messages. The are no messages because cmake -E
__run_co_compile hides the output from IWYU and does not display anything itself.

The actual problem is missing include directories on the compiler command line,
and the fix here is to extend a workaround previously added for clang-tidy to
be used for IWYU as well.

Breakage seems to have been caused by
NixOS/nixpkgs@76a8ffa
from NixOS/nixpkgs#445095, which I found by bisecting
with --first-parent to a change between the following merge commit:

https://github.com/NixOS/nixpkgs/commits/de21549a840be528ef4763dd7dca2006caf9c11f (bad)
https://github.com/NixOS/nixpkgs/commits/c4d1151093af5d483d1900d9214a65e68bc21560 (good)

If you check out the bad commit above (or any later commit) and revert
NixOS/nixpkgs@76a8ffa
the problem disappears.

I suspect the problem happens because cmake is not handling -cxx-isystem
properly, but did not debug further. The later change
NixOS/nixpkgs#462747 which followed up on
NixOS/nixpkgs#445095 did not seem to have any effect on
this issue in my testing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: darwin Running or building packages on Darwin 10.rebuild-darwin: 501+ This PR causes many rebuilds on Darwin and should normally target the staging branches. 10.rebuild-darwin: 5001+ This PR causes many rebuilds on Darwin and must target the staging branches. 10.rebuild-darwin-stdenv This PR causes stdenv to rebuild on Darwin and must target a staging branch. 10.rebuild-linux: 501+ This PR causes many rebuilds on Linux and should normally target the staging branches. 10.rebuild-linux: 5001+ This PR causes many rebuilds on Linux and must target the staging branches. 10.rebuild-linux-stdenv This PR causes stdenv to rebuild on Linux and must target a staging branch. 12.approvals: 1 This PR was reviewed and approved by one person. 12.approved-by: package-maintainer This PR was reviewed and approved by a maintainer listed in any of the changed packages.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants