Skip to content

Commit bcd4b93

Browse files
committed
Add initial support for object library product type
1 parent 78e7e1c commit bcd4b93

27 files changed

+662
-19
lines changed

Sources/SWBCore/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ add_library(SWBCore
138138
SpecImplementations/Tools/MergeInfoPlist.swift
139139
SpecImplementations/Tools/MkdirTool.swift
140140
SpecImplementations/Tools/ModulesVerifierTool.swift
141+
SpecImplementations/Tools/ObjectLibraryAssembler.swift
141142
SpecImplementations/Tools/PLUtilTool.swift
142143
SpecImplementations/Tools/PrelinkedObjectLink.swift
143144
SpecImplementations/Tools/ProcessSDKImports.swift

Sources/SWBCore/PlannedTaskAction.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ public protocol TaskActionCreationDelegate
346346
func createSignatureCollectionTaskAction() -> any PlannedTaskAction
347347
func createClangModuleVerifierInputGeneratorTaskAction() -> any PlannedTaskAction
348348
func createProcessSDKImportsTaskAction() -> any PlannedTaskAction
349+
func createObjectLibraryAssemblerTaskAction() -> any PlannedTaskAction
349350
}
350351

351352
extension TaskActionCreationDelegate {

Sources/SWBCore/SpecImplementations/LinkerSpec.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,16 @@ open class LinkerSpec : CommandLineToolSpec, @unchecked Sendable {
2424
case textBased
2525
case framework
2626
case object
27+
case objectLibrary
2728

2829
public var description: String {
2930
switch self {
30-
case .static: return "static library"
31-
case .dynamic: return "dynamic library"
32-
case .textBased: return "text-based stub"
33-
case .framework: return "framework"
34-
case .object: return "object file"
31+
case .static: return "static library"
32+
case .dynamic: return "dynamic library"
33+
case .textBased: return "text-based stub"
34+
case .framework: return "framework"
35+
case .object: return "object file"
36+
case .objectLibrary: return "object library"
3537
}
3638
}
3739
}
@@ -144,7 +146,7 @@ open class LinkerSpec : CommandLineToolSpec, @unchecked Sendable {
144146
/// Custom entry point for constructing linker tasks.
145147
public func constructLinkerTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, libraries: [LibrarySpecifier], usedTools: [CommandLineToolSpec: Set<FileTypeSpec>]) async {
146148
/// Delegate to the generic machinery.
147-
await delegate.createTask(type: self, ruleInfo: defaultRuleInfo(cbc, delegate), commandLine: commandLineFromTemplate(cbc, delegate, optionContext: discoveredCommandLineToolSpecInfo(cbc.producer, cbc.scope, delegate)).map(\.asString), environment: environmentFromSpec(cbc, delegate), workingDirectory: cbc.producer.defaultWorkingDirectory, inputs: cbc.inputs.map({ $0.absolutePath }), outputs: [cbc.output], action: nil, execDescription: resolveExecutionDescription(cbc, delegate), enableSandboxing: enableSandboxing)
149+
await delegate.createTask(type: self, ruleInfo: defaultRuleInfo(cbc, delegate), commandLine: commandLineFromTemplate(cbc, delegate, optionContext: discoveredCommandLineToolSpecInfo(cbc.producer, cbc.scope, delegate)).map(\.asString), environment: environmentFromSpec(cbc, delegate), workingDirectory: cbc.producer.defaultWorkingDirectory, inputs: cbc.inputs.map({ $0.absolutePath }), outputs: [cbc.output], action: createTaskAction(cbc, delegate), execDescription: resolveExecutionDescription(cbc, delegate), enableSandboxing: enableSandboxing)
148150
}
149151
}
150152

Sources/SWBCore/SpecImplementations/RegisterSpecs.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public struct BuiltinSpecsExtension: SpecificationsExtension {
5858
LibtoolLinkerSpec.self,
5959
LipoToolSpec.self,
6060
MkdirToolSpec.self,
61+
ObjectLibraryAssemblerSpec.self,
6162
PLUtilToolSpec.self,
6263
ProductPackagingToolSpec.self,
6364
ShellScriptToolSpec.self,

Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,9 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec
12281228
case .object:
12291229
// Object files are added to linker inputs in the sources task producer.
12301230
return ([], [])
1231+
case .objectLibrary:
1232+
let pathFlags = specifier.absolutePathFlagsForLd()
1233+
return (pathFlags, [specifier.path])
12311234
}
12321235
}.reduce(([], [])) { (lhs, rhs) in (lhs.args + rhs.args, lhs.inputs + rhs.inputs) }
12331236
}
@@ -1464,6 +1467,9 @@ fileprivate extension LinkerSpec.LibrarySpecifier {
14641467
case (.object, _):
14651468
// Object files are added to linker inputs in the sources task producer.
14661469
return []
1470+
case (.objectLibrary, _):
1471+
// Object libraries can't be found via search paths.
1472+
return []
14671473
}
14681474
}
14691475

@@ -1500,6 +1506,8 @@ fileprivate extension LinkerSpec.LibrarySpecifier {
15001506
case (.object, _):
15011507
// Object files are added to linker inputs in the sources task producer.
15021508
return []
1509+
case (.objectLibrary, _):
1510+
return ["@\(path.join("args.resp").str)"]
15031511
}
15041512
}
15051513
}
@@ -1601,6 +1609,10 @@ public final class LibtoolLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @u
16011609
// Object files are added to linker inputs in the sources task producer and so end up in the link-file-list.
16021610
return []
16031611

