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

ld-wrapper: Optimize expanding rpath #27657

Merged
merged 1 commit into from
Jul 31, 2017
Merged

Conversation

orivej
Copy link
Contributor

@orivej orivej commented Jul 26, 2017

Motivation for this change

The time to expand rpath was proportional to the number of -L flags times the number of -l flags. This change makes it proportional to their sum (assuming constant number of files in each directory in an -L flag).

Issue reported by @nh2 at #27609 (comment)

I'm going to test this soon.

Things done

Please check what applies. Note that these are not hard requirements but mereley serve as information for reviewers.

  • Tested using sandboxing
    (nix.useSandbox on NixOS,
    or option build-use-sandbox in nix.conf
    on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • Linux
  • 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.

@orivej
Copy link
Contributor Author

orivej commented Jul 26, 2017

Tested building nix-unstable as described in #27609 (comment)

@joachifm
Copy link
Contributor

Relying on nullglob is even simpler.

@orivej
Copy link
Contributor Author

orivej commented Jul 26, 2017

Thanks for the suggestions!

When cd is successful, it records the previous directory in $OLDPWD, and cd - is equivalent to cd "$OLDPWD". But I guess that pushd is more obvious, so I changed cd to pushd/popd.

Associative array libs may only contain entries that start with lib and end with .so, so dotglob which also matches files that start with . and nullglob that prevents expansion of * into * in an empty directory are not relevant.

@orivej orivej force-pushed the optimize-rpath branch 2 times, most recently from e2a8520 to 8b129a2 Compare July 26, 2017 17:34
@orivej
Copy link
Contributor Author

orivej commented Jul 26, 2017

This:

        for file in "$dir"/*; do
            if [ "${libs[${file##*/}]}" ]; then

turned out to be even faster than this

        pushd "$dir" &>/dev/null || continue
        for file in *; do
            if [ "${libs[$file]}" ]; then

so I updated the pull request (and also replaced * with lib*.so).

@orivej
Copy link
Contributor Author

orivej commented Jul 26, 2017

I have added shopt -s nullglob at the beginning of ld-wrapper.sh because after the previous change our wrapper will behave incorrectly if someone ran ld with the flags -l '*'. (Although I have not checked that other parts of the wrapper support this :) )

@joachifm
Copy link
Contributor

The for dir/lib*.so is what "relying on nullglob" implies ... I suppose you can always restore its previous state afterwards, to be maximally conservative.

@orivej
Copy link
Contributor Author

orivej commented Jul 26, 2017

Yes, thank you for bringing up nullglob. It is better enabled at the beginning and never disabled, for sanity.

I've tested building nixUnstable with the current pull request.

if [ -f "$i/lib$j.so" ]; then
addToRPath $i
for dir in "${libDirs[@]}"; do
for file in "$dir"/lib*.so; do
Copy link
Member

Choose a reason for hiding this comment

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

wait, how the hell have we been hard-coding .so on Darwin?! CC @copumpkin

addToRPath $i
for dir in "${libDirs[@]}"; do
for file in "$dir"/lib*.so; do
if [ "${libs[${file##*/}]}" ]; then
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible for file to bind a path with a trailing slash?

Copy link
Member

Choose a reason for hiding this comment

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

Above you mention "$dir"/*, but then you changed * to lib*.so, so I think it's not needed anymore.

Copy link
Contributor

Choose a reason for hiding this comment

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

What is not needed anymore? I take it the idea here is to establish a basename => dir mapping, whereas the generated items will contain the dir so you need to take the basename (aka ${file##*/}).

Copy link
Member

Choose a reason for hiding this comment

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

Oh right, pruning the dirname, duh.

Copy link
Contributor Author

@orivej orivej Jul 26, 2017

Choose a reason for hiding this comment

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

file must end with .so so it can not end with /, even if lib*.so is a directory, which is not necessary to support, and testing if an entry is a file or a directory is slow.

