Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Swift SDK bundles not working due to quarantine #6426

Merged
merged 10 commits into from
May 11, 2023
12 changes: 6 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,8 @@ let package = Package(
),

.target(
/** Interacts with cross-compilation destinations */
name: "CrossCompilationDestinationsTool",
/** Interacts with Swift SDKs used for cross-compilation */
name: "SwiftSDKTool",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"Basics",
Expand Down Expand Up @@ -480,9 +480,9 @@ let package = Package(
exclude: ["CMakeLists.txt"]
),
.executableTarget(
/** Interacts with cross-compilation destinations */
name: "swift-experimental-destination",
dependencies: ["Commands", "CrossCompilationDestinationsTool"],
/** Interacts with Swift SDKs used for cross-compilation */
name: "swift-experimental-sdk",
dependencies: ["Commands", "SwiftSDKTool"],
exclude: ["CMakeLists.txt"]
),
.executableTarget(
Expand All @@ -508,7 +508,7 @@ let package = Package(
dependencies: [
"Basics",
"Commands",
"CrossCompilationDestinationsTool",
"SwiftSDKTool",
"PackageCollectionsTool",
"PackageRegistryTool"
],
Expand Down
48 changes: 23 additions & 25 deletions Sources/Basics/FileSystem/FileSystem+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -224,65 +224,63 @@ extension FileSystem {
}
}

// MARK: - cross-compilation destinations
// MARK: - Swift SDKs

private let crossCompilationDestinationsDirectoryName = "destinations"
private let swiftSDKsDirectoryName = "swift-sdks"

extension FileSystem {
/// SwiftPM cross-compilation destinations directory (if exists)
public var swiftPMCrossCompilationDestinationsDirectory: AbsolutePath {
/// Path to Swift SDKs directory (if exists)
public var swiftSDKsDirectory: AbsolutePath {
get throws {
if let path = try idiomaticSwiftPMDirectory {
return path.appending(component: crossCompilationDestinationsDirectoryName)
return path.appending(component: swiftSDKsDirectoryName)
} else {
return try dotSwiftPMCrossCompilationDestinationsDirectory
return try dotSwiftPMSwiftSDKsDirectory
}
}
}

fileprivate var dotSwiftPMCrossCompilationDestinationsDirectory: AbsolutePath {
fileprivate var dotSwiftPMSwiftSDKsDirectory: AbsolutePath {
get throws {
return try dotSwiftPM.appending(component: crossCompilationDestinationsDirectoryName)
return try dotSwiftPM.appending(component: swiftSDKsDirectoryName)
}
}

public func getSharedCrossCompilationDestinationsDirectory(
explicitDirectory: AbsolutePath?
) throws -> AbsolutePath? {
if let explicitDestinationsDirectory = explicitDirectory {
public func getSharedSwiftSDKsDirectory(explicitDirectory: AbsolutePath?) throws -> AbsolutePath? {
if let explicitDirectory {
// Create the explicit SDKs path if necessary
if !exists(explicitDestinationsDirectory) {
try createDirectory(explicitDestinationsDirectory, recursive: true)
if !exists(explicitDirectory) {
try createDirectory(explicitDirectory, recursive: true)
}
return explicitDestinationsDirectory
return explicitDirectory
} else {
return try swiftPMCrossCompilationDestinationsDirectory
return try swiftSDKsDirectory
}
}

public func getOrCreateSwiftPMCrossCompilationDestinationsDirectory() throws -> AbsolutePath {
let idiomaticDestinationsDirectory = try swiftPMCrossCompilationDestinationsDirectory
public func getOrCreateSwiftPMSwiftSDKsDirectory() throws -> AbsolutePath {
let idiomaticSwiftSDKDirectory = try swiftSDKsDirectory

// Create idiomatic if necessary
if !exists(idiomaticDestinationsDirectory) {
try createDirectory(idiomaticDestinationsDirectory, recursive: true)
if !exists(idiomaticSwiftSDKDirectory) {
try createDirectory(idiomaticSwiftSDKDirectory, recursive: true)
}
// Create ~/.swiftpm if necessary
if !exists(try dotSwiftPM) {
try createDirectory(dotSwiftPM, recursive: true)
}
// Create ~/.swiftpm/destinations symlink if necessary
// Create ~/.swiftpm/swift-sdks symlink if necessary
// locking ~/.swiftpm to protect from concurrent access
try withLock(on: dotSwiftPM, type: .exclusive) {
if !exists(try dotSwiftPMCrossCompilationDestinationsDirectory, followSymlink: false) {
if !exists(try dotSwiftPMSwiftSDKsDirectory, followSymlink: false) {
try createSymbolicLink(
dotSwiftPMCrossCompilationDestinationsDirectory,
pointingAt: idiomaticDestinationsDirectory,
dotSwiftPMSwiftSDKsDirectory,
pointingAt: idiomaticSwiftSDKDirectory,
relative: false
)
}
}
return idiomaticDestinationsDirectory
return idiomaticSwiftSDKDirectory
}
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ add_subdirectory(Build)
add_subdirectory(Commands)
add_subdirectory(CompilerPluginSupport)
add_subdirectory(CoreCommands)
add_subdirectory(CrossCompilationDestinationsTool)
add_subdirectory(SwiftSDKTool)
add_subdirectory(DriverSupport)
add_subdirectory(LLBuildManifest)
add_subdirectory(PackageDescription)
Expand All @@ -28,7 +28,7 @@ add_subdirectory(SPMLLBuild)
add_subdirectory(SourceControl)
add_subdirectory(swift-bootstrap)
add_subdirectory(swift-build)
add_subdirectory(swift-experimental-destination)
add_subdirectory(swift-experimental-sdk)
add_subdirectory(swift-package)
add_subdirectory(swift-run)
add_subdirectory(swift-test)
Expand Down
11 changes: 6 additions & 5 deletions Sources/CoreCommands/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ public struct LocationOptions: ParsableArguments {
@Option(name: .customLong("destination"), help: .hidden, completion: .directory)
public var customCompileDestination: AbsolutePath?

@Option(name: .customLong("experimental-destinations-path"), help: .hidden, completion: .directory)
public var crossCompilationDestinationsDirectory: AbsolutePath?
/// Path to the directory containing installed Swift SDKs.
@Option(name: .customLong("experimental-swift-sdks-path"), help: .hidden, completion: .directory)
public var swiftSDKsDirectory: AbsolutePath?

@Option(
name: .customLong("pkg-config-path"),
Expand Down Expand Up @@ -398,9 +399,9 @@ public struct BuildOptions: ParsableArguments {
)
public var architectures: [String] = []

/// Path to the compilation destination describing JSON file.
@Option(name: .customLong("experimental-destination-selector"), help: .hidden)
public var crossCompilationDestinationSelector: String?
/// Filter for selecting a specific Swift SDK to build with.
@Option(name: .customLong("experimental-swift-sdk"), help: .hidden)
public var swiftSDKSelector: String?

/// Which compile-time sanitizers should be enabled.
@Option(
Expand Down
17 changes: 8 additions & 9 deletions Sources/CoreCommands/SwiftTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ public final class SwiftTool {
public let sharedConfigurationDirectory: AbsolutePath?

/// Path to the cross-compilation destinations directory.
public let sharedCrossCompilationDestinationsDirectory: AbsolutePath?
public let sharedSwiftSDKsDirectory: AbsolutePath?

/// Cancellator to handle cancellation of outstanding work when handling SIGINT
public let cancellator: Cancellator
Expand Down Expand Up @@ -336,10 +336,9 @@ public final class SwiftTool {
fileSystem: fileSystem
)
self.sharedCacheDirectory = try getSharedCacheDirectory(options: options, fileSystem: fileSystem)
self.sharedCrossCompilationDestinationsDirectory = try fileSystem
.getSharedCrossCompilationDestinationsDirectory(
explicitDirectory: options.locations.crossCompilationDestinationsDirectory
)
self.sharedSwiftSDKsDirectory = try fileSystem.getSharedSwiftSDKsDirectory(
explicitDirectory: options.locations.swiftSDKsDirectory
)

// set global process logging handler
Process.loggingHandler = { self.observabilityScope.emit(debug: $0) }
Expand Down Expand Up @@ -744,11 +743,11 @@ public final class SwiftTool {
let targetDestination = Destination.defaultDestination(for: triple, host: hostDestination)
{
destination = targetDestination
} else if let destinationSelector = options.build.crossCompilationDestinationSelector {
destination = try DestinationBundle.selectDestination(
fromBundlesAt: sharedCrossCompilationDestinationsDirectory,
} else if let swiftSDKSelector = options.build.swiftSDKSelector {
destination = try SwiftSDKBundle.selectBundle(
fromBundlesAt: sharedSwiftSDKsDirectory,
fileSystem: fileSystem,
matching: destinationSelector,
matching: swiftSDKSelector,
hostTriple: hostTriple,
observabilityScope: observabilityScope
)
Expand Down
5 changes: 4 additions & 1 deletion Sources/PackageModel/ArtifactsArchiveMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ public struct ArtifactsArchiveMetadata: Equatable {
}

// In the future we are likely to extend the ArtifactsArchive file format to carry other types of artifacts beyond
// executables and cross-compilation destinations. Additional fields may be required to support these new artifact
// executables and Swift SDKs. Additional fields may be required to support these new artifact
// types e.g. headers path for libraries. This can also support resource-only artifacts as well. For example,
// 3d models along with associated textures, or fonts, etc.
public enum ArtifactType: String, RawRepresentable, Decodable {
case executable
case swiftSDK

// Can't be marked as formally deprecated as we still need to use this value for warning users.
case crossCompilationDestination
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/PackageModel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ add_library(PackageModel
BuildFlags.swift
BuildSettings.swift
Destination.swift
DestinationConfigurationStore.swift
DestinationBundle.swift
Diagnostics.swift
IdentityResolver.swift
Manifest/Manifest.swift
Expand Down Expand Up @@ -44,6 +42,8 @@ add_library(PackageModel
Sources.swift
SupportedLanguageExtension.swift
SwiftLanguageVersion.swift
SwiftSDKConfigurationStore.swift
SwiftSDKBundle.swift
Target.swift
Toolchain.swift
ToolchainConfiguration.swift
Expand Down
37 changes: 29 additions & 8 deletions Sources/PackageModel/Destination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ public enum DestinationError: Swift.Error {
/// A destination with this artifact ID is already installed. Can't install a new bundle with this artifact,
/// installed artifact IDs are expected to be unique.
case destinationArtifactAlreadyInstalled(installedBundleName: String, newBundleName: String, artifactID: String)

#if os(macOS)
/// Quarantine attribute could not be removed by `xattr` command from an installed bundle.
case failedToRemoveQuarantineBit(bundlePath: AbsolutePath, xattrExitStatus: ProcessResult.ExitStatus)
#endif
}

extension DestinationError: CustomStringConvertible {
Expand All @@ -63,34 +68,50 @@ extension DestinationError: CustomStringConvertible {
return problem
case .invalidBundleName(let name):
return """
invalid bundle name `\(name)`, unpacked destination bundles are expected to have `.artifactbundle` extension
invalid bundle name `\(name)`, unpacked Swift SDK bundles are expected to have `.artifactbundle` extension
"""
case .noDestinationsDecoded(let path):
return "no valid destinations were decoded from a destination file at path `\(path)`"
return "no valid Swift SDKs were decoded from a destination file at path `\(path)`"
case .pathIsNotDirectory(let path):
return "path expected to be a directory is not a directory or doesn't exist: `\(path)`"
case .unserializableDestination:
return """
destination couldn't be serialized with the latest serialization schema, potentially because it \
was deserialized from an earlier incompatible schema version or initialized manually with missing \
Swift SDK configuration couldn't be serialized with the latest serialization schema, potentially because \
it was deserialized from an earlier incompatible schema version or initialized manually with missing \
properties required for initialization
"""
case .destinationNotFound(let artifactID, let buildTimeTriple, let runTimeTriple):
return """
destination with ID `\(artifactID)`, build-time triple \(buildTimeTriple), and run-time triple \
Swift SDK with ID `\(artifactID)`, build-time triple \(buildTimeTriple), and run-time triple \
\(runTimeTriple) is not currently installed.
"""
case .destinationBundleAlreadyInstalled(let bundleName):
return """
destination artifact bundle with name `\(bundleName)` is already installed. Can't install a new bundle \
Swift SDK bundle with name `\(bundleName)` is already installed. Can't install a new bundle \
with the same name.
"""
case .destinationArtifactAlreadyInstalled(let installedBundleName, let newBundleName, let artifactID):
return """
A destination with artifact ID `\(artifactID)` is already included in an installed bundle with name \
A Swift SDK with artifact ID `\(artifactID)` is already included in an installed bundle with name \
`\(installedBundleName)`. Can't install a new bundle `\(newBundleName)` with this artifact, artifact IDs \
are expected to be unique across all installed bundles.
are expected to be unique across all installed Swift SDK bundles.
"""
#if os(macOS)
case .failedToRemoveQuarantineBit(let bundlePath, let xattrExitStatus):
let exitStatusDescription: String

switch xattrExitStatus {
case .signalled(let signal):
exitStatusDescription = "the command received a signal with code \(signal)"
case .terminated(let code):
exitStatusDescription = "the command terminated with exit code \(code)"
}

return """
Failed to remove quarantine attribute with `xattr` command from a bundle installed at path \
`\(bundlePath)`, \(exitStatusDescription).
"""
#endif
}
}
}
Expand Down
Loading