From 1730d208b5c94c600f08241a47cb41f81f4db097 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Sun, 15 Jan 2023 23:25:20 -0800 Subject: Add incremental Swift static lib build test Ensure that we're actually trying to rebuild libB when the public interface for libA changes. Without handling the swiftmodule dependency edge correctly, we would only get a linker error because libA didn't have the symbol that libB depended on. With the fix, we get a proper compiler error because ninja knows to rebuild the intermediate libB when the public interface of libA changes. This is more actionable. --- .../Swift/IncrementalSwift-second-result.txt | 1 + .../Swift/IncrementalSwift-second-stderr.txt | 2 ++ .../Swift/IncrementalSwift-second-stdout.txt | 3 +++ Tests/RunCMake/Swift/IncrementalSwift.cmake | 22 ++++++++++++++++++++++ Tests/RunCMake/Swift/RunCMakeTest.cmake | 21 +++++++++++++++++++++ 5 files changed, 49 insertions(+) create mode 100644 Tests/RunCMake/Swift/IncrementalSwift-second-result.txt create mode 100644 Tests/RunCMake/Swift/IncrementalSwift-second-stderr.txt create mode 100644 Tests/RunCMake/Swift/IncrementalSwift-second-stdout.txt create mode 100644 Tests/RunCMake/Swift/IncrementalSwift.cmake diff --git a/Tests/RunCMake/Swift/IncrementalSwift-second-result.txt b/Tests/RunCMake/Swift/IncrementalSwift-second-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Swift/IncrementalSwift-second-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Swift/IncrementalSwift-second-stderr.txt b/Tests/RunCMake/Swift/IncrementalSwift-second-stderr.txt new file mode 100644 index 0000000..7a882f8 --- /dev/null +++ b/Tests/RunCMake/Swift/IncrementalSwift-second-stderr.txt @@ -0,0 +1,2 @@ +ninja explain: A.swiftmodule is dirty +ninja explain: libB.a is dirty diff --git a/Tests/RunCMake/Swift/IncrementalSwift-second-stdout.txt b/Tests/RunCMake/Swift/IncrementalSwift-second-stdout.txt new file mode 100644 index 0000000..bb08a49 --- /dev/null +++ b/Tests/RunCMake/Swift/IncrementalSwift-second-stdout.txt @@ -0,0 +1,3 @@ +.*Linking Swift static library libA.a +.*Linking Swift static library libB.a +FAILED: libB.a CMakeFiles/B.dir/b.swift.o B.swiftmodule diff --git a/Tests/RunCMake/Swift/IncrementalSwift.cmake b/Tests/RunCMake/Swift/IncrementalSwift.cmake new file mode 100644 index 0000000..092269f --- /dev/null +++ b/Tests/RunCMake/Swift/IncrementalSwift.cmake @@ -0,0 +1,22 @@ +enable_language(Swift) + +# Write initial files to build directory +# The files are generated into the build directory to avoid dirtying the source +# directory. This is done because the source files are changed during the test +# to ensure correct incremental build behavior. +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/a.swift + "let number: Int = 32\n" + "public func callA() -> Int { return number }\n") +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/b.swift + "import A\n" + "public func callB() -> Int { return callA() + 1 }\n") +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/exec.swift + "import B\n" + "print(callB())\n") + +add_library(A STATIC ${CMAKE_CURRENT_BINARY_DIR}/a.swift) +add_library(B STATIC ${CMAKE_CURRENT_BINARY_DIR}/b.swift) +target_link_libraries(B PRIVATE A) + +add_executable(exec ${CMAKE_CURRENT_BINARY_DIR}/exec.swift) +target_link_libraries(exec PRIVATE B) diff --git a/Tests/RunCMake/Swift/RunCMakeTest.cmake b/Tests/RunCMake/Swift/RunCMakeTest.cmake index 7f4464d..5537c01 100644 --- a/Tests/RunCMake/Swift/RunCMakeTest.cmake +++ b/Tests/RunCMake/Swift/RunCMakeTest.cmake @@ -24,6 +24,27 @@ elseif(RunCMake_GENERATOR STREQUAL Ninja) run_cmake_command(NoWorkToDo-build ${CMAKE_COMMAND} --build .) run_cmake_command(NoWorkToDo-nowork ${CMAKE_COMMAND} --build . -- -d explain) endblock() + + # Test that intermediate static libraries are rebuilt when the public + # interface of their dependency changes + block() + set(IncrementalSwift_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/IncrementalSwift-build) + set(IncrementalSwift_TEST_NO_CLEAN 1) + set(IncrementalSwift_TEST_OUTPUT_MERGE 1) + # Since files are modified during test, the files are created in the cmake + # file into the build directory + run_cmake(IncrementalSwift) + run_cmake_command(IncrementalSwift-first ${CMAKE_COMMAND} --build ${IncrementalSwift_TEST_BINARY_DIR}) + + # Modify public interface of libA requiring rebuild of libB + file(WRITE ${IncrementalSwift_TEST_BINARY_DIR}/a.swift + "public func callA() -> Float { return 32.0 }\n") + + # Note: We still expect this to fail, but instead of failure at link time, + # it should fail while re-compiling libB because the function changed + run_cmake_command(IncrementalSwift-second ${CMAKE_COMMAND} --build ${IncrementalSwift_TEST_BINARY_DIR} -- -d explain) + endblock() + endif() elseif(RunCMake_GENERATOR STREQUAL "Ninja Multi-Config") if(CMAKE_Swift_COMPILER) -- cgit v0.12