1612+
case .objectLibrary:
1613+
inputPaths.append(specifier.path)
1614+
return ["@\(specifier.path.join("args.resp").str)"]
1615+
16041616
case .framework:
16051617
// A static library can build against a framework, since the library in the framework could be a static library, which is valid, and we can't tell here whether it is or not. So we leave it to libtool to do the right thing here.
16061618
// Also, we wouldn't want to emit an error here even if we could determine that it contained a dylib, since the target might be only using the framework to find headers.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
public final class ObjectLibraryAssemblerSpec : GenericLinkerSpec, SpecIdentifierType, @unchecked Sendable {
14+
public static let identifier: String = "org.swift.linkers.object-library-assembler"
15+
16+
public override func createTaskAction(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) -> (any PlannedTaskAction)? {
17+
return delegate.taskActionCreationDelegate.createObjectLibraryAssemblerTaskAction()
18+
}
19+
}

Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,15 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
687687
xcframeworkSourcePath: xcframeworkPath,
688688
privacyFile: nil
689689
)
690+
} else if fileType.conformsTo(identifier: "compiled.object-library") {
691+
return LinkerSpec.LibrarySpecifier(
692+
kind: .objectLibrary,
693+
path: absolutePath,
694+
mode: .normal,
695+
useSearchPaths: false,
696+
swiftModulePaths: swiftModulePaths,
697+
swiftModuleAdditionalLinkerArgResponseFilePaths: swiftModuleAdditionalLinkerArgResponseFilePaths,
698+
)
690699
} else {
691700
// FIXME: Error handling.
692701
return nil
@@ -1624,20 +1633,30 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
16241633
/// Compute the linker to use in the given scope.
16251634
private func getLinkerToUse(_ scope: MacroEvaluationScope) -> LinkerSpec {
16261635
let isStaticLib = scope.evaluate(BuiltinMacros.MACH_O_TYPE) == "staticlib"
1636+
let isObjectLibrary = context.productType?.conformsTo(identifier: "org.swift.product-type.library.object") == true
16271637

16281638
// Return the custom linker, if specified.
1629-
var identifier = scope.evaluate(isStaticLib ? BuiltinMacros.LIBRARIAN : BuiltinMacros.LINKER)
1630-
if !identifier.isEmpty {
1631-
let spec = context.getSpec(identifier)
1632-
if let linker = spec as? LinkerSpec {
1633-
return linker
1634-
}
1639+
if !isObjectLibrary {
1640+
let identifier = scope.evaluate(isStaticLib ? BuiltinMacros.LIBRARIAN : BuiltinMacros.LINKER)
1641+
if !identifier.isEmpty {
1642+
let spec = context.getSpec(identifier)
1643+
if let linker = spec as? LinkerSpec {
1644+
return linker
1645+
}
16351646

1636-
// FIXME: Emit a warning here.
1647+
// FIXME: Emit a warning here.
1648+
}
16371649
}
16381650

16391651
// Return the default linker.
1640-
identifier = isStaticLib ? LibtoolLinkerSpec.identifier : LdLinkerSpec.identifier
1652+
let identifier: String
1653+
if isObjectLibrary {
1654+
identifier = ObjectLibraryAssemblerSpec.identifier
1655+
} else if isStaticLib {
1656+
identifier = LibtoolLinkerSpec.identifier
1657+
} else {
1658+
identifier = LdLinkerSpec.identifier
1659+
}
16411660
return context.getSpec(identifier) as! LinkerSpec
16421661
}
16431662

Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,7 @@ extension TaskProducerContext: CommandProducer {
13561356
let indexEnableBuildArena = scope.evaluate(BuiltinMacros.INDEX_ENABLE_BUILD_ARENA)
13571357
let isBundleProductType = productType?.conformsTo(identifier: "com.apple.product-type.bundle") ?? false
13581358
let isStaticLibrary = scope.evaluate(BuiltinMacros.MACH_O_TYPE) == "staticlib"
1359-
let isObject = scope.evaluate(BuiltinMacros.MACH_O_TYPE) == "mh_object"
1359+
let isObject = scope.evaluate(BuiltinMacros.MACH_O_TYPE) == "mh_object" && productType?.conformsTo(identifier: "org.swift.product-type.library.object") != true
13601360
let result = (isBuild || isLocExport)
13611361
&& !indexEnableBuildArena
13621362
&& (isBundleProductType || isStaticLibrary || isObject)

Sources/SWBTaskExecution/BuildDescriptionManager.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,10 @@ extension BuildSystemTaskPlanningDelegate: TaskActionCreationDelegate {
891891
func createProcessSDKImportsTaskAction() -> any PlannedTaskAction {
892892
return ProcessSDKImportsTaskAction()
893893
}
894+
895+
func createObjectLibraryAssemblerTaskAction() -> any PlannedTaskAction {
896+
return ObjectLibraryAssemblerTaskAction()
897+
}
894898
}
895899

896900
fileprivate extension BuildDescription {

Sources/SWBTaskExecution/BuiltinTaskActionsExtension.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ public struct BuiltinTaskActionsExtension: TaskActionExtension {
5151
36: ConstructStubExecutorInputFileListTaskAction.self,
5252
37: ConcatenateTaskAction.self,
5353
38: GenericCachingTaskAction.self,
54-
39: ProcessSDKImportsTaskAction.self
54+
39: ProcessSDKImportsTaskAction.self,
55+
42: ObjectLibraryAssemblerTaskAction.self
5556
]
5657
}
5758
}

0 commit comments

Comments
 (0)