Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/scripts/windows_pre_build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
##===----------------------------------------------------------------------===##
##
## This source file is part of the Swift open source project
##
## Copyright (c) 2025 Apple Inc. and the Swift project authors
## Licensed under Apache License v2.0 with Runtime Library Exception
##
## See http://swift.org/LICENSE.txt for license information
## See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
##
##===----------------------------------------------------------------------===##

param (
[switch]$SkipAndroid,
[switch]$InstallCMake
)

# winget isn't easily made available in containers, so use chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

if ($InstallCMake) {
choco install -y cmake --installargs 'ADD_CMAKE_TO_PATH=System' --apply-install-arguments-to-dependencies
choco install -y ninja

Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
refreshenv

# Let swiftc find the path to link.exe in the CMake smoke test
$env:Path += ";$(Split-Path -Path "$(& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" "-latest" -products Microsoft.VisualStudio.Product.BuildTools -find VC\Tools\MSVC\*\bin\HostX64\x64\link.exe)" -Parent)"
}

if (-not $SkipAndroid) {
choco install android-ndk

Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
refreshenv

# Work around a bug in the package causing the env var to be set incorrectly
$env:ANDROID_NDK_ROOT = $env:ANDROID_NDK_ROOT.replace('-windows.zip','')
}
5 changes: 4 additions & 1 deletion .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ jobs:
linux_pre_build_command: SKIP_ANDROID=1 INSTALL_CMAKE=1 ./.github/scripts/linux_pre_build.sh
linux_build_command: 'swift package -Xbuild-tools-swiftc -DUSE_PROCESS_SPAWNING_WORKAROUND cmake-smoke-test --disable-sandbox --cmake-path `which cmake` --ninja-path `which ninja` --extra-cmake-arg -DCMAKE_C_COMPILER=`which clang` --extra-cmake-arg -DCMAKE_CXX_COMPILER=`which clang++` --extra-cmake-arg -DCMAKE_Swift_COMPILER=`which swiftc`'
linux_swift_versions: '["nightly-main"]'
windows_swift_versions: '[]'
windows_pre_build_command: 'Invoke-Program .\.github\scripts\windows_pre_build.ps1 -SkipAndroid -InstallCMake'
windows_swift_versions: '["nightly-main"]'
windows_build_command: 'Invoke-Program swift package cmake-smoke-test --disable-sandbox --cmake-path (Get-Command cmake).Path --ninja-path (Get-Command ninja).Path --extra-cmake-arg "-DCMAKE_C_COMPILER=$((Get-Command clang).Path)" --extra-cmake-arg "-DCMAKE_CXX_COMPILER=$((Get-Command clang).Path)" --extra-cmake-arg "-DCMAKE_Swift_COMPILER=$((Get-Command swiftc).Path)" --extra-cmake-arg "-DCMAKE_STATIC_LIBRARY_PREFIX_Swift=lib" --extra-cmake-arg "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL"'

