From e1d635e71c8f2b4f6b2c835c15f422398556e0fc Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Mon, 2 Dec 2024 16:03:31 -0800 Subject: [PATCH] Swift: Expand generator expressions in Swift_MODULE_DIRECTORY This patch makes the `Swift_MODULE_DIRECTORY` property behave more like the other output directory properties, allowing generator expressions and fixing the behavior with multi-config generators. Issue: #26010 --- Help/prop_tgt/Swift_MODULE_DIRECTORY.rst | 18 +++++++++--------- Help/release/dev/swift-module-dir-genex.rst | 5 +++++ Source/cmGeneratorTarget.cxx | 18 +++++++++++++++--- .../RunCMake/Swift/CompileCommands-check.cmake | 4 ++-- .../Swift/ImportLibraryFlags-check-stdout.txt | 2 +- ...ibraryModuleCommand-check-stdout-darwin.txt | 11 +++++++++-- ...braryModuleCommand-check-stdout-windows.txt | 13 ++++++++++--- .../SwiftLibraryModuleCommand-check-stdout.txt | 11 +++++++++-- .../Swift/SwiftLibraryModuleCommand.cmake | 15 +++++++++++++-- Tests/SwiftOnly/CMakeLists.txt | 3 ++- 10 files changed, 75 insertions(+), 25 deletions(-) create mode 100644 Help/release/dev/swift-module-dir-genex.rst diff --git a/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst b/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst index 77f8311a89..63ea0ae588 100644 --- a/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst +++ b/Help/prop_tgt/Swift_MODULE_DIRECTORY.rst @@ -11,14 +11,14 @@ placed in the build directory corresponding to the target's source directory. If the variable :variable:`CMAKE_Swift_MODULE_DIRECTORY` is set when a target is created its value is used to initialize this property. +.. versionadded:: 3.32 + + The property value may use + :manual:`generator expressions `. + Multi-configuration generators (:generator:`Ninja Multi-Config`) append a + per-configuration subdirectory to the specified directory unless a generator + expression is used. + .. warning:: - This property does not currently provide a way to express per-config - module directories, so use with multi-config generators is problematic: - - * The :generator:`Xcode` generator does not implement the property at all. - - * The :generator:`Ninja Multi-Config` generator implements this property, - but module files generated for different build configurations have the - same path, which can lead to subtle problems when building more than - one configuration. + The :generator:`Xcode` generator ignores this property. diff --git a/Help/release/dev/swift-module-dir-genex.rst b/Help/release/dev/swift-module-dir-genex.rst new file mode 100644 index 0000000000..413301f9fb --- /dev/null +++ b/Help/release/dev/swift-module-dir-genex.rst @@ -0,0 +1,5 @@ +swift-module-dir-genex +---------------------- + +* The :prop_tgt:`Swift_MODULE_DIRECTORY` target property now supports + :manual:`generator expressions `. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index e87cdff50c..7eb23bd94d 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6011,15 +6011,27 @@ std::string cmGeneratorTarget::GetSwiftModuleFileName() const std::string cmGeneratorTarget::GetSwiftModuleDirectory( std::string const& config) const { - std::string moduleDirectory = - this->GetPropertyOrDefault("Swift_MODULE_DIRECTORY", ""); + // This is like the *_OUTPUT_DIRECTORY properties except that we don't have a + // separate per-configuration target property. + // + // The property expands generator expressions. Multi-config generators append + // a per-configuration subdirectory to the specified directory unless a + // generator expression is used. + bool appendConfigDir = true; + std::string moduleDirectory; + if (cmValue value = this->GetProperty("Swift_MODULE_DIRECTORY")) { + moduleDirectory = cmGeneratorExpression::Evaluate( + *value, this->LocalGenerator, config, this); + appendConfigDir = *value == moduleDirectory; + } if (moduleDirectory.empty()) { moduleDirectory = this->LocalGenerator->GetCurrentBinaryDirectory(); + } + if (appendConfigDir) { this->LocalGenerator->GetGlobalGenerator()->AppendDirectoryForConfig( "/", config, "", moduleDirectory); } - return moduleDirectory; } diff --git a/Tests/RunCMake/Swift/CompileCommands-check.cmake b/Tests/RunCMake/Swift/CompileCommands-check.cmake index e33a027063..b277c5c220 100644 --- a/Tests/RunCMake/Swift/CompileCommands-check.cmake +++ b/Tests/RunCMake/Swift/CompileCommands-check.cmake @@ -11,13 +11,13 @@ set(expected_compile_commands "directory": ".*(/Tests/RunCMake/Swift/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\Swift\\\\CompileCommands-build)", "command": ".*swiftc .* (\\")?.*(/Tests/RunCMake/Swift/E.swift|\\\\Tests\\\\RunCMake\\\\Swift\\\\E.swift)(\\")? (\\")?.*(/Tests/RunCMake/Swift/L.swift|\\\\Tests\\\\RunCMake\\\\Swift\\\\L.swift)(\\")?", "file": ".*(/Tests/RunCMake/Swift/E.swift|\\\\Tests\\\\RunCMake\\\\Swift\\\\E.swift)", - "output": "CMakeFiles/CompileCommandLib.dir/(Debug(/|\\))?E.swift.o|CMakeFiles\\\\CompileCommandLib.dir\\\\E.swift.obj" + "output": "CMakeFiles/CompileCommandLib.dir/(Debug(/|\\))?E.swift.o|CMakeFiles\\\\CompileCommandLib.dir\\\\(Debug\\\\|Release\\\\)?E.swift.obj" }, { "directory": ".*(/Tests/RunCMake/Swift/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\Swift\\\\CompileCommands-build)", "command": ".*swiftc .* (\\")?.*(/Tests/RunCMake/Swift/E.swift|\\\\Tests\\\\RunCMake\\\\Swift\\\\E.swift)(\\")? (\\")?.*(/Tests/RunCMake/Swift/L.swift|\\\\Tests\\\\RunCMake\\\\Swift\\\\L.swift)(\\")?", "file": ".*/Tests/RunCMake/Swift/L.swift", - "output": "CMakeFiles/CompileCommandLib.dir/(Debug(/|\\))?L.swift.o|CMakeFiles\\\\CompileCommandLib.dir\\\\L.swift.obj" + "output": "CMakeFiles/CompileCommandLib.dir/(Debug(/|\\))?L.swift.o|CMakeFiles\\\\CompileCommandLib.dir\\\\(Debug\\\\|Release\\\\)?L.swift.obj" } ]$]==] ) diff --git a/Tests/RunCMake/Swift/ImportLibraryFlags-check-stdout.txt b/Tests/RunCMake/Swift/ImportLibraryFlags-check-stdout.txt index 9b5382040e..94eb6d98b5 100644 --- a/Tests/RunCMake/Swift/ImportLibraryFlags-check-stdout.txt +++ b/Tests/RunCMake/Swift/ImportLibraryFlags-check-stdout.txt @@ -1 +1 @@ -.*-implib:lib\\L.lib +.*-implib:lib\\(Debug\\|Release\\)?L.lib diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-darwin.txt b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-darwin.txt index 20c656d600..34d28f57c2 100644 --- a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-darwin.txt +++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-darwin.txt @@ -1,13 +1,20 @@ .*swiftc(.exe)? [^ -]* -parse-as-library -static -emit-module [^ +]* -parse-as-library -static[^ +]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary.swiftmodule[^ ]* -module-name StaticLibrary [^ ]* .*swiftc(.exe)? [^ -]* -parse-as-library -emit-module [^ +]* -parse-as-library[^ +]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary.swiftmodule[^ ]* -module-name DynamicLibrary [^ ]* .*swiftc(.exe)? [^ ]* -emit-library [^ ]* -Xlinker -install_name -Xlinker @rpath/libDynamicLibrary.dylib -o ([A-Za-z]+/)?libDynamicLibrary.dylib [^ ]* +.*swiftc(.exe)? [^ +]* -parse-as-library[^ +]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2.swiftmodule[^ +]* -module-name DynamicLibrary2[^ +]* .*swiftc(.exe)? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-windows.txt b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-windows.txt index 220a805602..bfab4b63e9 100644 --- a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-windows.txt +++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout-windows.txt @@ -1,13 +1,20 @@ .*swiftc(.exe)? [^ -]* -parse-as-library -static -emit-module [^ +]* -parse-as-library -static[^ +]* -emit-module -emit-module-path (Debug\\|Release\\)?StaticLibrary.swiftmodule[^ ]* -module-name StaticLibrary [^ ]* .*swiftc(.exe)? [^ -]* -parse-as-library -emit-module [^ +]* -parse-as-library[^ +]* -emit-module -emit-module-path (debug|release)\\modules\\DynamicLibrary.swiftmodule[^ ]* -module-name DynamicLibrary [^ ]* .*swiftc(.exe)? [^ ]* -emit-library [^ -]* -Xlinker -implib:DynamicLibrary.lib +-o ([A-Za-z]+/)?DynamicLibrary.dll [^ +]* -Xlinker -implib:(Debug\\|Release\\)?DynamicLibrary.lib +-o ([A-Za-z]+/)?(Debug\\|Release\\)?DynamicLibrary.dll [^ +]* +.*swiftc(.exe)? [^ +]* -parse-as-library[^ +]* -emit-module -emit-module-path Modules\\(Debug\\|Release\\)?DynamicLibrary2.swiftmodule[^ +]* -module-name DynamicLibrary2 [^ ]* .*swiftc(.exe)? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt index c3530aab51..7a9a96e646 100644 --- a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt +++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand-check-stdout.txt @@ -1,13 +1,20 @@ .*swiftc(.exe)? [^ -]* -parse-as-library -static -emit-module [^ +]* -parse-as-library -static[^ +]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary.swiftmodule[^ ]* -module-name StaticLibrary [^ ]* .*swiftc(.exe)? [^ -]* -parse-as-library -emit-module [^ +]* -parse-as-library[^ +]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary.swiftmodule[^ ]* -module-name DynamicLibrary [^ ]* .*swiftc(.exe)? [^ ]* -emit-library [^ ]* -Xlinker -soname -Xlinker libDynamicLibrary.so -o ([A-Za-z]+/)?libDynamicLibrary.so [^ ]* +.*swiftc(.exe)? [^ +]* -parse-as-library[^ +]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2.swiftmodule[^ +]* -module-name DynamicLibrary2[^ +]* .*swiftc(.exe)? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable diff --git a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake index 700edf0bbc..2b938d6723 100644 --- a/Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake +++ b/Tests/RunCMake/Swift/SwiftLibraryModuleCommand.cmake @@ -6,8 +6,19 @@ enable_language(Swift) add_library(StaticLibrary STATIC L.swift) add_library(DynamicLibrary SHARED L.swift) -set_target_properties(DynamicLibrary PROPERTIES INSTALL_NAME_DIR "@rpath") +set_target_properties(DynamicLibrary + PROPERTIES + Swift_MODULE_DIRECTORY "$,release/modules,debug/modules>" + INSTALL_NAME_DIR "@rpath") + +add_library(DynamicLibrary2 SHARED L.swift) +set_target_properties(DynamicLibrary2 + PROPERTIES + Swift_MODULE_DIRECTORY "Modules" + INSTALL_NAME_DIR "@rpath") + add_executable(Executable E.swift) +add_dependencies(DynamicLibrary2 DynamicLibrary) add_dependencies(DynamicLibrary StaticLibrary) -add_dependencies(Executable DynamicLibrary) +add_dependencies(Executable DynamicLibrary2) diff --git a/Tests/SwiftOnly/CMakeLists.txt b/Tests/SwiftOnly/CMakeLists.txt index 26f75f3517..494a9bf51f 100644 --- a/Tests/SwiftOnly/CMakeLists.txt +++ b/Tests/SwiftOnly/CMakeLists.txt @@ -34,7 +34,8 @@ add_subdirectory(SubE) add_subdirectory("Sub Space") -set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift) +set(CMAKE_Swift_MODULE_DIRECTORY + "${CMAKE_BINARY_DIR}/modules/$,debug/,release/>swift") add_executable(SwiftOnly main.swift) target_compile_definitions(SwiftOnly PRIVATE SWIFTONLY)