Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public final class ProcessXCFrameworkLibrarySpec: CommandLineToolSpec, SpecImple
fatalError("unexpected direct invocation")
}

public func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, platform: String, environment: String?, outputDirectory copyLibraryToPath: Path, libraryPath: Path, expectedSignatures: [String]?) async {
public func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, platform: String, environment: String?, libraryIdentifier: String, outputDirectory copyLibraryToPath: Path, libraryPath: Path, expectedSignatures: [String]?) async {
let xcframeworkPath = cbc.input.absolutePath
let inputs: [any PlannedNode] = [delegate.createDirectoryTreeNode(xcframeworkPath)] + cbc.commandOrderingInputs

Expand All @@ -43,6 +43,8 @@ public final class ProcessXCFrameworkLibrarySpec: CommandLineToolSpec, SpecImple
commandLine.append(contentsOf: ["--environment", env])
}

commandLine.append(contentsOf: ["--library-identifier", libraryIdentifier])

// Use the calculated paths above to inform the process step what to copy instead of needing the action to perform the same work.
commandLine.append(contentsOf: ["--target-path", copyLibraryToPath.str])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ final class XCFrameworkTaskProducer: StandardTaskProducer, TaskProducer {
}

access(path: config.path)
await context.processXCFrameworkLibrarySpec.constructTasks(CommandBuildContext(producer: context, scope: scope, inputs: [FileToBuild(context: context, absolutePath: config.path)], outputs: config.outputs, commandOrderingInputs: outputDirectoryIsBuildDirectory ? [delegate.createBuildDirectoryNode(absolutePath: config.outputDirectory)] : []), delegate, platform: config.platform, environment: config.environment, outputDirectory: config.outputDirectory, libraryPath: config.libraryPath, expectedSignatures: expectedSignatures)
await context.processXCFrameworkLibrarySpec.constructTasks(CommandBuildContext(producer: context, scope: scope, inputs: [FileToBuild(context: context, absolutePath: config.path)], outputs: config.outputs, commandOrderingInputs: outputDirectoryIsBuildDirectory ? [delegate.createBuildDirectoryNode(absolutePath: config.outputDirectory)] : []), delegate, platform: config.platform, environment: config.environment, libraryIdentifier: config.libraryIdentifier, outputDirectory: config.outputDirectory, libraryPath: config.libraryPath, expectedSignatures: expectedSignatures)

