From 9e829779f249402071ee979705728db3066000fa Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 8 Jan 2024 13:02:21 -0800 Subject: Swift: preserve `-static` for static library swiftmodules The `-static` is important for the emission of the module as it is serialized into the swiftmodule which then is used by the Swift frontend to decide how to link to the symbol (via the GOT or not, or the IAT on Windows). This repairs building static libraries with Swift on Windows. --- Source/cmNinjaTargetGenerator.cxx | 20 ++++++++++++-------- Tests/RunCMake/Swift/RunCMakeTest.cmake | 6 ++++++ .../Swift/SwiftLibraryModuleCommand-check-stdout.txt | 3 +++ Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake | 8 ++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt create mode 100644 Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index c493778..bc97e88 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1987,6 +1987,18 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement( return !isMultiThread && compileMode == cmSwiftCompileMode::Wholemodule; }(); + // Without `-emit-library` or `-emit-executable`, targets with a single + // source file parse as a Swift script instead of like normal source. For + // non-executable targets, append this to ensure that they are parsed like a + // normal source. + if (target.GetType() != cmStateEnums::EXECUTABLE) { + this->LocalGenerator->AppendFlags(vars["FLAGS"], "-parse-as-library"); + } + + if (target.GetType() == cmStateEnums::STATIC_LIBRARY) { + this->LocalGenerator->AppendFlags(vars["FLAGS"], "-static"); + } + // Swift modules only make sense to emit from things that can be imported. // Executables that don't export symbols can't be imported, so don't try to // emit a swiftmodule for them. It will break. @@ -2011,14 +2023,6 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement( vars["FLAGS"], cmStrCat(libraryLinkNameFlag, ' ', libraryLinkName)); } - // Without `-emit-library` or `-emit-executable`, targets with a single - // source file parse as a Swift script instead of like normal source. For - // non-executable targets, append this to ensure that they are parsed like a - // normal source. - if (target.GetType() != cmStateEnums::EXECUTABLE) { - this->LocalGenerator->AppendFlags(vars["FLAGS"], "-parse-as-library"); - } - this->LocalGenerator->AppendFlags(vars["FLAGS"], this->GetFlags(language, config)); vars["DEFINES"] = this->GetDefines(language, config); diff --git a/Tests/RunCMake/Swift/RunCMakeTest.cmake b/Tests/RunCMake/Swift/RunCMakeTest.cmake index 5de4346..b5210c9 100644 --- a/Tests/RunCMake/Swift/RunCMakeTest.cmake +++ b/Tests/RunCMake/Swift/RunCMakeTest.cmake @@ -76,6 +76,12 @@ elseif(RunCMake_GENERATOR STREQUAL Ninja) # -v: verbose to capture executed commands -n: dry-run to avoid actually compiling run_cmake_command(ForceResponseFile-check ${CMAKE_COMMAND} --build ${ForceResponseFile_TEST_BINARY_DIR} -- -vn) endblock() + + block() + set(SwiftLibraryModuleCommand_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SwiftLibraryModuleCommand-build) + run_cmake(SwiftLibraryModuleCommand) + run_cmake_command(SwiftLibraryModuleCommand-check ${CMAKE_COMMAND} --build ${SwiftLibraryModuleCommand_TEST_BINARY_DIR} -- -n -v) + endblock() endif() elseif(RunCMake_GENERATOR STREQUAL "Ninja Multi-Config") if(CMake_TEST_Swift) diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt new file mode 100644 index 0000000..85767eb --- /dev/null +++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt @@ -0,0 +1,3 @@ +.*swiftc(.exe)? .* -parse-as-library -static -emit-module .* -module-name StaticLibrary [^ +]* +.*swiftc(.exe)? .* -parse-as-library -emit-module .* -module-name DynamicLibrary diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake new file mode 100644 index 0000000..7127751 --- /dev/null +++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake @@ -0,0 +1,8 @@ +if(POLICY CMP0157) + cmake_policy(SET CMP0157 NEW) +endif() + +enable_language(Swift) + +add_library(StaticLibrary STATIC L.swift) +add_library(DynamicLibrary SHARED L.swift) -- cgit v0.12