Link Against Custom Built `swift-stdlib`

Hi there! I want to debug my custom build macOS's swift-stdlib, but encounter some problems when I tried to link against it.

Here is my build script for apple/swift:

utils/build-script \
  utils/build-script \
  --sccache \
  --skip-build-benchmarks \
  --release-debuginfo \
  --debug-swift-stdlib \
  --skip-ios \
  --skip-watchos \
  --skip-tvos \
  --swift-darwin-supported-archs "$(uname -m)" \
  --swift-disable-dead-stripping \
  --test

With newly built swiftc, I found out the program was still (if I understand correctly) linking against system's stdlib, instead of custom built one (i.e. build/Ninja-RelWithDebInfoAssert+stdlib-DebugAssert/swift-macosx-x86_64/lib/swift/macosx/libswiftCore.dylib):

$ xcrun ./swiftc -g testprog.swift 

$ otool -L testprog
testprog:
    ...
    /usr/lib/swift/libswiftCore.dylib     // default one?
    /usr/lib/swift/libswiftCoreFoundation.dylib
    ...

IMO it indicates that testprog is linking against system default stdlib. and I have tried several ways:

  1. Change testprog's install name for libswiftCore.
  2. Force dynamic link all libswift*.dylib.

but either of them failed.

Since the functions I'm interested in are located in libswiftCore, for exmaple Collection.map(), how can I correctly link against to the custom built stdlib? Could anyone give some clues, would be much appreciated!

You can set the DYLD_LIBRARY_PATH environment variable while launching testprog to point at your build directory containing your locally-built runtime libraries, and then dyld should favor those over the ones in the OS.

3 Likes

There is a compiler flag to force this on macOS, -toolchain-stdlib-rpath, which the source code doc says exists for scenarios like yours. Linux has that flag turned on by default, since it usually doesn't ship with a Swift stdlib in the OS.

2 Likes

@Finagolfin Thanks for the reply! The option -toolchain-stdlib-rpath make effects but somewhat weird, I have tried to compile with -toolchain-stdlib-rpath, results in two RPATH settings, one is of toolchain the other of system:

$ xcrun ./swiftc -g testprog.swift -toolchain-stdlib-rpath
$ otool -l testprog
...
Load command 25
          cmd LC_RPATH
         path .../build/Ninja-RelWithDebInfoAssert+stdlib-DebugAssert/swift-macosx-x86_64/lib/swift/macosx (offset 12)
Load command 26
          cmd LC_RPATH
         path /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/swift (offset 12)
...

But then after I stripped of that system default setting, it still link against the system stdlib:

$ install_name_tool -delete_rpath /Applications/Xcode.app/...
$ DYLD_PRINT_LIBRARIES=1 ./testprog
dyld:<UUID> /usr/lib/libobjc.A.dylib
dyld:<UUID> /usr/lib/libc++abi.dylib
dyld:<UUID> /usr/lib/liboah.dylib
dyld:<UUID> /usr/lib/libc++.1.dylib
dyld:<UUID> /usr/lib/libSystem.B.dylib
...
/* HERE */ dyld:<UUID> /usr/lib/swift/libswiftCore.dylib
dyld:<UUID> /usr/lib/swift/libswiftCoreFoundation.dylib
dyld:<UUID> /usr/lib/swift/libswiftDarwin.dylib

What have I missed?

@Joe_Groff Thanks for the suggestion! Have tried it but no effects:

$ DYLD_LIBRARY_PATH=.../build/Ninja-RelWithDebInfoAssert+stdlib-DebugAssert/swift-macosx-x86_64/lib/swift/macosx ./testprog

$ DYLD_PRINT_LIBRARIES=1 ./testprog
dyld:<UUID> /usr/lib/libobjc.A.dylib
dyld:<UUID> /usr/lib/libc++abi.dylib
dyld:<UUID> /usr/lib/liboah.dylib
dyld:<UUID> /usr/lib/libc++.1.dylib
dyld:<UUID> /usr/lib/libSystem.B.dylib
...
/* HERE */ dyld:<UUID> /usr/lib/swift/libswiftCore.dylib
dyld:<UUID> /usr/lib/swift/libswiftCoreFoundation.dylib
dyld:<UUID> /usr/lib/swift/libswiftDarwin.dylib

The macOS's DYLD_LIBRARY_PATH seems working as expected for normal C/C++ program's dynamic linking. But here it doesn't affect Swift's dynamic linkage, a little confused, is there anything I've missed for swiftc?

Have you tried the -L command line option?

swiftc -g testprog -L <path to directory containing your library>

You can use as many -L parameters as you need. The -L parameter adds the directory to front of user linker search paths, ahead of system paths, DYLD_... paths, etc.

What have I missed?

No idea, I don't use macOS, was just aware that the tests use it to force using the newly built stdlib, not sure why it doesn't work for you.