Undefined symbols when building compiler tests

Attempting to build the tests locally for the first time in a bit and have been getting errors like the following even on a clean build:

[46/114][ 40%][6.710s] Linking CXX executable unittests/ClangImporter/SwiftClangImporterTests
FAILED: unittests/ClangImporter/SwiftClangImporterTests 
...
ld: Undefined symbols:
  swift::SILAnalysis::verifyFunction(swift::SILFunction*), referenced from:
      swift::FunctionAnalysisBase<swift::AliasAnalysis>::get(swift::SILFunction*) in libswiftSIL.a[69](MemoryLifetimeVerifier.cpp.o)
  swift::AliasAnalysis::computeMemoryBehavior(swift::SILInstruction*, swift::SILValue), referenced from:
      swift::AliasAnalysis::mayReadFromMemory(swift::SILInstruction*, swift::SILValue) in libswiftSIL.a[69](MemoryLifetimeVerifier.cpp.o)
  swift::AliasAnalysis::~AliasAnalysis(), referenced from:
      std::__1::default_delete<swift::AliasAnalysis>::operator()[abi:v160006](swift::AliasAnalysis*) const in libswiftSIL.a[69](MemoryLifetimeVerifier.cpp.o)
  swift::SILPassManager::SILPassManager(swift::SILModule*, bool, swift::irgen::IRGenModule*), referenced from:
      swift::SILModule::verify(bool, bool) const in libswiftSIL.a[72](SILVerifier.cpp.o)
  swift::SILPassManager::~SILPassManager(), referenced from:
      swift::SILModule::verify(bool, bool) const in libswiftSIL.a[72](SILVerifier.cpp.o)

I'm perfectly able to build, run, and debug the compiler, so not sure why this is only failing to link the tests. Any ideas? :thinking:

Hm, it appears libswiftSILOptimizer.a is not included in the list of libraries to link for SwiftClangImporterTests...

After adding the following dependencies to the relevant CMakeLists.txt files I was able to get tests compiling again:

diff --git a/lib/SIL/CMakeLists.txt b/lib/SIL/CMakeLists.txt
index 6d11f5518d9..dc0b4b1316a 100644
--- a/lib/SIL/CMakeLists.txt
+++ b/lib/SIL/CMakeLists.txt
@@ -6,7 +6,8 @@ target_link_libraries(swiftSIL PRIVATE
   swiftAST
   swiftClangImporter
   swiftSema
-  swiftSerialization)
+  swiftSerialization
+  swiftSILOptimizer)
 
 add_subdirectory(IR)
 add_subdirectory(Utils)
diff --git a/lib/SILGen/CMakeLists.txt b/lib/SILGen/CMakeLists.txt
index d4fbe6770e1..c1b70be843e 100644
--- a/lib/SILGen/CMakeLists.txt
+++ b/lib/SILGen/CMakeLists.txt
@@ -38,6 +38,7 @@ add_swift_host_library(swiftSILGen STATIC
   SILGenTopLevel.cpp
   SILGenType.cpp)
 target_link_libraries(swiftSILGen PRIVATE
+  swiftFrontend
   swiftSerialization
   swiftSIL)
 
diff --git a/lib/SILOptimizer/CMakeLists.txt b/lib/SILOptimizer/CMakeLists.txt
index 1f34ce6e44d..19fbe94b40a 100644
--- a/lib/SILOptimizer/CMakeLists.txt
+++ b/lib/SILOptimizer/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_swift_host_library(swiftSILOptimizer STATIC
   SILOptimizer.cpp)
 target_link_libraries(swiftSILOptimizer PRIVATE
+  swiftIRGen
   swiftSIL)
 set_swift_llvm_is_available(swiftSILOptimizer)

These dependencies appear legitimate (in that, for example, SILGen.cpp does appear to have had a dependency on swiftFrontend introduced somewhat recently), but I am not familar enough with the setup here to understand why this would only be broken for me, or why we need the SIL stuff at all to link SwiftClangImporterTests.

cc @John_McCall and @Erik_Eckstein who I believe also ran into this issue

1 Like

There is, unfortunately, a cyclic dependency between several of the core libraries, and apparently it only actually breaks things in debug builds for ineffable reasons. The short-term fix would be to add the right dependencies to these targets, but unfortunately it doesn't stop there — when I tried this, I found that I would've needed to add all of LLVM as a dependency of every unit test, which would be a huge problem for anyone actually using this build configuration. The better long-term fix is to break the cycle.

In the short term, I switched to a release build.

1 Like

Hah, yes, I believe that’s the transitive effect of the dependencies I added above. :sweat_smile:

Thanks for the info, will use a release configuration here as necessary until the cycle is resolved.