soundness:
name: Soundness
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
Expand Down
60 changes: 38 additions & 22 deletions Plugins/cmake-smoke-test/cmake-smoke-test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ struct CMakeSmokeTest: CommandPlugin {
let extraCMakeArgs = args.extractOption(named: "extra-cmake-arg")
Diagnostics.progress("Extra cmake args: \(extraCMakeArgs.joined(separator: " "))")

let moduleCachePath = context.pluginWorkDirectoryURL.appending(component: "module-cache").path()
let moduleCachePath = try context.pluginWorkDirectoryURL.appending(component: "module-cache").filePath

let swiftBuildURL = context.package.directoryURL
let swiftBuildBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-build")
Diagnostics.progress("swift-build: \(swiftBuildURL.path())")
try Diagnostics.progress("swift-build: \(swiftBuildURL.filePath)")

let swiftToolsSupportCoreURL = try findDependency("swift-tools-support-core", pluginContext: context)
let swiftToolsSupportCoreBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-tools-support-core")
Expand Down Expand Up @@ -70,12 +70,12 @@ struct CMakeSmokeTest: CommandPlugin {
sharedSwiftFlags += ["-sdk", sysrootPath]
}

let cMakeProjectArgs = [
"-DArgumentParser_DIR=\(swiftArgumentParserBuildURL.appending(components: "cmake", "modules").path())",
"-DLLBuild_DIR=\(llbuildBuildURL.appending(components: "cmake", "modules").path())",
"-DTSC_DIR=\(swiftToolsSupportCoreBuildURL.appending(components: "cmake", "modules").path())",
"-DSwiftDriver_DIR=\(swiftDriverBuildURL.appending(components: "cmake", "modules").path())",
"-DSwiftSystem_DIR=\(swiftSystemBuildURL.appending(components: "cmake", "modules").path())"
let cMakeProjectArgs = try [
"-DArgumentParser_DIR=\(swiftArgumentParserBuildURL.appending(components: "cmake", "modules").filePath)",
"-DLLBuild_DIR=\(llbuildBuildURL.appending(components: "cmake", "modules").filePath)",
"-DTSC_DIR=\(swiftToolsSupportCoreBuildURL.appending(components: "cmake", "modules").filePath)",
"-DSwiftDriver_DIR=\(swiftDriverBuildURL.appending(components: "cmake", "modules").filePath)",
"-DSwiftSystem_DIR=\(swiftSystemBuildURL.appending(components: "cmake", "modules").filePath)"
]

let sharedCMakeArgs = [
Expand All @@ -86,34 +86,34 @@ struct CMakeSmokeTest: CommandPlugin {
] + cMakeProjectArgs + extraCMakeArgs

Diagnostics.progress("Building swift-tools-support-core")
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftToolsSupportCoreURL.path()], workingDirectory: swiftToolsSupportCoreBuildURL)
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftToolsSupportCoreURL.filePath], workingDirectory: swiftToolsSupportCoreBuildURL)
try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftToolsSupportCoreBuildURL)
Diagnostics.progress("Built swift-tools-support-core")

if hostOS != .macOS {
Diagnostics.progress("Building swift-system")
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftSystemURL.path()], workingDirectory: swiftSystemBuildURL)
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftSystemURL.filePath], workingDirectory: swiftSystemBuildURL)
try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftSystemBuildURL)
Diagnostics.progress("Built swift-system")
}

Diagnostics.progress("Building llbuild")
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + ["-DLLBUILD_SUPPORT_BINDINGS:=Swift", llbuildURL.path()], workingDirectory: llbuildBuildURL)
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + ["-DLLBUILD_SUPPORT_BINDINGS:=Swift", llbuildURL.filePath], workingDirectory: llbuildBuildURL)
try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: llbuildBuildURL)
Diagnostics.progress("Built llbuild")

Diagnostics.progress("Building swift-argument-parser")
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + ["-DBUILD_TESTING=NO", "-DBUILD_EXAMPLES=NO", swiftArgumentParserURL.path()], workingDirectory: swiftArgumentParserBuildURL)
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + ["-DBUILD_TESTING=NO", "-DBUILD_EXAMPLES=NO", swiftArgumentParserURL.filePath], workingDirectory: swiftArgumentParserBuildURL)
try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftArgumentParserBuildURL)
Diagnostics.progress("Built swift-argument-parser")

Diagnostics.progress("Building swift-driver")
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftDriverURL.path()], workingDirectory: swiftDriverBuildURL)
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftDriverURL.filePath], workingDirectory: swiftDriverBuildURL)
try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftDriverBuildURL)
Diagnostics.progress("Built swift-driver")

