Closed rrbutani closed 7 months ago
Any updates on this issue?
Should we be doing this in the cc wrapper on darwin like we do on linux? It seems weird to require package maintainers to fix this package by package.
I looked more into this specifically for #269340 and it turns out that the cc-wrapper
script will indeed pass in -lc++abi
, but only if it detects that it attempts to link C++ code. And Postgis invokes its C compiler:
cc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Werror=unguarded-availability-new -Wendif-labels -Wmissing-format-attribute -Wcast-function-type -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-unused-command-line-argument -Wno-compound-token-split-by-macro -Wno-deprecated-non-prototype -g -O2 -bundle -o postgis-3.so postgis_module.o lwgeom_accum.o lwgeom_union.o lwgeom_spheroid.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_inout.o lwgeom_functions_basic.o lwgeom_btree.o lwgeom_box.o lwgeom_box3d.o lwgeom_geos.o lwgeom_geos_prepared.o lwgeom_geos_clean.o lwgeom_geos_relatematch.o lwgeom_generate_grid.o lwgeom_export.o lwgeom_in_gml.o lwgeom_in_kml.o lwgeom_in_marc21.o lwgeom_out_marc21.o lwgeom_in_geohash.o lwgeom_in_geojson.o lwgeom_in_encoded_polyline.o lwgeom_triggers.o lwgeom_dump.o lwgeom_dumppoints.o lwgeom_functions_lrs.o lwgeom_functions_temporal.o lwgeom_rectree.o long_xact.o lwgeom_sqlmm.o lwgeom_rtree.o lwgeom_transform.o lwgeom_window.o gserialized_typmod.o gserialized_gist_2d.o gserialized_gist_nd.o gserialized_supportfn.o gserialized_spgist_2d.o gserialized_spgist_3d.o gserialized_spgist_nd.o brin_2d.o brin_nd.o brin_common.o gserialized_estimate.o geography_inout.o geography_btree.o geography_centroid.o geography_measurement.o geography_measurement_trees.o geometry_inout.o postgis_libprotobuf.o vector_tile.pb-c.o geobuf.pb-c.o mvt.o lwgeom_out_mvt.o geobuf.o lwgeom_out_geobuf.o lwgeom_out_geojson.o flatgeobuf.o lwgeom_in_flatgeobuf.o lwgeom_out_flatgeobuf.o postgis_legacy.o -lm ../deps/wagyu/libwagyu.la -lc++ ../deps/flatgeobuf/libflatgeobuf.la -lc++ ../libpgcommon/libpgcommon.a ../liblwgeom/.libs/liblwgeom.a -L/nix/store/r3ci57b9h44dm8bzgddj2s33gmzf0k9d-geos-3.11.2/lib -lgeos_c -L/nix/store/crykfdf8mmkll3a524l34cd80cxczqrm-proj-9.3.0/lib -lproj -L/nix/store/h55yv2msyvgggbxb093za5was5yxfi47-json-c-0.16-dev/lib -ljson-c -L/nix/store/phw2l0iwb43pd3j1hlaml46asziw7vw0-protobuf-c-unstable-2023-07-08/lib -lprotobuf-c -L/nix/store/al2fcmdcsxlx9zv5nsr4464dmrypf2bk-libxml2-2.11.5/lib -lxml2 -L/nix/store/a377d66g1rgsd4vkzxdhkza5g55fkmky-zlib-1.3/lib -lz -lm -bundle_loader /nix/store/2364df0zry22gjqgsbdz41ypabbvsbm9-postgis-3.4.0/bin/postgres
Changing cc
to clang++
will cause this to compile correctly.
Alternatively, applying the following patch also causes the cc-wrapper
to detect that this is indeed a C++ linking happening:
diff --git i/pkgs/build-support/cc-wrapper/cc-wrapper.sh w/pkgs/build-support/cc-wrapper/cc-wrapper.sh
index b8d170df01..62075b2e3f 100644
--- i/pkgs/build-support/cc-wrapper/cc-wrapper.sh
+++ w/pkgs/build-support/cc-wrapper/cc-wrapper.sh
@@ -48,6 +48,7 @@ while (( "$n" < "$nParams" )); do
-nostdlib) cxxLibrary=0 ;;
-x*-header) dontLink=1 ;; # both `-x c-header` and `-xc-header` are accepted by clang
-xc++*) isCxx=1 ;; # both `-xc++` and `-x c++` are accepted by clang
+ -lc++) isCxx=1 ;;
-x)
case "$p2" in
*-header) dontLink=1 ;;
Hey it looks like we wound up with 33 copy-and-pastes of this code:
$ rg 'https://github.com/NixOS/nixpkgs/issues/166205' | wc -l
33
This means that when there's a bug in the copy-and-pasted code (which there is -- it breaks CI if stdenv.cc.libcxx
exists but lacks a cxxabi
subattribute) we need 33 separate fixes.
One of Nix's superpowers is that it provides abstraction, so we can refactor instead of copying and pasting. Please use those superpowers next time -- probably by changing ld-wrapper
to add -l${stdenv.cc.libcxx.cxxabi.libName}
automatically. That way, if there's a bug it can be fixed in one place instead of having to make thirty-three different changes, like these:
Hey it looks like we wound up with 33 copy-and-pastes of this code:
$ rg 'https://github.com/NixOS/nixpkgs/issues/166205' | wc -l 33
This means that when there's a bug in the copy-and-pasted code (which there is -- it breaks CI if
stdenv.cc.libcxx
exists but lacks acxxabi
subattribute) we need 33 separate fixes.One of Nix's superpowers is that it provides abstraction, so we can refactor instead of copying and pasting. Please use those superpowers next time -- probably by changing
ld-wrapper
to add-l${stdenv.cc.libcxx.cxxabi.libName}
automatically. That way, if there's a bug it can be fixed in one place instead of having to make thirty-three different changes, like these:* [34c3989](https://github.com/NixOS/nixpkgs/commit/34c3989a0e8ce395a6b28397848ee07eade3509e) * [895dbe8](https://github.com/NixOS/nixpkgs/commit/895dbe8aa68b373c2c033a4c627d4f5b13da7e24) * [9d96656](https://github.com/NixOS/nixpkgs/commit/9d966564329d31c23301d2517dc999858a704b04) * [caab415](https://github.com/NixOS/nixpkgs/commit/caab4159953f2bb254602cca50fc89f28703fed1) * [1bb69e8](https://github.com/NixOS/nixpkgs/commit/1bb69e8dfd520cf5b513699b5043dccc35ed09f4) * [8670f50](https://github.com/NixOS/nixpkgs/commit/8670f502d0d19b68c617dd42539df1b9605e2486) * [ad34020](https://github.com/NixOS/nixpkgs/commit/ad340203577eb36090b1afce7ec9c4fc15dff41d) * [eca13b3](https://github.com/NixOS/nixpkgs/commit/eca13b37fd12f76a9f261427415fbc222423f4f5) * [0917ca9](https://github.com/NixOS/nixpkgs/commit/0917ca9988103ef0abef67c1715360b1c368d4dd) * [587ee6e](https://github.com/NixOS/nixpkgs/commit/587ee6e31b0a0c14d8da07d516f0bb9cfe792ddf) * ... and on, and on ...
@amjoseph-nixpkgs thats a very good find ! we should fix it, is it darwin specific ?
Hi! This hits internal users where I work about once a week, as they add a native library and have to add this override. By and large, they are unfamiliar with the peculiarities of the linker, and the errors we get are strange as they usually reference other libraries, which is a red herring.
Is there some path to a default fix for this problem? From the above, there are a lot of workarounds being exported (which we apply internally), but there's no direct proposal for an override fix (adding the same override to ld-wrapper?).
Is it reasonable to (internally) automatically apply something which adds this linker flag to everything?
Is there some path to a default fix for this problem? From the above, there are a lot of workarounds being exported (which we apply internally), but there's no direct proposal for an override fix (adding the same override to ld-wrapper?).
the change still needs to go through the review processes.
Problem
When using
stdenv
s (or even justlibc++
versions, really) fromllvmPackages
corresponding to LLVM 12 and newer on macOS, symbols related to exceptions (such as__cxa_allocate_exception
) are not found by the linker.This can be reproduced by compiling and linking any C++ program that makes use of exceptions, i.e.:
Results in:
Comparing the
libc++
dylibs used by the wrappedclang++
in the LLVM 12 and 13stdenv
s (i.e.llvmPackages_12.libcxxStdenv
) to that used in the LLVM 11stdenv
reveals that while LLVM 11'slibc++.dylib
reexports such symbols, newerlibc++.dylib
s do not.When run through
llvm-nm -C
and grepped for__cxa_allocate_exception
, here is the output for LLVM 11'slibc++
dylib:And LLVM 13's:
Both of these
libc++
dylibs have a dynamic dependency onlibc++abi
which actually provides a definition for this symbol (this can be observed withotool -L <dylib path>
which shows thelibc++abi.dylib
dep and thenllvm-nm -C <libc++abi.dylib path>
which shows that the symbol is defined in thelibc++abi
dylib) however onlylibc++
versions prior to LLVM 12's reexport the symbol.This is consistent with the
libc++
source code. These symbols were initially removed from the main list of symbols reexported and gated onlibc++
exception support. However later this logic and the special list of symbols was removed.Open Questions
I am not certain I understand the changes in the commit linked above; it's not clear to me why
libcxxabi
was changed to reexport these symbols.This seems like an ABI break but there is no mention of this being potentially problematic on the CL and the comments added to the changelog in this commit seem to insist that it only adds some reexports to
libc++
.Potential Solutions
I am not sure what the "right" solution is but anecdotally it seems like it's common to pass in
-lc++abi
as a linkopt on macOS.cc-wrapper
already does this on Linux.To Reproduce
Here's a flake:
Running
nix flake check
shows the error when compiling with the LLVM 12 and 13stdenv
s; entering the dev shells withnix develop
prints the path of thelibc++
dylib that's used and greps it for__cxa_allocate_exception
(one of the missing symbols).The above also contains an example of a workaround that adds
-lc++abi
to the wrapper used in the LLVM 13stdenv
.I think this is reproducible with any nixpkgs version after the LLVM 12.0.0 package was added but just in case, here's my flake.lock file:
Click to expand
```json { "nodes": { "flake-utils": { "locked": { "lastModified": 1648297722, "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=", "owner": "numtide", "repo": "flake-utils", "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade", "type": "github" }, "original": { "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "nixpkgs": { "locked": { "lastModified": 1648219316, "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "nixos", "repo": "nixpkgs", "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { "owner": "nixos", "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, "root": { "inputs": { "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } } }, "root": "root", "version": 7 } ```