Skip to content

Handle -Wl options for disabling SDK imports #182

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

Merged
merged 1 commit into from
Feb 17, 2025
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
9 changes: 8 additions & 1 deletion Sources/SWBCore/Specs/Tools/LinkerTools.swift
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,14 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec
// Add flags to emit SDK imports info.
let sdkImportsInfoFile = cbc.scope.evaluate(BuiltinMacros.LD_SDK_IMPORTS_FILE)
let supportsSDKImportsFeature = (try? optionContext?.toolVersion >= .init("1164")) == true
let usesLDClassic = commandLine.contains("-r") || commandLine.contains("-ld_classic") || cbc.scope.evaluate(BuiltinMacros.CURRENT_ARCH) == "armv7k"
var usesLDClassic = cbc.scope.evaluate(BuiltinMacros.CURRENT_ARCH) == "armv7k"
enumerateLinkerCommandLine(arguments: commandLine) { arg, value in
switch arg {
case "-ld_classic": usesLDClassic = true
case "-r": usesLDClassic = true
default: break
}
}
if !usesLDClassic, supportsSDKImportsFeature, !sdkImportsInfoFile.isEmpty, cbc.scope.evaluate(BuiltinMacros.ENABLE_SDK_IMPORTS), cbc.producer.isApplePlatform {
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.
outputs.append(delegate.createNode(sdkImportsInfoFile))
Expand Down
157 changes: 94 additions & 63 deletions Tests/SWBBuildSystemTests/SDKImportsBuildOperationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,74 +19,80 @@ import Testing

@Suite
fileprivate struct SDKImportsBuildOperationTests: CoreBasedTests {
@Test(.requireSDKs(.macOS), .requireSDKImports())
func basic() async throws {
try await withTemporaryDirectory { (tmpDir: Path) in
let testProject = try await TestProject(
"TestProject",
sourceRoot: tmpDir,
groupTree: TestGroup(
"SomeFiles",
children: [
TestFile("main.swift"),
TestFile("static.swift"),
]),
buildConfigurations: [
TestBuildConfiguration("Debug", buildSettings: [
"ARCHS": "$(ARCHS_STANDARD)",
"CODE_SIGNING_ALLOWED": "YES",
"CODE_SIGN_IDENTITY": "-",
"CODE_SIGN_ENTITLEMENTS": "Entitlements.plist",
"DEFINES_MODULE": "YES",
"GENERATE_INFOPLIST_FILE": "YES",
"PRODUCT_NAME": "$(TARGET_NAME)",
"SDKROOT": "$(HOST_PLATFORM)",
"SUPPORTED_PLATFORMS": "$(HOST_PLATFORM)",
"SWIFT_VERSION": swiftVersion,
])
],
targets: [
TestStandardTarget(
"tool",
type: .application,
buildPhases: [
TestSourcesBuildPhase(["main.swift"]),
TestFrameworksBuildPhase([
TestBuildFile(.target("staticlib")),
])
],
dependencies: [
"staticlib",
]
),
TestStandardTarget(
"staticlib",
type: .staticLibrary,
buildPhases: [
TestSourcesBuildPhase(["static.swift"]),
]
),
func makeTester(ldFlags: String = "", tmpDir: Path) async throws -> BuildOperationTester {
let testProject = try await TestProject(
"TestProject",
sourceRoot: tmpDir,
groupTree: TestGroup(
"SomeFiles",
children: [
TestFile("main.swift"),
TestFile("static.swift"),
]),
buildConfigurations: [
TestBuildConfiguration("Debug", buildSettings: [
"ARCHS": "$(ARCHS_STANDARD)",
"CODE_SIGNING_ALLOWED": "YES",
"CODE_SIGN_IDENTITY": "-",
"CODE_SIGN_ENTITLEMENTS": "Entitlements.plist",
"DEFINES_MODULE": "YES",
"GENERATE_INFOPLIST_FILE": "YES",
"PRODUCT_NAME": "$(TARGET_NAME)",
"SDKROOT": "$(HOST_PLATFORM)",
"SUPPORTED_PLATFORMS": "$(HOST_PLATFORM)",
"SWIFT_VERSION": swiftVersion,
"OTHER_LDFLAGS": ldFlags,
])
let core = try await getCore()
let tester = try await BuildOperationTester(core, testProject, simulated: false)

let projectDir = tester.workspace.projects[0].sourceRoot
],
targets: [
TestStandardTarget(
"tool",
type: .application,
buildPhases: [
TestSourcesBuildPhase(["main.swift"]),
TestFrameworksBuildPhase([
TestBuildFile(.target("staticlib")),
])
],
dependencies: [
"staticlib",
]
),
TestStandardTarget(
"staticlib",
type: .staticLibrary,
buildPhases: [
TestSourcesBuildPhase(["static.swift"]),
]
),
])
let core = try await getCore()
let tester = try await BuildOperationTester(core, testProject, simulated: false)

let projectDir = tester.workspace.projects[0].sourceRoot

try await tester.fs.writeFileContents(projectDir.join("main.swift")) { stream in
stream <<< "import staticlib\n"
stream <<< "staticLib()\n"
stream <<< "print(\"Hello world\")\n"
}

try await tester.fs.writeFileContents(projectDir.join("main.swift")) { stream in
stream <<< "import staticlib\n"
stream <<< "staticLib()\n"
stream <<< "print(\"Hello world\")\n"
}
try await tester.fs.writeFileContents(projectDir.join("static.swift")) { stream in
stream <<< "import Foundation\n"
stream <<< "public func staticLib() {\n"
stream <<< "_ = UserDefaults.standard\n"
stream <<< "}\n"
}

try await tester.fs.writeFileContents(projectDir.join("static.swift")) { stream in
stream <<< "import Foundation\n"
stream <<< "public func staticLib() {\n"
stream <<< "_ = UserDefaults.standard\n"
stream <<< "}\n"
}
try await tester.fs.writePlist(projectDir.join("Entitlements.plist"), .plDict([:]))

try await tester.fs.writePlist(projectDir.join("Entitlements.plist"), .plDict([:]))
return tester
}

@Test(.requireSDKs(.macOS), .requireSDKImports())
func basic() async throws {
try await withTemporaryDirectory { (tmpDir: Path) in
let tester = try await makeTester(tmpDir: tmpDir)
let provisioningInputs = [
"staticlib": ProvisioningTaskInputs(identityHash: "-", signedEntitlements: .plDict([:]), simulatedEntitlements: .plDict([:])),
"tool": ProvisioningTaskInputs(identityHash: "-", signedEntitlements: .plDict([:]), simulatedEntitlements: .plDict([:]))
Expand Down Expand Up @@ -182,5 +188,30 @@ fileprivate struct SDKImportsBuildOperationTests: CoreBasedTests {
}
}
}

@Test(.requireSDKs(.macOS), .requireSDKImports())
func disabledWhenLdClassicIsInUse() async throws {
for flags in ["-Xlinker -ld_classic", "-Wl,-ld_classic"] {
try await withTemporaryDirectory { (tmpDir: Path) in
let tester = try await makeTester(ldFlags: flags, tmpDir: tmpDir)
let provisioningInputs = [
"staticlib": ProvisioningTaskInputs(identityHash: "-", signedEntitlements: .plDict([:]), simulatedEntitlements: .plDict([:])),
"tool": ProvisioningTaskInputs(identityHash: "-", signedEntitlements: .plDict([:]), simulatedEntitlements: .plDict([:]))
]

let destination: RunDestinationInfo = .host
try await tester.checkBuild(runDestination: destination, signableTargets: Set(provisioningInputs.keys), signableTargetInputs: provisioningInputs) { results in
results.checkNoErrors()
results.checkWarning(.prefix("-ld_classic is deprecated"))

let derivedData = tmpDir.join("build/Debug")
let appResources = derivedData.join("tool.app/Contents/Resources")

let sdkImportsPath = appResources.join("tool_normal_x86_64_sdk_imports.json")
#expect(tester.fs.exists(sdkImportsPath) == false)
}
}
}
}
}