How to export Foundation built from source on Linux?

I'm trying to run LLDB's tests, but those that depend on Foundation are failing.

I've built Swift with the command:

utils/build-script  --libicu --lldb  --foundation

I've found instructions for building Foundation on Linux here. I've tried exporting LD_LIBRARY_PATH as suggested, switching Foundation for CoreFoundation:

export BUILD_DIR=~/Developer/swift/build/Ninja-DebugAssert
export LD_LIBRARY_PATH=$BUILD_DIR/foundation-linux-x86_64/CoreFoundation

But swiftc still fails to find Foundation.

So what should I do to expose Foundation to the swift compiler?

@Adrian_Prantl @vedantk

1 Like

cc @compnerd @lorentey for advice on building Swift+Foundation on Linux.

Hey @augusto2112, mind sharing the error message produced by swiftc when it fails to find Foundation?

One suspicion I have is that the environment variables you've exported aren't forwarded to the swiftc invocation constructed by the lldb test driver. If that's the case, we might consider updating the test driver so it can forward all the right info to swiftc.

Before re-running the tests, I've tried just compiling with swiftc a test file with just import Foundation.

That fails with the error:

test.swift:1:8: error: no such module 'Foundation'

Your swiftc invocation most probably needs an appropriate -L flag to point it to the path where your build results are. You could also do something like find / -iname "*.swiftmodule" on your system to find where the rest of the "system" modules (such as stdlib, Dispatch etc) are located and just put it there manually. It's not the best solution, but it worked for me when working on the WebAssembly toolchain. Besides the *.swift* files (there are also .swiftdoc and .swiftsourceinfo in addition to .swiftmodule, as far as I remember) that describe your module, you also probably need something like libFoundation.so located at path where the compiler expects to find it. Without it your swiftc location will find the module, but might fail to link.

(Copying the module files and the library .so file are only manual hacks that could help in diagnosing things, these obviously won't help in making the build work in a reproducible way).

@Max_Desiatov thanks! Copy pasting the Foundation swiftmodule, swiftsourceinfo and swiftdoc files to where Swift.swiftmodule changes the error to: error: missing required modules: 'CoreFoundation', 'Dispatch', which means that the Foundation files were found.

However, if I just try to add the path where the foundation files live as an argument to -L, swiftc can't find them. Am I doing something wrong? Here's what I'm running exactly:

swiftc -L/home/augusto/Developer/swift/build/Ninja-DebugAssert/foundation-linux-x86_64/swift/ test.swift

You'll need to copy the dependencies like CoreFoundation and Dispatch to the same place for it to fully work.

You might need the -I flag pointing to that directory too. I'm not quite sure about that, but the problem might also be that you're pointing it to the build directory, not the installation directory. And then the build directory doesn't have the directory layout that the compiler would expect. Again, I'm not an expert in this area, but somehow copying everything to where the rest of the system modules were worked for me. Unfortunately, the compiler errors are not very helpful here, I would hope it to show paths where it attempted to look for modules and also a suggestions how to point it to the correct path ¯\_(ツ)_/¯

1 Like

Ok, having another look at the original invocation utils/build-script --libicu --lldb --foundation, did you try to pass the installation flags? Something like utils/build-script | grep install could point you in the right direction. Then after the build has completed it should install everything in an appropriate directory, where everything (including Foundation, hopefully) is laid out properly.

You may have luck copying the build-script invocation from the 18.04 builder (https://ci.swift.org/job/oss-lldb-incremental-linux-ubuntu-18_04/); although it's possible I'm on the wrong track, as this one doesn't seem to pass an install-related option.

So I was able to install passing the flags --install-foundation --install-libdispatch (by the way, I don't think these flags are documented. I found them in presets.ini).

This creates a new folder, toolchain-linux-x86_64,which contains a swiftc compiler that can import Foundation, yay!

I re-ran ninja check-lldb, but unfortunately doesn't use this version of the compiler.

Cool! I think build-script-impl configures lldb with -DLLDB_SWIFTC:PATH="$(build_directory ${LOCAL_HOST} swift)/bin/swiftc", which will point to swift-linux-x86_64. So one (admittedly bad) option is to stitch in symlinks, or hack up the logic that passes in LLDB_SWIFTC.

Stepping back a bit, are we sure the --install-* options are the right way to go? The Linux PR testing bot doesn't appear to do this, but does appear to be running all the Swift tests: https://ci.swift.org/view/Pull%20Request/job/swift-lldb-PR-Linux/2516/consoleText. Are these somehow skipping Foundation tests that check-lldb picks up?

As I mentioned before, build-presets.ini is where you look to figure out how to use the build-script. I see several skip-test-lldb and lldb-test-swift-only in there, so it's likely you have to be careful how you run the full lldb testsuite, if it can be run at all.

Find a preset config in there that runs the lldb tests you want and either run that or the flags that it bundles, then you can experiment with changing it if wanted.

1 Like

TestSwiftBridgedMetatype is one of my failing tests, but it is listed under "Slowest tests" in the logs, and since there are no failures in the bot it seems to work there.

I tried running exactly the same command as in the logs (utils/build-script --foundation --libdispatch --test --release --lldb -- --skip-test-cmark --skip-test-swift --lldb-test-swift-only --skip-test-foundation=1 --jobs) but that didn't work either.

@Finagolfin that's a good idea, I'll try that next!

@vedantk I should've tried your suggestion sooner. The command you suggested works:

utils/build-script --foundation --libdispatch --release --lldb --test --build-ninja -- --reconfigure --skip-test-cmark --skip-test-swift --skip-build-benchmarks --skip-test-foundation=1

The one I tried before was:

utils/build-script --foundation --libdispatch --test --lldb -- --skip-test-cmark --skip-test-swift --lldb-test-swift-only --skip-test-foundation=1

I had removed the release flag as I wanted a debug build, but that shouldn't affect the results. The one I'm suspicious of is reconfigure, but I can't find online what that does.

check-lldb now fails in just one test, unrelated to Foundation (which I'll investigate now). The swiftc inside swift-linux-x86_64 still fails to import Foundation, but I can use the one inside the toolchain folder instead.

1 Like

@augusto2112 According to utils/build-script-impl, --reconfigure tells the build system to "force a CMake configuration run even if CMakeCache.txt already exists". So, perhaps you were testing out different build-script invocations without wiping your build directory? That might explain the results you saw: unfortunately, the build system is not smart enough to invalidate+regenerate CMakeCache.txt files when build options change. The --reconfigure forces that.

As for --release, this is the best-supported configuration to build, AFAICT. All of the bots test in release mode for PR testing. Folks tend to build this way locally as well (you can always partially convert a release build into a debug build by recompiling the object files you care about with CCC_OVERRIDE_OPTIONS="+-g O0" set). Because --debug mode gets less testing coverage, it can break more often (e.g. due to linker issues, as there's less inlining in debug builds). But that shouldn't cause the failures you saw.

Cool, thanks for doing this! Consider filing a SR on the bug tracker so others can see the issue (and maybe chime in on it if it looks familiar).

Yes, that's exactly what I was doing. I didn't know I had to wipe CMakeCache if compiling with different flags. That is good to know!

Hmm I see, guess I'll work on release as a default too.

What does SR stand for exactly?

Heh, no idea :). Maybe swift (issue) report?

Haha :grin: I'll open one if I can't figure it out!

SR is defined in the lexicon:

Edit: The Discourse preview wasn't registering the #sr in the url, so I quoted it instead.

1 Like