-
-
Notifications
You must be signed in to change notification settings - Fork 15.1k
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
python3Packages.jax: fix libstdc++ mismatch when built with CUDA #225661
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,33 @@ | ||
{ nixpkgsStdenv | ||
, nvccCompatibleStdenv | ||
{ lib | ||
, nixpkgsCompatibleLibstdcxx | ||
, nvccCompatibleCC | ||
, overrideCC | ||
, stdenv | ||
, wrapCCWith | ||
}: | ||
|
||
overrideCC nixpkgsStdenv (wrapCCWith { | ||
cc = nvccCompatibleStdenv.cc.cc; | ||
let | ||
cc = wrapCCWith | ||
{ | ||
cc = nvccCompatibleCC; | ||
|
||
# This option is for clang's libcxx, but we (ab)use it for gcc's libstdc++. | ||
# Note that libstdc++ maintains forward-compatibility: if we load a newer | ||
# libstdc++ into the process, we can still use libraries built against an | ||
# older libstdc++. This, in practice, means that we should use libstdc++ from | ||
# the same stdenv that the rest of nixpkgs uses. | ||
# We currently do not try to support anything other than gcc and linux. | ||
libcxx = nixpkgsCompatibleLibstdcxx; | ||
}; | ||
cudaStdenv = overrideCC stdenv cc; | ||
samuela marked this conversation as resolved.
Show resolved
Hide resolved
|
||
passthruExtra = { | ||
inherit nixpkgsCompatibleLibstdcxx; | ||
# cc already exposed | ||
}; | ||
assertCondition = true; | ||
in | ||
lib.extendDerivation | ||
assertCondition | ||
passthruExtra | ||
cudaStdenv | ||
|
||
# This option is for clang's libcxx, but we (ab)use it for gcc's libstdc++. | ||
# Note that libstdc++ maintains forward-compatibility: if we load a newer | ||
# libstdc++ into the process, we can still use libraries built against an | ||
# older libstdc++. This, in practice, means that we should use libstdc++ from | ||
# the same stdenv that the rest of nixpkgs uses. | ||
# We currently do not try to support anything other than gcc and linux. | ||
libcxx = nixpkgsStdenv.cc.cc.lib; | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,7 +49,7 @@ | |
}: | ||
|
||
let | ||
inherit (cudaPackages) cudatoolkit cudaFlags cudnn nccl; | ||
inherit (cudaPackages) backendStdenv cudatoolkit cudaFlags cudnn nccl; | ||
|
||
pname = "jaxlib"; | ||
version = "0.3.22"; | ||
|
@@ -81,7 +81,7 @@ let | |
cudatoolkit_cc_joined = symlinkJoin { | ||
name = "${cudatoolkit.cc.name}-merged"; | ||
paths = [ | ||
cudatoolkit.cc | ||
backendStdenv.cc | ||
binutils.bintools # for ar, dwp, nm, objcopy, objdump, strip | ||
]; | ||
}; | ||
SomeoneSerge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
@@ -271,6 +271,7 @@ let | |
sed -i 's@include/pybind11@pybind11@g' $src | ||
done | ||
'' + lib.optionalString cudaSupport '' | ||
export NIX_LDFLAGS+=" -L${backendStdenv.nixpkgsCompatibleLibstdcxx}/lib" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the order matter here? I'm assuming There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think there's any extra |
||
patchShebangs ../output/external/org_tensorflow/third_party/gpus/crosstool/clang/bin/crosstool_wrapper_driver_is_not_gcc.tpl | ||
'' + lib.optionalString stdenv.isDarwin '' | ||
# Framework search paths aren't added by bintools hook | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately I don't think
libcxx
here has the semantics you're looking for.nixpkgsCompatibleLibstdcxx
is added topropagatedDeps
but I think that's it; If you look incc-wrapper
,libcxx
is only consulted forlibc++
include paths whenlibcxx.isLLVM
is present and true:nixpkgs/pkgs/build-support/cc-wrapper/default.nix
Lines 372 to 388 in 82fa717
Even if
nixpkgsCompatibleLibstdcxx.isLLVM
were present and true this wouldn't work as intended; the logic forlibcxx
incc-wrapper
(i.e.-stdlib
,cxxabi
,include/c++/v1
) really is specific toclang
andlibc++
.Further, setting
libcxx
does not inhibitcc-wrapper
from tacking on the gcc library paths where thecc
's libraries (i.e.libstdc++
and friends) tocflags
/ldflags
.Unfortunately I don't think
cc-wrapper
as it exists today has the right knobs to support this use case (cc = gcc
butlibstdc++
from a different gcc) but I think we can get pretty close withuseCcForLibs
andgccForLibs = gccFromWhichYouWantToGrabLibstdcxx
. Here's a quick PoC (imperfect -- it seems to loselibc
headers somehow -- but hopefully gets the point across): dc6a8f9Note that with the commit above, using
"${np.cudaPackages.backendStdenv.cc}/bin/g++
to compile binaries results in them being linked againstlibstdc++
fromgcc12
(observable by runningldd
on the binaries). With the PR as it exists right now, such binaries are still linked againstlibstdc++
frombackendStdenv.cc.cc
.Depending on what the requirement here is (just a newer
libstdc++
? compiler builtins likelibgcc_s
too? etc) getting cc-wrapper to support this use case might make more sense than adding link options for the desiredlibstdc++
to packages in an ad-hoc way.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was almost sure about that when I added the original line
Indeed! And by sheer accident this has been sufficient for most of our broken cuda packages. This is why took a blind eye on the obvious erroneousness of the current "approach" and hastily merged #223664
I think it shouldn't be hard, though, to develop this into a correctly working stdenv while keeping all of the interfaces intact
I suspected so. Again, effectively we've only relied on the propagated build inputs so far, but we definitely should keep it this way for long
I was afraid of that. I think it would make sense to extend cc-wrapper for our use-case
Oh wow, thank you so much! I think this is exactly the direction we should be heading in!
Thankfully,
backendStdenv.cc.cc
does not really link to its.lib
and happily picks up any libstdc++ we put in downstream package'sbuildInputs
... unless they are built with BazelBut, as I admit above, this behaviour is accidental and we must not rely on it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point, I think we only need to override what c++ stdlib gets written into runpaths of downstream derivations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay, thanks for clarifying; this is good to hear 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, interesting...
In general I'd think that your propagated deps would make their way into the linkopts that Bazel uses (propagatedDeps should get picked up by the
bintools
stdenv hooks and added toNIX_LDFLAGS
whichbuildBazelPackage
should map tolinkopts
).Maybe it's an ordering thing? I think normally things specified in the
NIX_LDFLAGS
env var would have precedence over flags inlibc-ldflags
; with Bazel'slinkopts
this wouldn't be the case.Easiest way to test would be to add
NIX_LDFLAGS
as anaction_env
in the Bazel options I think.