if scope.evaluate(BuiltinMacros.ENABLE_SIGNATURE_AGGREGATION) {
let output = config.outputDirectory.join("\(config.path.basename)-\(config.platform)\(config.environment.map { "-\($0)"} ?? "").signature")
Expand Down
3 changes: 2 additions & 1 deletion Sources/SWBTaskConstruction/XCFrameworkContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ final class XCFrameworkContext: Sendable {
package let path: Path
package let platform: String
package let environment: String?
package let libraryIdentifier: String
package let outputDirectory: Path
package let libraryPath: Path
package let outputs: [Path]
Expand Down Expand Up @@ -63,7 +64,7 @@ final class XCFrameworkContext: Sendable {

if let (library, outputDirectory) = block(xcframework) {
let outputs = try xcframework.copy(library: library, from: path, to: outputDirectory, fs: workspaceContext.fs, dryRun: true)
state.copyConfigurations[Key(path: path, guid: target.guid)] = XCFrameworkCopyConfiguration(path: path, platform: library.supportedPlatform, environment: library.platformVariant, outputDirectory: outputDirectory, libraryPath: library.libraryPath, outputs: outputs, expectedSignature: expectedSignature)
state.copyConfigurations[Key(path: path, guid: target.guid)] = XCFrameworkCopyConfiguration(path: path, platform: library.supportedPlatform, environment: library.platformVariant, libraryIdentifier: library.libraryIdentifier, outputDirectory: outputDirectory, libraryPath: library.libraryPath, outputs: outputs, expectedSignature: expectedSignature)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public final class ProcessXCFrameworkTaskAction: TaskAction {
var xcframeworkPath: Path?
var platform: String?
var environment: String?
var libraryIdentifier: String?
var targetPath: Path?
var expectedSignatures: [String] = []
var skipSignatureValidation: Bool = false
Expand Down Expand Up @@ -56,6 +57,13 @@ public final class ProcessXCFrameworkTaskAction: TaskAction {
}
environment = value

case "--library-identifier":
guard let value = generator.next() else {
outputDelegate.emitError("`--library-identifier` requires a parameter")
return .failed
}
libraryIdentifier = value

case "--target-path":
guard let value = generator.next() else {
outputDelegate.emitError("`--target-path` requires a parameter")
Expand Down Expand Up @@ -101,10 +109,17 @@ public final class ProcessXCFrameworkTaskAction: TaskAction {

let platformDisplayName = BuildVersion.Platform(platform: plat, environment: environment)?.displayName(infoLookup: executionDelegate.infoLookup) ?? ("\(plat)" + (environment.flatMap { "-\($0)" } ?? ""))

// Find a library in the XCFramework which is compatible with the current platform.
// Note that we don't validate supported architectures here because this task copies the xcframework's contents for potential use by multiple targets which may have different architecture settings.
guard let library = xcframework.findLibrary(platform: plat, platformVariant: environment ?? "") else {
outputDelegate.emitError("While building for \(platformDisplayName), no library for this platform was found in '\(xcframeworkName)'.")
// Task construction selected the library using the target's architectures and passes its identifier.
// Resolve by identifier so we copy that exact slice: multiple per-arch slices (e.g. linux-aarch64 and
// linux-x86_64) share a platform and library file name, so platform alone cannot disambiguate them here.
guard let libraryIdentifier else {
outputDelegate.emitError("--library-identifier is a required argument")
return .failed
}
let matches = xcframework.libraries.filter { $0.libraryIdentifier == libraryIdentifier && $0.supportedPlatform == plat }
guard let library = matches.only else {
let problem = matches.isEmpty ? "no library was" : "\(matches.count) libraries were"
outputDelegate.emitError("While building for \(platformDisplayName), \(problem) found with identifier '\(libraryIdentifier)' in '\(xcframeworkName)'.")
return .failed
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1139,10 +1139,10 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
results.consumeTasksMatchingRuleTypes(taskTypesToExclude)

results.checkTask(.matchRuleType("ProcessXCFramework"), .matchRuleItemBasename("\(fwkBaseName).xcframework")) { task in
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(fwkBaseName).xcframework", "--platform", "ios", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(fwkBaseName).xcframework", "--platform", "ios", "--library-identifier", "ios-arm64", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
}
results.checkTask(.matchRuleType("ProcessXCFramework"), .matchRuleItemBasename("\(libBaseName).xcframework")) { task in
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(libBaseName).xcframework", "--platform", "ios", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(libBaseName).xcframework", "--platform", "ios", "--library-identifier", "ios-arm64", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
}

// Check the tasks in the target.
Expand Down Expand Up @@ -1252,10 +1252,10 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
results.consumeTasksMatchingRuleTypes(taskTypesToExclude)

results.checkTask(.matchRuleType("ProcessXCFramework"), .matchRuleItemBasename("\(fwkBaseName).xcframework")) { task in
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(fwkBaseName).xcframework", "--platform", "ios", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(fwkBaseName).xcframework", "--platform", "ios", "--library-identifier", "ios-arm64", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
}
results.checkTask(.matchRuleType("ProcessXCFramework"), .matchRuleItemBasename("\(libBaseName).xcframework")) { task in
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(libBaseName).xcframework", "--platform", "ios", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(libBaseName).xcframework", "--platform", "ios", "--library-identifier", "ios-arm64", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
}

// Check the tasks in the target.
Expand Down Expand Up @@ -1530,10 +1530,10 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
results.consumeTasksMatchingRuleTypes(taskTypesToExclude)

results.checkTask(.matchRuleType("ProcessXCFramework"), .matchRuleItemBasename("\(fwkBaseName).xcframework")) { task in
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(fwkBaseName).xcframework", "--platform", "ios", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(fwkBaseName).xcframework", "--platform", "ios", "--library-identifier", "ios-arm64", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
}
results.checkTask(.matchRuleType("ProcessXCFramework"), .matchRuleItemBasename("\(libBaseName).xcframework")) { task in
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(libBaseName).xcframework", "--platform", "ios", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
task.checkCommandLine(["builtin-process-xcframework", "--xcframework", "\(SRCROOT)/Sources/\(libBaseName).xcframework", "--platform", "ios", "--library-identifier", "ios-arm64", "--target-path", "\(BUILT_PRODUCTS_DIR)"])
}

// Check MergedFwkTarget
Expand Down
Loading
Loading