Skip to content

Commit 841db27

Browse files
authored
Merge pull request #84306 from Steelskin/fabrice/cmake-version-support
utils: Support multiple CMake versions in build.ps1
2 parents b916be3 + 9dbf81a commit 841db27

File tree

2 files changed

+80
-25
lines changed

2 files changed

+80
-25
lines changed

stdlib/public/SwiftShims/swift/shims/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ else()
127127
set(clang_headers_location "${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION_MAJOR}")
128128
endif()
129129

130+
# Normalize the path.
131+
cmake_path(CONVERT "${clang_headers_location}" TO_CMAKE_PATH_LIST clang_headers_location NORMALIZE)
132+
130133
add_custom_command_target(unused_var
131134
COMMAND
132135
"${CMAKE_COMMAND}" "-E" "make_directory" "${SWIFTLIB_DIR}"

utils/build.ps1

Lines changed: 77 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,15 @@ function Get-CMake {
511511
throw "CMake not found on Path nor in the Visual Studio Installation. Please Install CMake to continue."
512512
}
513513

514+
$cmake = Get-CMake
515+
$CMakeVersionString = & $cmake --version | Select-String -Pattern 'cmake version ([\d\.]+)' | ForEach-Object { $_.Matches[0].Groups[1].Value }
516+
$CMakeVersion = [Version]$CMakeVersionString
517+
# Starting with CMake 3.30, CMake propagates linker flags to Swift.
518+
$CMakePassesSwiftLinkerFlags = $CMakeVersion -ge [version]'3.30'
519+
# CMP0181 enables support for the `LINKER:flag1,flag2,...` syntax in
520+
# `CMAKE_[EXE|SHARED|MODULE]_LINKER_FLAGS[_<CONFIG>]` variables.
521+
$CMakeSupportsCMP0181 = $CMakeVersion -ge [version]'4.0'
522+
514523
function Get-Ninja {
515524
try {
516525
return (Get-Command "Ninja.exe" -ErrorAction Stop).Source
@@ -522,7 +531,6 @@ function Get-Ninja {
522531
throw "Ninja not found on Path nor in the Visual Studio Installation. Please Install Ninja to continue."
523532
}
524533

525-
$cmake = Get-CMake
526534
$ninja = Get-Ninja
527535

528536
$NugetRoot = "$BinaryCache\nuget"
@@ -1472,9 +1480,32 @@ function Build-CMakeProject {
14721480
$UseCXX = $UseBuiltCompilers.Contains("CXX") -or $UseMSVCCompilers.Contains("CXX") -or $UsePinnedCompilers.Contains("CXX")
14731481
$UseSwift = $UseBuiltCompilers.Contains("Swift") -or $UsePinnedCompilers.Contains("Swift")
14741482

1483+
# We need to manually prefix linker flags with `-Xlinker` if we are using
1484+
# the GNU driver or if Swift is used as the linker driver.
1485+
# This is not necessary with CMake 4.0+ as CMP0181 simplifies the handling
1486+
# of linker arguments.
1487+
$PrefixLinkerFlags = if ($Platform.OS -eq [OS]::Android) {
1488+
# We pass the linker location to the driver, not to the linker.
1489+
$false
1490+
} elseif ($CMakeSupportsCMP0181) {
1491+
# Not necessary if CMP0181 is supported.
1492+
$false
1493+
} elseif ($UseGnuDriver) {
1494+
# Always necessary with the GNU driver.
1495+
$true
1496+
} else {
1497+
# Only necessary with Swift projects, when CMake is not passing the linker flags.
1498+
$UseSwift -and $CMakePassesSwiftLinkerFlags
1499+
}
1500+
14751501
# Add additional defines (unless already present)
14761502
$Defines = $Defines.Clone()
14771503

1504+
# Always enable CMP0181 if available.
1505+
if ($CMakeSupportsCMP0181) {
1506+
Add-KeyValueIfNew $Defines CMAKE_POLICY_DEFAULT_CMP0181 NEW
1507+
}
1508+
14781509
Add-KeyValueIfNew $Defines CMAKE_BUILD_TYPE Release
14791510

14801511
# Avoid specifying `CMAKE_SYSTEM_NAME` and `CMAKE_SYSTEM_PROCESSOR` on
@@ -1645,23 +1676,31 @@ function Build-CMakeProject {
16451676
@("-gnone")
16461677
}
16471678

1648-
# Disable EnC as that introduces padding in the conformance tables
1649-
$SwiftFlags += @("-Xlinker", "/INCREMENTAL:NO")
1650-
# Swift requires COMDAT folding and de-duplication
1651-
$SwiftFlags += @("-Xlinker", "/OPT:REF", "-Xlinker", "/OPT:ICF")
1679+
if (-not $CMakePassesSwiftLinkerFlags) {
1680+
# Disable EnC as that introduces padding in the conformance tables
1681+
$SwiftFlags += @("-Xlinker", "/INCREMENTAL:NO")
1682+
# Swift requires COMDAT folding and de-duplication
1683+
$SwiftFlags += @("-Xlinker", "/OPT:REF", "-Xlinker", "/OPT:ICF")
1684+
}
16521685

16531686
Add-FlagsDefine $Defines CMAKE_Swift_FLAGS $SwiftFlags
16541687
# Workaround CMake 3.26+ enabling `-wmo` by default on release builds
16551688
Add-FlagsDefine $Defines CMAKE_Swift_FLAGS_RELEASE "-O"
16561689
Add-FlagsDefine $Defines CMAKE_Swift_FLAGS_RELWITHDEBINFO "-O"
1657-
}
16581690

1659-
$LinkerFlags = if ($UseGNUDriver) {
1660-
@("-Xlinker", "/INCREMENTAL:NO", "-Xlinker", "/OPT:REF", "-Xlinker", "/OPT:ICF")
1661-
} else {
1662-
@("/INCREMENTAL:NO", "/OPT:REF", "/OPT:ICF")
1691+
if ($CMakePassesSwiftLinkerFlags) {
1692+
# CMake 3.30+ passes all linker flags to Swift as the linker driver,
1693+
# including those from the internal CMake modules files, without
1694+
# a `-Xlinker` prefix. This causes build failures as Swift cannot
1695+
# parse linker flags.
1696+
# Overwrite the release linker flags to be empty to avoid this.
1697+
Add-KeyValueIfNew $Defines CMAKE_EXE_LINKER_FLAGS_RELEASE ""
1698+
Add-KeyValueIfNew $Defines CMAKE_SHARED_LINKER_FLAGS_RELEASE ""
1699+
}
16631700
}
16641701

1702+
$LinkerFlags = @("/INCREMENTAL:NO", "/OPT:REF", "/OPT:ICF")
1703+
16651704
if ($DebugInfo) {
16661705
if ($UseASM -or $UseC -or $UseCXX) {
16671706
# Prefer `/Z7` over `/ZI`
@@ -1671,10 +1710,14 @@ function Build-CMakeProject {
16711710
Add-KeyValueIfNew $Defines CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded
16721711
Add-KeyValueIfNew $Defines CMAKE_POLICY_DEFAULT_CMP0141 NEW
16731712

1674-
$LinkerFlags += if ($UseGNUDriver) {
1675-
@("-Xlinker", "/DEBUG")
1676-
} else {
1677-
@("/DEBUG")
1713+
$LinkerFlags += @("/DEBUG")
1714+
1715+
# The linker flags are shared across every language, and `/IGNORE:longsections` is an
1716+
# `lld-link.exe` argument, not `link.exe`, so this can only be enabled when we use
1717+
# `lld-link.exe` for linking.
1718+
# TODO: Investigate supporting fission with PE/COFF, this should avoid this warning.
1719+
if ($SwiftDebugFormat -eq "dwarf" -and -not ($UseMSVCCompilers.Contains("C") -or $UseMSVCCompilers.Contains("CXX"))) {
1720+
$LinkerFlags += @("/IGNORE:longsections")
16781721
}
16791722

16801723
# The linker flags are shared across every language, and `/IGNORE:longsections` is an
@@ -1825,24 +1868,33 @@ function Build-CMakeProject {
18251868
$Value = $Define.Value.Replace("\", "/")
18261869
} else {
18271870
# Flags array, multiple tokens, quoting needed for tokens containing spaces
1828-
$Value = ""
1829-
foreach ($Arg in $Define.Value) {
1830-
if ($Value.Length -gt 0) {
1831-
$Value += " "
1832-
}
1833-
1834-
$ArgWithForwardSlashes = $Arg.Replace("\", "/")
1835-
if ($ArgWithForwardSlashes.Contains(" ")) {
1871+
$EscapedArgs = $Define.Value | ForEach-Object {
1872+
$Arg = $_.Replace("\", "/")
1873+
if ($Arg.Contains(" ")) {
18361874
# Escape the quote so it makes it through. PowerShell 5 and Core
18371875
# handle quotes differently, so we need to check the version.
18381876
$quote = if ($PSEdition -eq "Core") { '"' } else { '\"' }
1839-
$Value += "$quote$ArgWithForwardSlashes$quote"
1877+
"$quote$Arg$quote"
18401878
} else {
1841-
$Value += $ArgWithForwardSlashes
1879+
$Arg
18421880
}
18431881
}
1844-
}
18451882

1883+
# Linker flags are handled differently depending on the CMake version.
1884+
$IsLinkerFlag = $Define.Key -match "_LINKER_FLAGS" -and ($Platform.OS -ne [OS]::Android)
1885+
$Value = if ($IsLinkerFlag) {
1886+
if ($CMakeSupportsCMP0181) { "LINKER:" } elseif ($PrefixLinkerFlags) { "-Xlinker " } else { "" }
1887+
} else {
1888+
""
1889+
}
1890+
$Separator = if ($IsLinkerFlag) {
1891+
if ($CMakeSupportsCMP0181) { "," } elseif ($PrefixLinkerFlags) { " -Xlinker " } else { " " }
1892+
} else {
1893+
" "
1894+
}
1895+
1896+
$Value += $EscapedArgs -join $Separator
1897+
}
18461898
$cmakeGenerateArgs += @("-D", "$($Define.Key)=$Value")
18471899
}
18481900

0 commit comments

Comments
 (0)