macOS binary with hardcoded library path

Trying to write a derivation for the JLink tools.

The big challenge is it seems to have the path to its own dylib hardcoded. The error:

$ JlinkExe                                                                                                                                                                                                                                                                                                                                       /nix/store/pw787fdb2ral61jc84gvl68i3j7y9xrw-jlink/lib
SEGGER J-Link Commander V6.94d (Compiled Feb 12 2021 15:53:12)
Could not open J-Link shared library. Exiting now.

Running strings:

$ strings $(which JLinkExe) | grep Applications                                                                                                                                                                                                                                                                                            /nix/store/pw787fdb2ral61jc84gvl68i3j7y9xrw-jlink/lib

Running otool:

$ otool -L $(which JLinkExe)                                                                                                                                                                                                                                                                                                               /nix/store/pw787fdb2ral61jc84gvl68i3j7y9xrw-jlink/lib
        /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1770.106.0)
        /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.0.0)
        /usr/lib/libedit.3.dylib (compatibility version 2.0.0, current version 3.0.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 904.4.0)

What I’ve tried:

preFixup = ''
    # install_name_tool -id $out/lib/libjlinkarm.6.94.4.dylib $out/lib/libjlinkarm.6.94.4.dylib
    install_name_tool -add_rpath "$out/lib" $out/bin/JLinkExe

along with fixDarwinDyLibNames.


export DYLD_LIBRARY_PATH="$(dirname $(readlink $(which JLinkExe)))/../lib"

doesn’t work either, although it did for the nrf-command-line-tools, which depend on this. I was able to use the above install_name_tool approach for nrf-command-line-tools once I realized setting DYLD_LIBRARY_PATH fixed the issue (in some documentation I saw it had to be set up so that dlopen could find it).

I even tried an elaborate approach to replacing the string in the binary:

original=$(printf "/Applications/SEGGER/JLink/" | xxd -p)
new=$(printf "$out/" | xxd -p | tr -d '\n')
xxd -p < Applications/SEGGER/JLink_${downloadVersion}/JLinkExe | tr -d '\n' | sed "s/$original/$new/g" | xxd -r -p > $out/bin/JLinkExe

but sadly this causes it to crash (presumably the rest of the binary becomes misaligned, so it might work if it were shorter).

If I set up a symlink:

ln -s $(dirname $(readlink $(which JLinkExe)))/../lib /Applications/SEGGER/JLink

It works (at least inasmuch as execution is concerned):

SEGGER J-Link Commander V6.94d (Compiled Feb 12 2021 15:53:12)
DLL version V6.94d, compiled Feb 12 2021 15:53:05

Connecting to J-Link via USB...FAILED: Cannot connect to J-Link.

But of course, this is definitely not idiomatic for nix…

Anyone have any more ideas? Thanks.