Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stdenv.cc: use libc++ as default c++ standard library on darwin #41589

Closed
wants to merge 1 commit into from

Conversation

uri-canva
Copy link
Contributor

@uri-canva uri-canva commented Jun 6, 2018

Motivation for this change

When installing clang on darwin the default c++ standard library isn't set up as it is for gcc on Linux, so compiling c++ code will fail unless include and link flags for the standard library as specified explicitly, which is counter intuitive as the compiler will add them automatically in a traditional installation unless -nostdlib or similar is used.

In fact the derivation of gcc does take care of this.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

@GrahamcOfBorg GrahamcOfBorg added the 6.topic: darwin Running or building packages on Darwin label Jun 6, 2018
@@ -126,9 +126,9 @@ fi

if [[ "$isCpp" = 1 ]]; then
if [[ "$cppInclude" = 1 ]]; then
NIX_@infixSalt@_CFLAGS_COMPILE+=" ${NIX_@infixSalt@_CXXSTDLIB_COMPILE-@default_cxx_stdlib_compile@}"
NIX_@infixSalt@_CFLAGS_COMPILE+=" ${NIX_@infixSalt@_CXXSTDLIB_COMPILE:-@default_cxx_stdlib_compile@}"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The missing : might have been a bug: since the variable is declared in add-flags.sh the default substitution will not come into play with -, only with :-.