${file##*/} is needed to take the basename of the file because libs contains only file names and dir/lib*.so returns dir/liba.so, dir/libb.so, etc.; calling basename $file here is too slow since basename is not a bash builtin.

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 you meant that the whole conditional if [ "${libs[${file##*/}]}" ] should be removed, it is not the case because the main purpose of this loop is to filter out directories with libraries none of which are needed.

Copy link
Member

Choose a reason for hiding this comment

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

@orivej I just forgot that the expanded glob would include the dirname; simple as that 😊.

@orivej
Copy link
Contributor Author

orivej commented Jul 26, 2017

I have replaced

                addToRPath "$dir"
                break

with

                addToRPath "$dir"
                libs["$file"]=

because we do not want to add a directory for a library provided by a previous directory. addToRPath prevents duplicates. libs["$file"]= is instantaneous, whereas unset libs["$file"] takes noticeable time.

@orivej
Copy link
Contributor Author

orivej commented Jul 26, 2017

After the last change, if there are both /tmp/liba.so and /nix/store/xxx/lib/liba.so and the linker is invoked as ld -L/tmp -L/nix/store/xxx/lib -la, it will no longer add /nix/store/xxx/lib to rpath. Should it?

@Ericson2314
Copy link
Member

Ericson2314 commented Jul 26, 2017

@orivej thanks for this; with all the recent improvements, ld-wrapper has never looked better! This is purely cosmetic, but it would be nice to also turn the elif chain into a case with glob patterns (-L/* for example). Happy to do that in a follow-up PR, though.

@orivej orivej force-pushed the optimize-rpath branch 2 times, most recently from 6b7552d to 7ae3d26 Compare July 26, 2017 21:03
@orivej
Copy link
Contributor Author

orivej commented Jul 26, 2017

@Ericson2314 Good idea! Done.

@nh2 I have removed the piece of allParams loop that was quadratic in the number of parameters:

-            rest=("${rest[@]}" "$p")
+            rest+=("$p")

This shoud take care of the last 1/3 second you observed in #27609 (comment)

Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

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

More style nice-to-haves, but don't worry.

# to add the dynamic linker path to rpath.
n=$((n + 1))
;;
[^-]*.so | [^-]*.so.*)
Copy link
Member

Choose a reason for hiding this comment

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

Would ? in [^-]*.so | [^-]*.so.? replicate the original regex more accurately?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it captures libraries with versions longer than one character, like libavformat.so.57.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I misread the original regex.

# First, find all -L... switches.
allParams=("${params[@]}" ${extra[@]})
nParams=${#allParams[@]}
n=0
Copy link
Member

Choose a reason for hiding this comment

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

declare -i n=0 I think will allow one to... [see below]

case "$p" in
-L)
addToLibPath "${p2}"
n=$((n + 1))
Copy link
Member

Choose a reason for hiding this comment

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

...make these n+=1 or let ++n. (Do ++n not n++ or risk a non-0 exit status---that bit me recently.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great, thanks! Done.

@orivej orivej force-pushed the optimize-rpath branch 2 times, most recently from 19a1698 to 2533ffe Compare July 26, 2017 23:19
@edolstra
Copy link
Member

After the last change, if there are both /tmp/liba.so and /nix/store/xxx/lib/liba.so and the linker is invoked as ld -L/tmp -L/nix/store/xxx/lib -la, it will no longer add /nix/store/xxx/lib to rpath. Should it?

I think so, yes. IIRC this pattern does occur in practice.

@domenkozar domenkozar merged commit 61b5b7f into NixOS:staging Jul 31, 2017
@orivej orivej deleted the optimize-rpath branch July 31, 2017 21:35
@FRidh
Copy link
Member

FRidh commented Aug 1, 2017

This breaks the building of which on staging.
https://nix-cache.s3.amazonaws.com/log/5i4cra7k0gxdkj38ngwjrnv018yrvqx8-xz-5.2.3.drv

XZ Utils 5.2.3

System type:
checking whether we are cross compiling... configure: error: in `/build/which-2.21':
configure: error: cannot run C compiled programs.
If you meant to cross compile, use `--host'.
See `config.log' for more details
builder for ‘/nix/store/sjmpwmqfz580hnw7ymhf44bklbm5jxc6-which-2.21.drv’ failed with exit code 1

Or is it due to a bug in one of the earlier cross compiling commits?

@orivej
Copy link
Contributor Author

orivej commented Aug 1, 2017

The cause of this is that glibc-2.25/lib/ld-linux-x86-64.so.2 has non empty RUNPATH. (I don't know yet why.)

@orivej
Copy link
Contributor Author

orivej commented Aug 1, 2017

#27831 fixes this.

@globin
Copy link
Member

globin commented Aug 7, 2017

Currently a lot of Qt apolications/libraries aren't building because of linker errors that as far as I can tell are a result of this PR: https://hydra.nixos.org/build/58122426

/nix/store/q40qqjwdvhazcbji0gpi9r00apbywfcx-binutils-2.29/bin/ld: warning: libQt5Widgets.so.5, needed by ../../libKF5IdleTime.so.5.36.0, not found (try using -rpath or -rpath-link)

If I run the build with NIX_DEBUG=1 it works, but I've found some weird output (note the multiple : after -rpath):

original flags to /nix/store/hbk91shlri5bsd5skfw3xp22f2i5ka65-binutils-2.29/bin/ld:
  -plugin
  /nix/store/7lwd7p6qdqmv02bijihnyx3hjdz3rksg-gcc-5.4.0/libexec/gcc/x86_64-unknown-linux-gnu/5.4.0/liblto_plugin.so
  -plugin-opt=/nix/store/7lwd7p6qdqmv02bijihnyx3hjdz3rksg-gcc-5.4.0/libexec/gcc/x86_64-unknown-linux-gnu/5.4.0/lto-wrapper
  -plugin-opt=-fresolution=/tmp/nix-build-kidletime-5.36.0.drv-0/ccmdwUUE.res
  -plugin-opt=-pass-through=-lgcc_s
  -plugin-opt=-pass-through=-lc
  -plugin-opt=-pass-through=-lgcc_s
  --eh-frame-hdr
  -m
  elf_x86_64
  -shared
  -o
  libKF5IdleTime.so.5.36.0
  -z
  relro
  -z
  now
  /nix/store/lg62hfq1py4vj3z5bx047qkwrdlf9xwd-glibc-2.25/lib/crti.o
  /nix/store/7lwd7p6qdqmv02bijihnyx3hjdz3rksg-gcc-5.4.0/lib/gcc/x86_64-unknown-linux-gnu/5.4.0/crtbeginS.o
  -L/nix/store/rd1c7fqkahw8qy26ry16xbhw35kqqwwl-qtx11extras-5.9.0-dev/lib
  -L/nix/store/2c0fp6iic5kb4i2c11cdxwrmfk2pf1x8-qtbase-5.9.0-bin/lib
  -L/nix/store/l09c9ca54y3jm3xrm6i6xzcf7xh0ij6f-qtbase-5.9.0-dev/lib
  -L/nix/store/14mj955fkp7963lh565zgkfxh0zb4d2k-libxml2-2.9.4-dev/lib
  -L/nix/store/lp7cgrh2sp1sx5znqna5xckxqmxx8bsd-zlib-1.2.11-dev/lib
  -L/nix/store/b8ggrwi9iyglipnl0gpplyl8jlcmqh65-zlib-1.2.11/lib
  -L/nix/store/bdcmybjvb4cik22a8d00c9sshiia98w9-libxml2-2.9.4/lib
  -L/nix/store/xnhll4lfnzhzm0bvmv2d7gixb6yl2d03-libxml2-2.9.4-py/lib
  -L/nix/store/f21rn3myw422a2jphlnaznrisrj3c93q-libxslt-1.1.29-dev/lib
  -L/nix/store/x76rsha12v0fcw77d4ancnqm0189rswv-libxslt-1.1.29/lib
  -L/nix/store/2kq2cpkdlhbdspjcim6mgnzswh8x5bw5-openssl-1.0.2l-dev/lib
  -L/nix/store/n6b93ah4l53gg5dr28hjc050fan4lf8b-openssl-1.0.2l/lib
  -L/nix/store/4nshf989iiq62b2c26sa91s5bbkwdfdf-pcre2-10.23-dev/lib
  -L/nix/store/s7bvbwnqgn3dkzdxs0g0rdsc22i1zpxw-pcre2-10.23/lib
  -L/nix/store/2zx8lrlrwzwcasyxasbw82lvslxw62di-sqlite-3.19.3-dev/lib
  -L/nix/store/is98y793hwa3ynpmssc4nnz7b2v6n65v-sqlite-3.19.3/lib
  -L/nix/store/1f0gaf736pqsgvrnprg9llqy9gdr4b6n-harfbuzz-icu-1.4.6-dev/lib
  -L/nix/store/8lpcb61yqzmi3ccw93qylx60i2923vv2-graphite2-1.3.6/lib
  -L/nix/store/qls10j926wfr4m9nbipfggb8zsma9pzs-icu4c-58.2-dev/lib
  -L/nix/store/d7wkfhkmx3qsgxvk1gds74jxdbby6w2c-icu4c-58.2/lib
  -L/nix/store/bkj1j7345h7qmvakcy6yvrfm3ji8a4iz-harfbuzz-1.4.6-dev/lib
  -L/nix/store/q7sjhg35010hl723j52y99qgjpff3g0q-harfbuzz-1.4.6/lib
  -L/nix/store/9c4x9xaf0jh2wjhfaaj3yb8yv99sswq3-harfbuzz-icu-1.4.6/lib
  -L/nix/store/rs36fqg03nsbal19h8vdyci6a72cnczm-libjpeg-turbo-1.5.2-dev/lib
  -L/nix/store/sd8bkfqzm613mp3lmjsi96hq9689dwmc-libjpeg-turbo-1.5.2/lib
  -L/nix/store/kcn7b327jay5ks9kwb9gl4dsd00yqqrl-libpng-apng-1.6.31-dev/lib
  -L/nix/store/irmmvxhn6rd7df5cw3kxvixdwiwbpx14-libpng-apng-1.6.31/lib
  -L/nix/store/gjb3mzr2cnpm0bdcskfvkqygnqbrf538-libtiff-4.0.8-dev/lib
  -L/nix/store/h76gyjkkniiqz8qz05s3wg7jbzmbijxi-xz-5.2.3-dev/lib
  -L/nix/store/avbll1r13jfg21pxac8chrwsf4vfjmbx-xz-5.2.3/lib
  -L/nix/store/i088psv913xl9y9c7m9kvk7hf8dwfrqm-libtiff-4.0.8/lib
  -L/nix/store/9rxv1clc2wmp69lh5zyfvqjp6vmmsykl-mesa-noglu-17.1.5-dev/lib
  -L/nix/store/0x5v9qx1l2xspbkpay5fipc0wwl0r6x4-libXdamage-1.1.4-dev/lib
  -L/nix/store/0ar1ivn3j4kmml1d3iqwj1kvxpbyi66g-xproto-7.0.31/lib
  -L/nix/store/v94p23246ip9vsnrl6nnfc8628hqdvkx-damageproto-1.2.1/lib
  -L/nix/store/bsqcn6vd9smpg1bvnysjcsaqclaih205-libXfixes-5.0.2-dev/lib
  -L/nix/store/xcwfvphqgb7lvn6zgc8khxb2a3vhcgwp-fixesproto-5.0/lib
  -L/nix/store/9dkzs75rcj8v2zpd5aak2xr7kpv58rnr-xextproto-7.3.0/lib
  -L/nix/store/wvpb69a8bq460sn43mg95cz7a0jci7yz-libXfixes-5.0.2/lib
  -L/nix/store/c00jq0ji3hnp7i8pbvalbbkpxzz1qsyx-libXdamage-1.1.4/lib
  -L/nix/store/xq20js0rwxrly0w0fg8vrhyg2k9yzqnb-libXxf86vm-1.1.4-dev/lib
  -L/nix/store/8c29ki77lnlqf3ywq7k1vwhm8d9wc8v0-xf86vidmodeproto-2.3.1/lib
  -L/nix/store/23b83j4cmm31p230z785rzbz2q6nhxpv-libXxf86vm-1.1.4/lib
  -L/nix/store/0imggm633jmig2px3xac1fr24bsc997a-libdrm-2.4.81-dev/lib
  -L/nix/store/r5lpvphh5yq5m9mbk9281gsf29k4zgq9-libdrm-2.4.81/lib
  -L/nix/store/z2i9in9xzn88hcj2wabq1zm83y5x4cyy-mesa-noglu-17.1.5/lib
  -L/nix/store/5drzkxypzka63z4wsjn8dylkcw6v555b-dbus-1.10.20-dev/lib
  -L/nix/store/sigy70csv9nf877vcv2i1z07qbi4b96p-expat-2.2.2-dev/lib
  -L/nix/store/9j2rdjg5pqcj9rzzv0cjm6yny00c2jq2-expat-2.2.2/lib
  -L/nix/store/6w1lvshhr4g316cnj2iwifdz0zhqgaq8-dbus-1.10.20-lib/lib
  -L/nix/store/bk5xhh71difib2wx60vzw4n377ig9x95-glib-2.52.1-dev/lib
  -L/nix/store/yj1kyhlhcll1i7gpk26l05gpa8d32d4d-libffi-3.2.1-dev/lib
  -L/nix/store/421xz93i6a7aawwil1vbvncd62y372vm-libffi-3.2.1/lib
  -L/nix/store/hiw7r69bf4fb66yd22msnc4r5h100x9c-glib-2.52.1/lib
  -L/nix/store/i8miv8skbab7a5z5hnfpf5i6k3xp72vf-systemd-234-dev/lib
  -L/nix/store/2x474225q80a5r4nyngfyv61svh0cpd7-systemd-234-lib/lib
  -L/nix/store/2y1k2qpaxr3c43d37yvm19k7j3k6j1jw-systemd-234/lib
  -L/nix/store/17rp8319i2vkmld4vv162hvaa2chqmhq-fontconfig-2.12.1-dev/lib
  -L/nix/store/h7hbs4z08gsp6qc8lbk5lwiky9sg5mfh-freetype-2.7.1-dev/lib
  -L/nix/store/i9az7fzzz4qh04qcpiyhfvbf7pli11gj-bzip2-1.0.6.0.1-dev/lib
  -L/nix/store/gghl22ad050z6gp4082pb3bk3803x64d-bzip2-1.0.6.0.1/lib
  -L/nix/store/889mijcp37wgg6f7xarazjfi49jkghr6-freetype-2.7.1/lib
  -L/nix/store/7k6zpi4rh4insdb4ss21rif4lf7x2i92-fontconfig-2.12.1-lib/lib
  -L/nix/store/1vrc45x4r8676rhr1b94jxkzrzhxxcvl-libX11-1.6.5-dev/lib
  -L/nix/store/734dl5106jnfjv9gg63rh604imylivvf-libxcb-1.12-dev/lib
  -L/nix/store/ilv52g1x21v4lbbj4q5hc6fc96cmcd5k-libxcb-1.12/lib
  -L/nix/store/q2f30adk8ly08d7g6h6pzl5p94py1c6m-kbproto-1.0.7/lib
  -L/nix/store/k2dl2c8hz8w1c5hcrl5ihfx1j6zhjcv1-libX11-1.6.5/lib
  -L/nix/store/mmxi6y3jmrijddiz8l3vkvha8cnhr46n-libXcomposite-0.4.4-dev/lib
  -L/nix/store/xv8iq64lq5f9xsrbjgz8hl06c1c022hr-compositeproto-0.4.2/lib
  -L/nix/store/4ji7fdvn1fab7j8dvkw21s10libdkrjw-libXcomposite-0.4.4/lib
  -L/nix/store/k8yw8nwsyx1lqilwgdf8v4m4af43hz28-libXext-1.3.3-dev/lib
  -L/nix/store/niypknsyf2s6zicrapq0z1f6mc5p4pjw-libXau-1.0.8-dev/lib
  -L/nix/store/2gch74ap1xkn5ibkaskh36zl4wmacpg4-libXau-1.0.8/lib
  -L/nix/store/gf1qp5ns5qsbpsdxq54bcazsr3bfym8m-libXext-1.3.3/lib
  -L/nix/store/hrzvgy395dvbm83rxdz0clmaz4hz7v3j-libXi-1.7.9-dev/lib
  -L/nix/store/njlwal6bd55x7r1n1dm48i4mjnn5rqk0-inputproto-2.3.2/lib
  -L/nix/store/zcf1qpafhqc3d7crxdspaa3sdqzh8bhh-libXi-1.7.9/lib
  -L/nix/store/6risyn99rh4827anhwf8hmbv9papgk09-libXrender-0.9.10-dev/lib
  -L/nix/store/9zjw5i0j6i019s2mqg485md28iwbwv65-renderproto-0.11.1/lib
  -L/nix/store/9zjw5i0j6i019s2mqg485md28iwbwv65-renderproto-0.11.1/lib
  -L/nix/store/cdpbkp5mzvvwdw28w3fb4c9m3d09jyxs-libXrender-0.9.10/lib
  -L/nix/store/c81d5hw9s7cfp97xpk4hg6vy3hfkw93c-libxkbcommon-0.7.1-dev/lib
  -L/nix/store/g3sriw6am2654wbp4q0xim26s766c64k-libxkbcommon-0.7.1/lib
  -L/nix/store/a2mfg3l856y0l752nyfcrgsvg645g7dx-xcb-util-0.4.0-dev/lib
  -L/nix/store/g4y7hcc9378jkac139fmd45qgdf0xcl6-xcb-util-0.4.0/lib
  -L/nix/store/bbzgg5i6is2wr9cngpcm4b13z7b7ny5f-xcb-util-image-0.4.0-dev/lib
  -L/nix/store/w0cwq15ddl13sppp5qnhfr1llpyf62yj-xcb-util-image-0.4.0/lib
  -L/nix/store/m4grnb6by1mp1f1xg3y64l0dmc6vab3r-xcb-util-keysyms-0.4.0-dev/lib
  -L/nix/store/y980g80b17clxfpq6xh8lcjkh10n9sw2-xcb-util-keysyms-0.4.0/lib
  -L/nix/store/3rdawm8f5dk2243s7qja7jyhm2vgrhhs-xcb-util-renderutil-0.3.9-dev/lib
  -L/nix/store/kvg0rn34k9lcwb7fpi587dddmj1hja2m-xcb-util-renderutil-0.3.9/lib
  -L/nix/store/h4why5f4vdgfmdnsqdhi6r7ys7ncxssl-xcb-util-wm-0.4.1-dev/lib
  -L/nix/store/87b8qjmdi90hrhrz3iiq6q0rmbhg65xz-xcb-util-wm-0.4.1/lib
  -L/nix/store/c3p2pavk16qs9v3pxhy8zj7qpmcdg713-qtbase-5.9.0/lib
  -L/nix/store/8009ysmc633vzjhg4ygbmw9zhw9g67rg-qtx11extras-5.9.0/lib
  -L/nix/store/lg62hfq1py4vj3z5bx047qkwrdlf9xwd-glibc-2.25/lib
  -L/nix/store/dwnan1p2iqs9g6kkv32x4p1qzwknpb55-gcc-5.4.0-lib/lib
  -L/nix/store/dwnan1p2iqs9g6kkv32x4p1qzwknpb55-gcc-5.4.0-lib/lib
  -L/nix/store/lg62hfq1py4vj3z5bx047qkwrdlf9xwd-glibc-2.25/lib
  -L/nix/store/6bf68cqvdjwmhiz9ils2fz7biw8qvg3p-gcc-wrapper-5.4.0/bin
  -L/nix/store/7lwd7p6qdqmv02bijihnyx3hjdz3rksg-gcc-5.4.0/lib/gcc/x86_64-unknown-linux-gnu/5.4.0
  -L/nix/store/7lwd7p6qdqmv02bijihnyx3hjdz3rksg-gcc-5.4.0/lib/gcc/x86_64-unknown-linux-gnu/5.4.0/../../../../lib64
  -L/nix/store/7lwd7p6qdqmv02bijihnyx3hjdz3rksg-gcc-5.4.0/lib/gcc/x86_64-unknown-linux-gnu/5.4.0/../../..
  -dynamic-linker
  /nix/store/lg62hfq1py4vj3z5bx047qkwrdlf9xwd-glibc-2.25/lib/ld-linux-x86-64.so.2
  --no-undefined
  --fatal-warnings
  --enable-new-dtags
  -soname
  libKF5IdleTime.so.5
  CMakeFiles/KF5IdleTime.dir/logging.cpp.o
  CMakeFiles/KF5IdleTime.dir/kidletime.cpp.o
  CMakeFiles/KF5IdleTime.dir/abstractsystempoller.cpp.o
  CMakeFiles/KF5IdleTime.dir/widgetbasedpoller.cpp.o
  CMakeFiles/KF5IdleTime.dir/KF5IdleTime_autogen/moc_compilation.cpp.o
  -rpath
  :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  /nix/store/c3p2pavk16qs9v3pxhy8zj7qpmcdg713-qtbase-5.9.0/lib/libQt5Widgets.so.5.9.0
  /nix/store/c3p2pavk16qs9v3pxhy8zj7qpmcdg713-qtbase-5.9.0/lib/libQt5Gui.so.5.9.0
  /nix/store/c3p2pavk16qs9v3pxhy8zj7qpmcdg713-qtbase-5.9.0/lib/libQt5Core.so.5.9.0
  -rpath-link
  /nix/store/z2i9in9xzn88hcj2wabq1zm83y5x4cyy-mesa-noglu-17.1.5/lib
  -rpath
  /nix/store/xvkr0spbyzs1nfc22sraaha6s5vn1vbj-kidletime-5.36.0/lib64
  -rpath
  /nix/store/xvkr0spbyzs1nfc22sraaha6s5vn1vbj-kidletime-5.36.0/lib
  -lstdc++
  -lm
  -lgcc_s
  -lc
  -lgcc_s
  /nix/store/7lwd7p6qdqmv02bijihnyx3hjdz3rksg-gcc-5.4.0/lib/gcc/x86_64-unknown-linux-gnu/5.4.0/crtendS.o
  /nix/store/lg62hfq1py4vj3z5bx047qkwrdlf9xwd-glibc-2.25/lib/crtn.o
extra flags to /nix/store/hbk91shlri5bsd5skfw3xp22f2i5ka65-binutils-2.29/bin/ld:
  -z
  relro
  -z
  now
  -rpath
  /nix/store/lg62hfq1py4vj3z5bx047qkwrdlf9xwd-glibc-2.25/lib
  -rpath
  /nix/store/dwnan1p2iqs9g6kkv32x4p1qzwknpb55-gcc-5.4.0-lib/lib

cc @orivej @Ericson2314

@FRidh
Copy link
Member

FRidh commented Aug 7, 2017

I tracked an issue with Qt on staging (#27975) down to #27879.

@globin
Copy link
Member

globin commented Aug 7, 2017

Hmm, but I get that error on master and that PR is currently only in staging.

EDIT: Ah, you've just merged that commit, but I was experiencing the error before that.

@orivej
Copy link
Contributor Author

orivej commented Aug 7, 2017

@globin I can not reproduce this error on master, kdeFrameworks.kidletime builds fine. You linked to a hydra job failing on staging.

@domenkozar
Copy link
Member

It could be a bug in #27831

@globin
Copy link
Member

globin commented Aug 7, 2017

Definitely occuring for me on master..

...
error: build of ‘/nix/store/4nmmzacmpv9ny7f3hasgp47is0s0ynkh-kidletime-5.36.0.drv’ failed
 ✘  ~/d/nixpkgs-upstream # git rev-parse HEAD
2203908e5fa7529183f43b6a9e7e11559b1fcde6

@globin
Copy link
Member

globin commented Aug 7, 2017

And here the failing build of kidletime on master on hydra:
https://hydra.nixos.org/build/58115802

@Ericson2314
Copy link
Member

If there's one thing I've learned lately, to play with cc-wrapper is to play with fire!

@orivej
Copy link
Contributor Author

orivej commented Aug 7, 2017

@globin This is a bug in ld-wrapper.sh: direct references to libraries with names that do not match lib*.so, such as in ld … /nix/store/…-qtbase-5.9.1/libQt5Widgets.so.5.9.1, do not affect rpath. Here is a possible patch:

-        for path in "$dir"/lib*.so; do
+        for path in "$dir"/*.so*; do

Should it go to staging or to master?

@FRidh
Copy link
Member

FRidh commented Aug 7, 2017

@orivej staging

@globin
Copy link
Member

globin commented Aug 7, 2017

I'll test and fix this on staging

@orivej
Copy link
Contributor Author

orivej commented Aug 8, 2017

If I run the build with NIX_DEBUG=1 it works, but I've found some weird output (note the multiple : after -rpath)

This is used by cmake to edit rpath:

  foreach(file
      "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libKF5IdleTime.so.5.36.0"
      "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libKF5IdleTime.so.5"
      "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/libKF5IdleTime.so"
      )
    if(EXISTS "${file}" AND
       NOT IS_SYMLINK "${file}")
      file(RPATH_CHANGE
           FILE "${file}"
           OLD_RPATH "::::::::::::::::::::"
           NEW_RPATH "/var/empty/local/lib")
      if(CMAKE_INSTALL_DO_STRIP)
        execute_process(COMMAND "/nix/store/d8dsyi10qz3dg7vlnrf2k44bs2yk0945-binutils-2.29/bin/strip" "${file}")
      endif()
    endif()
  endforeach()

https://gitlab.kitware.com/cmake/cmake/blob/b17b6dbb/Source/cmInstallTargetGenerator.cxx#L745
https://gitlab.kitware.com/cmake/cmake/blob/b17b6dbb/Source/cmComputeLinkInformation.cxx#L1842

-l?*)
libs["lib${p:2}.so"]=1
;;
"$NIX_STORE"/*.so | "$NIX_STORE"/*.so.*)
Copy link
Member

Choose a reason for hiding this comment

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

@orivej It just occurred to me, say somebody does $LD ... -o $out/lib/asdf.so? Should we check that [[ $prev != -* ]]?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Some options do not require an argument, so this check would be incorrect. The idea behind the current option parser is that the path after -o and possibly other options, except -dynamic-linker and -plugin, can not start with $NIX_STORE and will not be added to rpath. Only when ld is invoked outside nix-build environment where $NIX_STORE is unset ld may add extra rpaths. This is worth fixing by adding -o alongside -plugin above.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm true.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But I'm wrong in thinking that $out does not start with $NIX_STORE. I'll ignore the argument after -o in the next pull request for #28021 (comment)

@nh2
Copy link
Contributor

nh2 commented Aug 17, 2017

I have now found how I can backport this fix to release-17.03 and use it in my Haskell build only (without cherry-picking the fix to avoid having to rebuild the world):

First define

customLdWrapper = pkgs.stdenv.mkDerivation {
  name = "custom-ld-wrapper";

  # The wrapper scripts use 'cat' and 'grep', so we may need coreutils.
  # The variable being set here exposes it as a bash variable
  # in `buildCommand`, where `substituteAll` will pick it up.
  coreutils_bin = pkgs.lib.getBin pkgs.coreutils;

  buildCommand = let ldWrapperPath = ./fast-ld-wrapper.sh; in ''
    mkdir -p $out/bin $out/nix-support

    wrap() {
      local dst="$1"
      local wrapper="$2"
      export prog="$3"
      substituteAll "$wrapper" "$out/bin/$dst"
      chmod +x "$out/bin/$dst"
    }

    wrap ld.gold ${ldWrapperPath} ${pkgs.lib.getBin pkgs.binutils}/bin/ld.gold
  '' +
  # We need all the files available that the real wrapper has, so we copy them over.
  ''
    cp -r ${pkgs.gcc}/nix-support $out
  '';
};

where fast-ld-wrapper.sh is the fixed version of the wrapper as provided in this PR.

But it turns out it is not enough to just put this package into buildInputs to have it on the PATH; my gcc will not use it, because collect2 will set COMPILER_PATH to a path that contains the original gcc-wrapper and that takes precedence.

I had to pass it as -optl-B/nix/store/...custom-ld-wrapper-.../bin to ghc, and did that this way:

preConfigure = ''
  export FIXED_LD_WRAPPER_PATH=${pkgs.customLdWrapper}/bin
'';

# So that it also works in a cabal/Setup.hs build in nix-shell
shellHook = ''
  export FIXED_LD_WRAPPER_PATH=${pkgs.customLdWrapper}/bin
'';

and then define a custom Setup.hs:

import Distribution.Simple
import Distribution.Simple.Setup
import Distribution.Simple.LocalBuildInfo (extraConfigArgs, configFlags)
import System.Environment (lookupEnv)
main = defaultMainWithHooks simpleUserHooks{
  confHook = \(genericPackageDescription, hookedBuildInfo) hookConfigFlags -> do
     -- TODO Remove this, the customLdWrapper nix derivation and
     --      all occurrences of FIXED_LD_WRAPPER_PATH once we are
     --      on nixpkgs 17.09.
     maybeLdPath <- lookupEnv "FIXED_LD_WRAPPER_PATH"
     let patchedConfigFlags = case maybeLdPath of
           Nothing -> hookConfigFlags
           Just path -> hookConfigFlags{ configProgramArgs = prependIfNotPresent ("ghc", ["-optl-B" ++ path]) (configProgramArgs hookConfigFlags) }
             where
               prependIfNotPresent :: (Eq a) => a -> [a] -> [a]
               prependIfNotPresent x xs = if x `elem` xs then xs else x:xs
     localBuildInfo <- (confHook simpleUserHooks) (genericPackageDescription, hookedBuildInfo) patchedConfigFlags
     putStrLn $
       "Setup.hs: Adding flag to tell GHC to use fixed nix gold ld-wrapper; configure arguments are: "
       ++ show (configProgramArgs $ configFlags localBuildInfo)
     return localBuildInfo
}

and set build-type: Custom in the .cabal file.

That sped up my nix-build by factor 2x.

@vcunat
Copy link
Member

vcunat commented Aug 19, 2017

You could also override the whole cc-wrapper part only for the packages that you care for, i.e. build only those with a stdenv containing the modified wrapper.

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