Diagnostics.progress("Building swift-build in \(swiftBuildBuildURL)")
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftBuildURL.path()], workingDirectory: swiftBuildBuildURL)
try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftBuildURL.filePath], workingDirectory: swiftBuildBuildURL)
try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftBuildBuildURL)
Diagnostics.progress("Built swift-build")
}
Expand All @@ -135,9 +135,10 @@ struct CMakeSmokeTest: CommandPlugin {
throw Errors.missingRepository(name)
}
let dependencyURL = dependency.directoryURL
Diagnostics.progress("\(name): \(dependencyURL.path())")
guard FileManager.default.fileExists(atPath: dependencyURL.path()) else {
throw Errors.missingRepository(dependencyURL.path())
let dependencyFilePath = try dependencyURL.filePath
Diagnostics.progress("\(name): \(dependencyFilePath)")
guard FileManager.default.fileExists(atPath: dependencyFilePath) else {
throw Errors.missingRepository(dependencyFilePath)
}
return dependencyURL
}
Expand Down Expand Up @@ -169,6 +170,19 @@ enum OS {
}
}

extension URL {
var filePath: String {
get throws {
try withUnsafeFileSystemRepresentation { path in
guard let path else {
throw Errors.miscError("cannot get file path for URL: \(self)")
}
return String(cString: path)
}
}
}
}

extension Process {
func run() async throws {
try await withCheckedThrowingContinuation { continuation in
Expand All @@ -186,8 +200,8 @@ extension Process {
}

static func checkNonZeroExit(url: URL, arguments: [String], workingDirectory: URL, environment: [String: String]? = nil) async throws {
Diagnostics.progress("\(url.path()) \(arguments.joined(separator: " "))")
#if USE_PROCESS_SPAWNING_WORKAROUND
try Diagnostics.progress("\(url.filePath) \(arguments.joined(separator: " "))")
#if USE_PROCESS_SPAWNING_WORKAROUND && !os(Windows)
Diagnostics.progress("Using process spawning workaround")
// Linux workaround for https://github.com/swiftlang/swift-corelibs-foundation/issues/4772
// Foundation.Process on Linux seems to inherit the Process.run()-calling thread's signal mask, creating processes that even have SIGTERM blocked
Expand All @@ -197,7 +211,7 @@ extension Process {
var attrs: posix_spawnattr_t = posix_spawnattr_t()
defer { posix_spawnattr_destroy(&attrs) }
posix_spawn_file_actions_init(&fileActions)
posix_spawn_file_actions_addchdir_np(&fileActions, workingDirectory.path())
try posix_spawn_file_actions_addchdir_np(&fileActions, workingDirectory.filePath)

posix_spawnattr_init(&attrs)
posix_spawnattr_setpgroup(&attrs, 0)
Expand All @@ -216,9 +230,9 @@ extension Process {
posix_spawnattr_setsigdefault(&attrs, &mostSignals)
posix_spawnattr_setflags(&attrs, numericCast(POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK))
var pid: pid_t = -1
try withArrayOfCStrings([url.path()] + arguments) { arguments in
try withArrayOfCStrings([url.filePath] + arguments) { arguments in
try withArrayOfCStrings((environment ?? [:]).map { key, value in "\(key)=\(value)" }) { environment in
let spawnResult = posix_spawn(&pid, url.path(), /*file_actions=*/&fileActions, /*attrp=*/&attrs, arguments, nil);
let spawnResult = try posix_spawn(&pid, url.filePath, /*file_actions=*/&fileActions, /*attrp=*/&attrs, arguments, nil);
var exitCode: Int32 = -1
var result = wait4(pid, &exitCode, 0, nil);
while (result == -1 && errno == EINTR) {
Expand Down Expand Up @@ -246,6 +260,7 @@ extension Process {
}
}

#if USE_PROCESS_SPAWNING_WORKAROUND && !os(Windows)
func scan<S: Sequence, U>(_ seq: S, _ initial: U, _ combine: (U, S.Element) -> U) -> [U] {
var result: [U] = []
result.reserveCapacity(seq.underestimatedCount)
Expand Down Expand Up @@ -283,3 +298,4 @@ func withArrayOfCStrings<T>(
}
}
}
#endif