Skip to content

Commit 2dda86e

Browse files
committed
Pass -add_mergeable_debug_hook to the linker when linking a mergeable library in a debug (unoptimized) build.
rdar://151724474
1 parent eeb25a8 commit 2dda86e

File tree

6 files changed

+116
-18
lines changed

6 files changed

+116
-18
lines changed

Sources/SWBCore/Settings/BuiltinMacros.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ public final class BuiltinMacros {
420420

421421
// MARK: Mergeable libraries macros
422422

423+
public static let ADD_MERGEABLE_DEBUG_HOOK = BuiltinMacros.declareBooleanMacro("ADD_MERGEABLE_DEBUG_HOOK")
423424
public static let AUTOMATICALLY_MERGE_DEPENDENCIES = BuiltinMacros.declareBooleanMacro("AUTOMATICALLY_MERGE_DEPENDENCIES")
424425
public static let MERGEABLE_LIBRARY = BuiltinMacros.declareBooleanMacro("MERGEABLE_LIBRARY")
425426
public static let DONT_EMBED_REEXPORTED_MERGEABLE_LIBRARIES = BuiltinMacros.declareBooleanMacro("DONT_EMBED_REEXPORTED_MERGEABLE_LIBRARIES")
@@ -1371,6 +1372,7 @@ public final class BuiltinMacros {
13711372
ADDITIONAL_SDK_DIRS,
13721373
AD_HOC_CODE_SIGNING_ALLOWED,
13731374
__AD_HOC_CODE_SIGNING_NOT_ALLOWED_SUPPLEMENTAL_MESSAGE,
1375+
ADD_MERGEABLE_DEBUG_HOOK,
13741376
AGGREGATE_TRACKED_DOMAINS,
13751377
ALLOW_BUILD_REQUEST_OVERRIDES,
13761378
ALLOW_DISJOINTED_DIRECTORIES_AS_DEPENDENCIES,

Sources/SWBCore/Settings/Settings.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,9 +2164,14 @@ private class SettingsBuilder {
21642164
table.push(BuiltinMacros.MERGE_LINKED_LIBRARIES, literal: true)
21652165
}
21662166

2167-
// If this is a mergeable library, then build it as mergeable if this is a release build.
2168-
if scope.evaluate(BuiltinMacros.MERGEABLE_LIBRARY), !scope.evaluate(BuiltinMacros.IS_UNOPTIMIZED_BUILD) {
2169-
table.push(BuiltinMacros.MAKE_MERGEABLE, literal: true)
2167+
// If this is a mergeable library, for a release build we want to build it as mergeable, whereas for a debug build we want to add the mergeable debug hook.
2168+
if scope.evaluate(BuiltinMacros.MERGEABLE_LIBRARY) {
2169+
if scope.evaluate(BuiltinMacros.IS_UNOPTIMIZED_BUILD) {
2170+
table.push(BuiltinMacros.ADD_MERGEABLE_DEBUG_HOOK, literal: true)
2171+
}
2172+
else {
2173+
table.push(BuiltinMacros.MAKE_MERGEABLE, literal: true)
2174+
}
21702175
}
21712176

21722177
push(table, .exportedForNative)

Sources/SWBTestSupport/CoreBasedTests.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,13 @@ extension CoreBasedTests {
379379
try await SWBCore.discoveredSwiftCompilerInfo(MockCommandProducer(core: getCore(), productTypeIdentifier: "com.apple.product-type.framework", platform: nil, useStandardExecutableSearchPaths: true, toolchain: nil, fs: PseudoFS()), AlwaysDeferredCoreClientDelegate(), at: toolPath, blocklistsPathOverride: nil)
380380
}
381381

382+
package func discoveredLdLinkerInfo(at toolPath: Path) async throws -> DiscoveredLdLinkerToolSpecInfo {
383+
guard let info = try await SWBCore.discoveredLinkerToolsInfo(MockCommandProducer(core: getCore(), productTypeIdentifier: "com.apple.product-type.framework", platform: nil, useStandardExecutableSearchPaths: true, toolchain: nil, fs: PseudoFS()), AlwaysDeferredCoreClientDelegate(), at: toolPath) as? DiscoveredLdLinkerToolSpecInfo else {
384+
throw StubError.error("Could not get tool spec info for LdLinkerSpec")
385+
}
386+
return info
387+
}
388+
382389
package func discoveredTAPIToolInfo(at toolPath: Path) async throws -> DiscoveredTAPIToolSpecInfo {
383390
try await SWBCore.discoveredTAPIToolInfo(MockCommandProducer(core: getCore(), productTypeIdentifier: "com.apple.product-type.framework", platform: nil, useStandardExecutableSearchPaths: true, toolchain: nil, fs: PseudoFS()), AlwaysDeferredCoreClientDelegate(), at: toolPath)
384391
}

Sources/SWBUniversalPlatform/Specs/Ld.xcspec

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,19 @@
665665
};
666666
},
667667

668+
{ Name = LD_ADD_MERGEABLE_DEBUG_HOOK;
669+
Type = Boolean;
670+
DefaultValue = "$(ADD_MERGEABLE_DEBUG_HOOK)";
671+
CommandLineArgs = {
672+
YES = (
673+
"-Xlinker",
674+
"-add_mergeable_debug_hook",
675+
);
676+
NO = ();
677+
};
678+
SupportedVersionRanges = ( "1217" );
679+
},
680+
668681
{
669682
Name = "LD_SHARED_CACHE_ELIGIBLE";
670683
Type = Enumeration;

Tests/SWBBuildSystemTests/MergeableLibrariesBuildOperationTests.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ import MachO
2626

2727
@Suite(.requireXcode16())
2828
fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
29+
30+
private func linkerSupportsMergeableDebugHook() async throws -> Bool {
31+
guard let ldPath = try await ldPath else {
32+
throw StubError.error("Could not get path for ld linker.")
33+
}
34+
let info = try await discoveredLdLinkerInfo(at: ldPath)
35+
guard let version = info.toolVersion else {
36+
throw StubError.error("Could not get version for ld linker at '\(ldPath.str).")
37+
}
38+
return version >= Version(1217)
39+
}
40+
2941
@Test(.requireSDKs(.iOS))
3042
func automaticMergedFrameworkCreation() async throws {
3143
try await testAutomaticMergedFrameworkCreation(useAppStoreCodelessFrameworksWorkaround: true)
@@ -164,6 +176,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
164176
let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false)
165177
let SRCROOT = testWorkspace.sourceRoot.join("aProject")
166178
let signableTargets: Set<String> = Set(tester.workspace.projects[0].targets.map({ $0.name }))
179+
let supportsMergeableDebugHook = try await linkerSupportsMergeableDebugHook()
167180

168181
// Write the source files.
169182
try await tester.fs.writeFileContents(SRCROOT.join("Sources/Application.swift")) { contents in
@@ -216,6 +229,9 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
216229
results.checkTask(.matchTargetName(targetName), .matchRuleType("SwiftCompile")) { _ in }
217230
results.checkTask(.matchTargetName(targetName), .matchRuleType("Ld")) { task in
218231
task.checkCommandLineDoesNotContain("-make_mergeable")
232+
if supportsMergeableDebugHook {
233+
task.checkCommandLineContains("-add_mergeable_debug_hook")
234+
}
219235
task.checkCommandLineContains(["-o", "\(SYMROOT)/Debug-iphoneos/\(targetName).framework/\(targetName)"])
220236
}
221237
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
@@ -234,6 +250,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
234250
task.checkCommandLineContains(["-o", "\(SYMROOT)/Debug-iphoneos/\(targetName).framework/\(targetName)"])
235251
task.checkCommandLineDoesNotContain("-merge_framework")
236252
task.checkCommandLineDoesNotContain("-make_mergeable")
253+
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
237254
}
238255
results.checkTask(.matchTargetName(targetName), .matchRuleType("CodeSign"), .matchRuleItemBasename("\(targetName).framework")) { _ in }
239256
// Check that the mergeable frameworks' binaries were copied in and re-signed.
@@ -396,6 +413,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
396413
results.checkTask(.matchTargetName(targetName), .matchRuleType("SwiftCompile")) { _ in }
397414
results.checkTask(.matchTargetName(targetName), .matchRuleType("Ld")) { task in
398415
task.checkCommandLineContains("-make_mergeable")
416+
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
399417
task.checkCommandLineContains(["-o", "\(OBJROOT)/UninstalledProducts/iphoneos/\(targetName).framework/\(targetName)"])
400418
}
401419
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
@@ -415,6 +433,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
415433
task.checkCommandLineContains(["-Xlinker", "-merge_framework", "-Xlinker", "FwkTarget2"])
416434
task.checkCommandLineContains(["-o", "\(OBJROOT)/UninstalledProducts/iphoneos/\(targetName).framework/\(targetName)"])
417435
task.checkCommandLineDoesNotContain("-make_mergeable")
436+
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
418437
task.checkCommandLineDoesNotContain("-no_merge_framework")
419438
}
420439
results.checkTask(.matchTargetName(targetName), .matchRuleType("Strip")) { _ in }
@@ -649,6 +668,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
649668
let SRCROOT_App = testWorkspace.sourceRoot.join("AppProject")
650669
let SRCROOT_Fwk = testWorkspace.sourceRoot.join("FwkProject")
651670
let signableTargets: Set<String> = Set(tester.workspace.projects.flatMap({$0.targets}).map({ $0.name }))
671+
let supportsMergeableDebugHook = try await linkerSupportsMergeableDebugHook()
652672

653673
// Write the source files.
654674
try await tester.fs.writeFileContents(SRCROOT_App.join("Sources/Application.swift")) { contents in
@@ -698,6 +718,9 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
698718
results.checkTask(.matchTargetName(targetName), .matchRuleType("SwiftCompile")) { _ in }
699719
results.checkTask(.matchTargetName(targetName), .matchRuleType("Ld")) { task in
700720
task.checkCommandLineDoesNotContain("-make_mergeable")
721+
if supportsMergeableDebugHook {
722+
task.checkCommandLineContains("-add_mergeable_debug_hook")
723+
}
701724
task.checkCommandLineContains(["-o", "\(SYMROOT)/Config-iphoneos/\(targetName).framework/\(targetName)"])
702725
}
703726
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
@@ -855,6 +878,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
855878
results.checkTask(.matchTargetName(targetName), .matchRuleType("SwiftCompile")) { _ in }
856879
results.checkTask(.matchTargetName(targetName), .matchRuleType("Ld")) { task in
857880
task.checkCommandLineContains("-make_mergeable")
881+
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
858882
task.checkCommandLineContains(["-o", "\(OBJROOT)/UninstalledProducts/iphoneos/\(targetName).framework/\(targetName)"])
859883
}
860884
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
@@ -876,6 +900,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
876900
task.checkCommandLineContains(["-Xlinker", "-merge_library", "-Xlinker", "\(OBJROOT)/UninstalledProducts/iphoneos/\(fwkTargetName).framework/\(fwkTargetName)"])
877901
task.checkCommandLineContains(["-o", "\(DSTROOT)/Applications/\(targetName).app/\(targetName)"])
878902
task.checkCommandLineDoesNotContain("-make_mergeable")
903+
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
879904
task.checkCommandLineDoesNotContain("-no_merge_framework")
880905
}
881906
// Check that we're excluding the binary when embedding the mergeable targets, but not the merged target.
@@ -1512,6 +1537,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
15121537
task.checkCommandLineContains(["-Xlinker", "-merge-l\(libBaseName)"])
15131538
task.checkCommandLineContains(["-o", "\(OBJROOT)/UninstalledProducts/iphoneos/\(targetName).framework/\(targetName)"])
15141539
task.checkCommandLineDoesNotContain("-make_mergeable")
1540+
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
15151541
task.checkCommandLineDoesNotContain("-no_merge_framework")
15161542
}
15171543
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }

0 commit comments

Comments
 (0)