Skip to content

Commit e54519c

Browse files
committed
Handle -Wl options for disabling SDK imports
The original implementation only worked with `-Xlinker` based options. rdar://145006360
1 parent fbad654 commit e54519c

File tree

2 files changed

+95
-64
lines changed

2 files changed

+95
-64
lines changed

Sources/SWBCore/Specs/Tools/LinkerTools.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec
559559
// Add flags to emit SDK imports info.
560560
let sdkImportsInfoFile = cbc.scope.evaluate(BuiltinMacros.LD_SDK_IMPORTS_FILE)
561561
let supportsSDKImportsFeature = (try? optionContext?.toolVersion >= .init("1164")) == true
562-
let usesLDClassic = commandLine.contains("-r") || commandLine.contains("-ld_classic") || cbc.scope.evaluate(BuiltinMacros.CURRENT_ARCH) == "armv7k"
562+
let usesLDClassic = commandLine.contains("-r") || commandLine.contains("-Wl,-r") || commandLine.contains("-ld_classic") || commandLine.contains("-Wl,-ld_classic") || cbc.scope.evaluate(BuiltinMacros.CURRENT_ARCH) == "armv7k"
563563
if !usesLDClassic, supportsSDKImportsFeature, !sdkImportsInfoFile.isEmpty, cbc.scope.evaluate(BuiltinMacros.ENABLE_SDK_IMPORTS), cbc.producer.isApplePlatform {
564564
commandLine.insert(contentsOf: ["-Xlinker", "-sdk_imports", "-Xlinker", sdkImportsInfoFile.str, "-Xlinker", "-sdk_imports_each_object"], at: commandLine.count - 2) // This preserves the assumption that the last argument is the linker output which a few tests make.
565565
outputs.append(delegate.createNode(sdkImportsInfoFile))

Tests/SWBBuildSystemTests/SDKImportsBuildOperationTests.swift

Lines changed: 94 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,74 +19,80 @@ import Testing
1919

2020
@Suite
2121
fileprivate struct SDKImportsBuildOperationTests: CoreBasedTests {
22-
@Test(.requireSDKs(.macOS), .requireSDKImports())
23-
func basic() async throws {
24-
try await withTemporaryDirectory { (tmpDir: Path) in
25-
let testProject = try await TestProject(
26-
"TestProject",
27-
sourceRoot: tmpDir,
28-
groupTree: TestGroup(
29-
"SomeFiles",
30-
children: [
31-
TestFile("main.swift"),
32-
TestFile("static.swift"),
33-
]),
34-
buildConfigurations: [
35-
TestBuildConfiguration("Debug", buildSettings: [
36-
"ARCHS": "$(ARCHS_STANDARD)",
37-
"CODE_SIGNING_ALLOWED": "YES",
38-
"CODE_SIGN_IDENTITY": "-",
39-
"CODE_SIGN_ENTITLEMENTS": "Entitlements.plist",
40-
"DEFINES_MODULE": "YES",
41-
"GENERATE_INFOPLIST_FILE": "YES",
42-
"PRODUCT_NAME": "$(TARGET_NAME)",
43-
"SDKROOT": "$(HOST_PLATFORM)",
44-
"SUPPORTED_PLATFORMS": "$(HOST_PLATFORM)",
45-
"SWIFT_VERSION": swiftVersion,
46-
])
47-
],
48-
targets: [
49-
TestStandardTarget(
50-
"tool",
51-
type: .application,
52-
buildPhases: [
53-
TestSourcesBuildPhase(["main.swift"]),
54-
TestFrameworksBuildPhase([
55-
TestBuildFile(.target("staticlib")),
56-
])
57-
],
58-
dependencies: [
59-
"staticlib",
60-
]
61-
),
62-
TestStandardTarget(
63-
"staticlib",
64-
type: .staticLibrary,
65-
buildPhases: [
66-
TestSourcesBuildPhase(["static.swift"]),
67-
]
68-
),
22+
func makeTester(ldFlags: String = "", tmpDir: Path) async throws -> BuildOperationTester {
23+
let testProject = try await TestProject(
24+
"TestProject",
25+
sourceRoot: tmpDir,
26+
groupTree: TestGroup(
27+
"SomeFiles",
28+
children: [
29+
TestFile("main.swift"),
30+
TestFile("static.swift"),
31+
]),
32+
buildConfigurations: [
33+
TestBuildConfiguration("Debug", buildSettings: [
34+
"ARCHS": "$(ARCHS_STANDARD)",
35+
"CODE_SIGNING_ALLOWED": "YES",
36+
"CODE_SIGN_IDENTITY": "-",
37+
"CODE_SIGN_ENTITLEMENTS": "Entitlements.plist",
38+
"DEFINES_MODULE": "YES",
39+
"GENERATE_INFOPLIST_FILE": "YES",
40+
"PRODUCT_NAME": "$(TARGET_NAME)",
41+
"SDKROOT": "$(HOST_PLATFORM)",
42+
"SUPPORTED_PLATFORMS": "$(HOST_PLATFORM)",
43+
"SWIFT_VERSION": swiftVersion,
44+
"OTHER_LDFLAGS": ldFlags,
6945
])
70-
let core = try await getCore()
71-
let tester = try await BuildOperationTester(core, testProject, simulated: false)
72-
73-
let projectDir = tester.workspace.projects[0].sourceRoot
46+
],
47+
targets: [
48+
TestStandardTarget(
49+
"tool",
50+
type: .application,
51+
buildPhases: [
52+
TestSourcesBuildPhase(["main.swift"]),
53+
TestFrameworksBuildPhase([
54+
TestBuildFile(.target("staticlib")),
55+
])
56+
],
57+
dependencies: [
58+
"staticlib",
59+
]
60+
),
61+
TestStandardTarget(
62+
"staticlib",
63+
type: .staticLibrary,
64+
buildPhases: [
65+
TestSourcesBuildPhase(["static.swift"]),
66+
]
67+
),
68+
])
69+
let core = try await getCore()
70+
let tester = try await BuildOperationTester(core, testProject, simulated: false)
71+
72+
let projectDir = tester.workspace.projects[0].sourceRoot
73+
74+
try await tester.fs.writeFileContents(projectDir.join("main.swift")) { stream in
75+
stream <<< "import staticlib\n"
76+
stream <<< "staticLib()\n"
77+
stream <<< "print(\"Hello world\")\n"
78+
}
7479

75-
try await tester.fs.writeFileContents(projectDir.join("main.swift")) { stream in
76-
stream <<< "import staticlib\n"
77-
stream <<< "staticLib()\n"
78-
stream <<< "print(\"Hello world\")\n"
79-
}
80+
try await tester.fs.writeFileContents(projectDir.join("static.swift")) { stream in
81+
stream <<< "import Foundation\n"
82+
stream <<< "public func staticLib() {\n"
83+
stream <<< "_ = UserDefaults.standard\n"
84+
stream <<< "}\n"
85+
}
8086

81-
try await tester.fs.writeFileContents(projectDir.join("static.swift")) { stream in
82-
stream <<< "import Foundation\n"
83-
stream <<< "public func staticLib() {\n"
84-
stream <<< "_ = UserDefaults.standard\n"
85-
stream <<< "}\n"
86-
}
87+
try await tester.fs.writePlist(projectDir.join("Entitlements.plist"), .plDict([:]))
8788

88-
try await tester.fs.writePlist(projectDir.join("Entitlements.plist"), .plDict([:]))
89+
return tester
90+
}
8991

92+
@Test(.requireSDKs(.macOS), .requireSDKImports())
93+
func basic() async throws {
94+
try await withTemporaryDirectory { (tmpDir: Path) in
95+
let tester = try await makeTester(tmpDir: tmpDir)
9096
let provisioningInputs = [
9197
"staticlib": ProvisioningTaskInputs(identityHash: "-", signedEntitlements: .plDict([:]), simulatedEntitlements: .plDict([:])),
9298
"tool": ProvisioningTaskInputs(identityHash: "-", signedEntitlements: .plDict([:]), simulatedEntitlements: .plDict([:]))
@@ -182,5 +188,30 @@ fileprivate struct SDKImportsBuildOperationTests: CoreBasedTests {
182188
}
183189
}
184190
}
191+
192+
@Test(.requireSDKs(.macOS), .requireSDKImports())
193+
func disabledWhenLdClassicIsInUse() async throws {
194+
for flags in ["-Xlinker -ld_classic", "-Wl,-ld_classic"] {
195+
try await withTemporaryDirectory { (tmpDir: Path) in
196+
let tester = try await makeTester(ldFlags: flags, tmpDir: tmpDir)
197+
let provisioningInputs = [
198+
"staticlib": ProvisioningTaskInputs(identityHash: "-", signedEntitlements: .plDict([:]), simulatedEntitlements: .plDict([:])),
199+
"tool": ProvisioningTaskInputs(identityHash: "-", signedEntitlements: .plDict([:]), simulatedEntitlements: .plDict([:]))
200+
]
201+
202+
let destination: RunDestinationInfo = .host
203+
try await tester.checkBuild(runDestination: destination, signableTargets: Set(provisioningInputs.keys), signableTargetInputs: provisioningInputs) { results in
204+
results.checkNoErrors()
205+
results.checkWarning(.prefix("-ld_classic is deprecated"))
206+
207+
let derivedData = tmpDir.join("build/Debug")
208+
let appResources = derivedData.join("tool.app/Contents/Resources")
209+
210+
let sdkImportsPath = appResources.join("tool_normal_x86_64_sdk_imports.json")
211+
#expect(tester.fs.exists(sdkImportsPath) == false)
212+
}
213+
}
214+
}
215+
}
185216
}
186217

0 commit comments

Comments
 (0)