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.
This commit is contained in:
Evan Wilde
2023-01-15 23:25:20 -08:00
parent bf3a8ef6d5
commit 1730d208b5
5 changed files with 49 additions and 0 deletions
@@ -0,0 +1 @@
1
@@ -0,0 +1,2 @@
ninja explain: A.swiftmodule is dirty
ninja explain: libB.a is dirty
@@ -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
@@ -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)
+21
View File
@@ -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)