default_cxx_stdlib_compile = if (targetPlatform.isLinux && !(cc.isGNU or false) && !nativeTools) then
"-isystem $(echo -n ${cc.gcc}/include/c++/*) -isystem $(echo -n ${cc.gcc}/include/c++/*)/$(${cc.gcc}/bin/gcc -dumpmachine)"
else if (targetPlatform.isDarwin && (cc.isClang or true) && !nativeTools && libcxx != null) then
"-isystem ${libcxx}/include/c++/v1"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should this be ${libcxx}/include/c++/* instead like the gcc one? I'm not sure which is the correct way, especially since if it has multiple versions that would make the oldest version win, assuming the * works like shell globs.

Copy link
Member

Choose a reason for hiding this comment

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

I might be wrong, but I think this has impact on bootstrapping the darwin stdenv.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I personally would have preferred passing libcxx only from all-packages.nix's clang. My interest is in having nix-env -iA clang install a working clang on darwin. I understand that when using clang from within nixpkgs the right flags are threaded through via the hooks and environment variables.

But it didn't seem like nix-env -iA clang was installing that clang at all, at least builtins.trace showed that wasn't getting evaluated at all. I'm a bit confused on how nix-env -iA finds the derivations to install.

else
"";
default_cxx_stdlib_link = optionalString (targetPlatform.isDarwin && (cc.isClang or true) && !nativeTools && libcxx != null)
"-L${libcxx}/lib -stdlib=libc++";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think there's a function to get the library directory of a derivation, I forget what it was though (getLib maybe), and whether it should be used in this situation.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah it's probably safer to use getLib here. libc++ could become multiple outputs in the future.

@Synthetica9
Copy link
Member

Wouldn't you want to merge this into staging instead of master?

@LnL7
Copy link
Member

LnL7 commented Jun 6, 2018

See #30670

I'd personally prefer to get rid of the default_cxx_stdlib_compile attribute and it's crazy conditional.

@uri-canva uri-canva requested a review from FRidh as a code owner June 6, 2018 23:42
@uri-canva uri-canva changed the base branch from master to staging June 6, 2018 23:43
@@ -360,6 +360,7 @@ in rec {
cc = pkgs.llvmPackages.clang-unwrapped;
bintools = pkgs.darwin.binutils;
libc = pkgs.darwin.Libsystem;
libcxx = pkgs.libcxx;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we don't pass in libcxx here then stdenv is unaffected.

@uri-canva
Copy link
Contributor Author

I'm trying to get this to work: #30670 (comment)

I'd like nix-env -iA clang (it installs clang-wrapper-5.0.2 right now) to install a clang compiler that can be used outside of nixpkgs.

According to the discussion in #30670 we should have an wrapper for clang being used outside of nixpkgs, then nixpkgs can used the unwrapped one? I thought that was already the case with wrapCC? Or is that a different kind of wrapper?

@matthewbauer
Copy link
Member

I'd like nix-env -iA clang (it installs clang-wrapper-5.0.2 right now) to install a clang compiler that can be used outside of nixpkgs.

That shouldn't be too hard if it's not being used anywhere else. Just set:

clang = llvmPackages.clang.cc;

and you should get the "unwrapped" version. We will probably need to refactor things for this to work but I agree with it & I think that that's what most users would expect. Of course it won't pick up your dependencies correctly (NIX_CFLAGS_COMPILE will be broken).

@matthewbauer
Copy link
Member

That would be a really good refactoring project if someone is looking for something to do: remove all references in Nixpkg to clang or gcc directly - packages shouldn't depend on them, instead they should use the corresponding stdenv (there are a few exceptions with libclang however).

@uri-canva
Copy link
Contributor Author

That shouldn't be too hard if it's not being used anywhere else. Just set:

I don't understand. The unwrapped version cannot be used outside of nixpkgs since it doesn't have the c++ standard library, so that wouldn't help? Do you mean nixpkgs should use the unwrapped one everywhere, and then we can make the wrapped one work outside of nixpkgs?

I'm confused what the wrapping is for now if it's not to make it work outside of nixpkgs?

@matthewbauer
Copy link
Member

I don't understand. The unwrapped version cannot be used outside of nixpkgs since it doesn't have the c++ standard library, so that wouldn't help? Do you mean nixpkgs should use the unwrapped one everywhere, and then we can make the wrapped one work outside of nixpkgs?

Ok that's true w.r.t. to c++ being missing. The wrapped version is meant to only be run in mkDerivation & nix-shell. There are many hacks that we apply that are pretty specific to Nixpkgs & it's possible that with some work we can get it to work correctly, but I've never used it that way. My understanding is that the "unwrapped" clang should be identical to what you would get in any other package manager but it's possible that the missing libc++ will be an issue. We may need a different wrapper to make it behave like a normal c++ compiler.

@Ericson2314
Copy link
Member

Okay yeah there's other ways to fix this with like a pkg-config wrapper which is what I really want. Let's hold off for a second sorry.

@uri-canva
Copy link
Contributor Author

I tested it a bit more and I'm really confused:

diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 1b7800301fd..058f9d54158 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -6067,7 +6067,7 @@ with pkgs;
     inherit (darwin) cctools;
   };

-  clang = llvmPackages.clang;
+  clang = null;

   clang-sierraHack = clang.override {
     name = "clang-wrapper-with-reexport-hack";
@@ -6082,7 +6082,7 @@ with pkgs;
   };

   clang_6  = llvmPackages_6.clang;
-  clang_5  = llvmPackages_5.clang;
+  clang_5  = null;
   clang_4  = llvmPackages_4.clang;
   clang_39 = llvmPackages_39.clang;
   clang_38 = llvmPackages_38.clang;
$ nix-env --max-jobs 4 --cores 4 --file . --profile /nix/var/nix/profiles/per-user/uri/uri-bazel-nix -iA clang_5 --show-trace
error: expression does not evaluate to a derivation (or a set or list of those)
$ nix-env --max-jobs 4 --cores 4 --file . --profile /nix/var/nix/profiles/per-user/uri/uri-bazel-nix -iA clang --show-trace
replacing old 'clang-wrapper-5.0.2'
installing 'clang-wrapper-5.0.2'
...

so what is -iA clang installing?

@uri-canva
Copy link
Contributor Author

Opened a higher level issue to understand whether the expectation of clang working outside of nix-shell and nixpkgs is correct: #42059.

@uri-canva
Copy link
Contributor Author

@Ericson2314 can you elaborate on the pkg-config wrapper you have in mind?

According to @orivej in #42059 and @matthewbauer above it should be ok to have two different derivations for clang, one for use in a nix environment and one outside, so I will be looking at doing that, is that related?

@Ericson2314
Copy link
Member

Ericson2314 commented Jun 19, 2018

The pkg-config wrapper would use pkg-config where possible to get the -isystem and -L flags. Then libc++ needs no special support: we give it a pkg-config file with two -isystem entries.

Two different clangs is fine, yes.

@jwiegley
Copy link
Contributor

jwiegley commented Sep 7, 2018

I've run into this today too. I was expecting the following to show me the ctime file:

ls -l $($(nix-store -r $(nix-instantiate --expr 'let pkgs = import <nixpkgs> {}; in pkgs.llvmPackages_6.libcxxStdenv.cc.cc') | head -1)/bin/clang++ -print-search-dirs | tail -1 | sed 's/libraries: =//')/include/ctime

However, -print-search-dirs reports that there is only one libraries path, and it only contains relatively few files in it.

@matthewbauer
Copy link
Member

The missing clang++ on nix-shell should be addressed on master. Feel free to reopen if this is still relevant.

@uri-canva uri-canva deleted the clang-darwin branch February 22, 2019 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants