From 89fb25a7993c6aaee6d8e7832a9de789aa7f45cc Mon Sep 17 00:00:00 2001 From: Fabrice de Gans Date: Fri, 10 Apr 2026 10:36:40 +0200 Subject: [PATCH] utils: Pass linker flags to the Swift flags Starting with CMake 3.30+, CMAKE_SHARED_LINKER_FLAGS are passed to Swift targets. This is an undocumented behavior change from CMake 3.29. However, the same does not apply to CMAKE_EXE_LINKER_FLAGS, which are only supported with CMake 4.4+ and CMP0214. In order to work around these issues and keep the handling of linker arguments consistent, this changes build.ps1 to also pass linker flags to the Swift flags, maintaining consistency. At worst, this results in duplicate linker arguments, which is not a problem in practice. This is a no-op when building with CMake 3.29. --- utils/build.ps1 | 64 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/utils/build.ps1 b/utils/build.ps1 index ae8f9ae8b514f..a5d6ae6fda566 100644 --- a/utils/build.ps1 +++ b/utils/build.ps1 @@ -2105,6 +2105,22 @@ function Build-CMakeProject { # Helper cmdlet to add linker flags with the appropriate handling based on # the linker driver and CMake version. function Convert-LinkerFlags([string[]]$Value) { + # CMake only passes CMAKE_EXE_LINKER_FLAGS to Swift executables starting + # with CMake 4.4, which CMP0214 set to NEW. CMAKE_SHARED_LINKER_FLAGS + # are passed to Swift shared libraries when CMP0157 is set to NEW, but + # only after CMake 3.30. + # To work around these issues, add the linker flags directly to + # CMAKE_Swift_FLAGS with the `-Xlinker` prefix, until CMake 4.4 is used to + # build the toolchain. + if ($UseSwift) { + $SwiftLinkerFlags = @() + foreach ($Flag in $Value) { + $SwiftLinkerFlags += "-Xlinker" + $SwiftLinkerFlags += $Flag + } + Add-FlagsDefine $Defines CMAKE_Swift_FLAGS $SwiftLinkerFlags + } + switch ($FlagHandling) { CMP0181 { $Value | ForEach-Object { "LINKER:$_" } @@ -2237,21 +2253,31 @@ function Build-CMakeProject { Add-FlagsDefine $Defines CMAKE_Swift_FLAGS $(& $SwiftCompiler.DebugFlags $DebugFormat) } else { Add-FlagsDefine $Defines CMAKE_Swift_FLAGS @("-gnone") + [string[]] $SwiftFlags = @(); + + $SwiftFlags += if ($SwiftSDK) { + @("-sdk", $SwiftSDK) + } else { + @() + } + + $SwiftFlags += if ($DebugInfo) { + if ($DebugFormat -eq "dwarf") { + @("-g", "-debug-info-format=dwarf", "-use-ld=lld-link") + } else { + @("-g", "-debug-info-format=codeview") + } + } else { + @("-gnone") } if ($CMakePassesSwiftLinkerFlags) { - # CMake 3.30+ passes all linker flags to Swift as the linker driver, - # including those from the internal CMake modules files, without - # a `-Xlinker` prefix. This causes build failures as Swift cannot - # parse linker flags. - # Overwrite the release linker flags to be empty to avoid this. + # CMake 3.30+ passes CMAKE_SHARED_LINKER_FLAGS to Swift shared + # libraries (via CMP0157). CMake's MSVC platform files set + # release-config linker flags that the Swift driver doesn't + # understand. Clear them to prevent build failures. Add-KeyValueIfNew $Defines CMAKE_EXE_LINKER_FLAGS_RELEASE "" Add-KeyValueIfNew $Defines CMAKE_SHARED_LINKER_FLAGS_RELEASE "" - } else { - # Disable EnC as that introduces padding in the conformance tables - Add-FlagsDefine $Defines CMAKE_Swift_FLAGS @("-Xlinker", "/INCREMENTAL:NO") - # Swift requires COMDAT folding and de-duplication - Add-FlagsDefine $Defines CMAKE_Swift_FLAGS @("-Xlinker", "/OPT:REF", "-Xlinker", "/OPT:ICF") } Add-FlagsDefine $Defines CMAKE_Swift_FLAGS $SwiftCompiler.Flags @@ -2260,6 +2286,8 @@ function Build-CMakeProject { Add-FlagsDefine $Defines CMAKE_Swift_FLAGS_RELWITHDEBINFO "-O" } + # Disable Edit-and-Continue as that introduces padding in the conformance tables. + # COMDAT folding and de-duplication are required by Swift. Add-LinkerFlagsDefine $Defines @("/INCREMENTAL:NO", "/OPT:REF", "/OPT:ICF") Add-SharedLinkerFlagsDefine $Defines @("/MANIFEST:NO") Add-KeyValueIfNew $Defines CMAKE_USER_MAKE_RULES_OVERRIDE ` @@ -2273,16 +2301,16 @@ function Build-CMakeProject { # is no need to set them explicitly above. Add-KeyValueIfNew $Defines CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded Add-KeyValueIfNew $Defines CMAKE_POLICY_DEFAULT_CMP0141 NEW + } + if ($DebugFormat -eq "dwarf" -and -not ($UseMSVCCompilers.Contains("C") -or $UseMSVCCompilers.Contains("CXX"))) { + # The linker flags are shared across every language, and these are + # `lld-link.exe` arguments, not `link.exe`. + # TODO: Investigate supporting fission with PE/COFF, this should + # avoid the `longsections` warning. + Add-LinkerFlagsDefine $Defines @("/DEBUG:DWARF", "/IGNORE:longsections") + } else { Add-LinkerFlagsDefine $Defines @("/DEBUG") - - # The linker flags are shared across every language, and `/IGNORE:longsections` is an - # `lld-link.exe` argument, not `link.exe`, so this can only be enabled when we use - # `lld-link.exe` for linking. - # TODO: Investigate supporting fission with PE/COFF, this should avoid this warning. - if ($DebugFormat -eq "dwarf" -and -not $UseMSVC) { - Add-LinkerFlagsDefine $Defines @("/IGNORE:longsections") - } } } }