Skip to content
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
2 changes: 2 additions & 0 deletions Sources/SWBCore/Settings/BuiltinMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ public final class BuiltinMacros {

// MARK: Mergeable libraries macros

public static let ADD_MERGEABLE_DEBUG_HOOK = BuiltinMacros.declareBooleanMacro("ADD_MERGEABLE_DEBUG_HOOK")
public static let AUTOMATICALLY_MERGE_DEPENDENCIES = BuiltinMacros.declareBooleanMacro("AUTOMATICALLY_MERGE_DEPENDENCIES")
public static let MERGEABLE_LIBRARY = BuiltinMacros.declareBooleanMacro("MERGEABLE_LIBRARY")
public static let DONT_EMBED_REEXPORTED_MERGEABLE_LIBRARIES = BuiltinMacros.declareBooleanMacro("DONT_EMBED_REEXPORTED_MERGEABLE_LIBRARIES")
Expand Down Expand Up @@ -1369,6 +1370,7 @@ public final class BuiltinMacros {
ADDITIONAL_SDK_DIRS,
AD_HOC_CODE_SIGNING_ALLOWED,
__AD_HOC_CODE_SIGNING_NOT_ALLOWED_SUPPLEMENTAL_MESSAGE,
ADD_MERGEABLE_DEBUG_HOOK,
AGGREGATE_TRACKED_DOMAINS,
ALLOW_BUILD_REQUEST_OVERRIDES,
ALLOW_DISJOINTED_DIRECTORIES_AS_DEPENDENCIES,
Expand Down
11 changes: 8 additions & 3 deletions Sources/SWBCore/Settings/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2164,9 +2164,14 @@ private class SettingsBuilder {
table.push(BuiltinMacros.MERGE_LINKED_LIBRARIES, literal: true)
}

// If this is a mergeable library, then build it as mergeable if this is a release build.
if scope.evaluate(BuiltinMacros.MERGEABLE_LIBRARY), !scope.evaluate(BuiltinMacros.IS_UNOPTIMIZED_BUILD) {
table.push(BuiltinMacros.MAKE_MERGEABLE, literal: true)
// 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.
if scope.evaluate(BuiltinMacros.MERGEABLE_LIBRARY) {
if scope.evaluate(BuiltinMacros.IS_UNOPTIMIZED_BUILD) {
table.push(BuiltinMacros.ADD_MERGEABLE_DEBUG_HOOK, literal: true)
}
else {
table.push(BuiltinMacros.MAKE_MERGEABLE, literal: true)
}
}

push(table, .exportedForNative)
Expand Down
7 changes: 7 additions & 0 deletions Sources/SWBTestSupport/CoreBasedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,13 @@ extension CoreBasedTests {
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)
}

package func discoveredLdLinkerInfo(at toolPath: Path) async throws -> DiscoveredLdLinkerToolSpecInfo {
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 {
throw StubError.error("Could not get tool spec info for LdLinkerSpec")
}
return info
}

package func discoveredTAPIToolInfo(at toolPath: Path) async throws -> DiscoveredTAPIToolSpecInfo {
try await SWBCore.discoveredTAPIToolInfo(MockCommandProducer(core: getCore(), productTypeIdentifier: "com.apple.product-type.framework", platform: nil, useStandardExecutableSearchPaths: true, toolchain: nil, fs: PseudoFS()), AlwaysDeferredCoreClientDelegate(), at: toolPath)
}
Expand Down
13 changes: 13 additions & 0 deletions Sources/SWBUniversalPlatform/Specs/Ld.xcspec
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,19 @@
};
},

{ Name = LD_ADD_MERGEABLE_DEBUG_HOOK;
Type = Boolean;
DefaultValue = "$(ADD_MERGEABLE_DEBUG_HOOK)";
CommandLineArgs = {
YES = (
"-Xlinker",
"-add_mergeable_debug_hook",
);
NO = ();
};
SupportedVersionRanges = ( "1217" );
},

{
Name = "LD_SHARED_CACHE_ELIGIBLE";
Type = Enumeration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ import MachO

@Suite(.requireXcode16())
fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {

private func linkerSupportsMergeableDebugHook() async throws -> Bool {
guard let ldPath = try await ldPath else {
throw StubError.error("Could not get path for ld linker.")
}
let info = try await discoveredLdLinkerInfo(at: ldPath)
guard let version = info.toolVersion else {
throw StubError.error("Could not get version for ld linker at '\(ldPath.str).")
}
return version >= Version(1217)
}

@Test(.requireSDKs(.iOS))
func automaticMergedFrameworkCreation() async throws {
try await testAutomaticMergedFrameworkCreation(useAppStoreCodelessFrameworksWorkaround: true)
Expand Down Expand Up @@ -164,6 +176,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false)
let SRCROOT = testWorkspace.sourceRoot.join("aProject")
let signableTargets: Set<String> = Set(tester.workspace.projects[0].targets.map({ $0.name }))
let supportsMergeableDebugHook = try await linkerSupportsMergeableDebugHook()

// Write the source files.
try await tester.fs.writeFileContents(SRCROOT.join("Sources/Application.swift")) { contents in
Expand Down Expand Up @@ -216,6 +229,9 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
results.checkTask(.matchTargetName(targetName), .matchRuleType("SwiftCompile")) { _ in }
results.checkTask(.matchTargetName(targetName), .matchRuleType("Ld")) { task in
task.checkCommandLineDoesNotContain("-make_mergeable")
if supportsMergeableDebugHook {
task.checkCommandLineContains("-add_mergeable_debug_hook")
}
task.checkCommandLineContains(["-o", "\(SYMROOT)/Debug-iphoneos/\(targetName).framework/\(targetName)"])
}
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
Expand All @@ -234,6 +250,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
task.checkCommandLineContains(["-o", "\(SYMROOT)/Debug-iphoneos/\(targetName).framework/\(targetName)"])
task.checkCommandLineDoesNotContain("-merge_framework")
task.checkCommandLineDoesNotContain("-make_mergeable")
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
}
results.checkTask(.matchTargetName(targetName), .matchRuleType("CodeSign"), .matchRuleItemBasename("\(targetName).framework")) { _ in }
// Check that the mergeable frameworks' binaries were copied in and re-signed.
Expand Down Expand Up @@ -396,6 +413,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
results.checkTask(.matchTargetName(targetName), .matchRuleType("SwiftCompile")) { _ in }
results.checkTask(.matchTargetName(targetName), .matchRuleType("Ld")) { task in
task.checkCommandLineContains("-make_mergeable")
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
task.checkCommandLineContains(["-o", "\(OBJROOT)/UninstalledProducts/iphoneos/\(targetName).framework/\(targetName)"])
}
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
Expand All @@ -415,6 +433,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
task.checkCommandLineContains(["-Xlinker", "-merge_framework", "-Xlinker", "FwkTarget2"])
task.checkCommandLineContains(["-o", "\(OBJROOT)/UninstalledProducts/iphoneos/\(targetName).framework/\(targetName)"])
task.checkCommandLineDoesNotContain("-make_mergeable")
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
task.checkCommandLineDoesNotContain("-no_merge_framework")
}
results.checkTask(.matchTargetName(targetName), .matchRuleType("Strip")) { _ in }
Expand Down Expand Up @@ -649,6 +668,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
let SRCROOT_App = testWorkspace.sourceRoot.join("AppProject")
let SRCROOT_Fwk = testWorkspace.sourceRoot.join("FwkProject")
let signableTargets: Set<String> = Set(tester.workspace.projects.flatMap({$0.targets}).map({ $0.name }))
let supportsMergeableDebugHook = try await linkerSupportsMergeableDebugHook()

// Write the source files.
try await tester.fs.writeFileContents(SRCROOT_App.join("Sources/Application.swift")) { contents in
Expand Down Expand Up @@ -698,6 +718,9 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
results.checkTask(.matchTargetName(targetName), .matchRuleType("SwiftCompile")) { _ in }
results.checkTask(.matchTargetName(targetName), .matchRuleType("Ld")) { task in
task.checkCommandLineDoesNotContain("-make_mergeable")
if supportsMergeableDebugHook {
task.checkCommandLineContains("-add_mergeable_debug_hook")
}
task.checkCommandLineContains(["-o", "\(SYMROOT)/Config-iphoneos/\(targetName).framework/\(targetName)"])
}
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
Expand Down Expand Up @@ -855,6 +878,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
results.checkTask(.matchTargetName(targetName), .matchRuleType("SwiftCompile")) { _ in }
results.checkTask(.matchTargetName(targetName), .matchRuleType("Ld")) { task in
task.checkCommandLineContains("-make_mergeable")
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
task.checkCommandLineContains(["-o", "\(OBJROOT)/UninstalledProducts/iphoneos/\(targetName).framework/\(targetName)"])
}
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
Expand All @@ -876,6 +900,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
task.checkCommandLineContains(["-Xlinker", "-merge_library", "-Xlinker", "\(OBJROOT)/UninstalledProducts/iphoneos/\(fwkTargetName).framework/\(fwkTargetName)"])
task.checkCommandLineContains(["-o", "\(DSTROOT)/Applications/\(targetName).app/\(targetName)"])
task.checkCommandLineDoesNotContain("-make_mergeable")
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
task.checkCommandLineDoesNotContain("-no_merge_framework")
}
// Check that we're excluding the binary when embedding the mergeable targets, but not the merged target.
Expand Down Expand Up @@ -1512,6 +1537,7 @@ fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests {
task.checkCommandLineContains(["-Xlinker", "-merge-l\(libBaseName)"])
task.checkCommandLineContains(["-o", "\(OBJROOT)/UninstalledProducts/iphoneos/\(targetName).framework/\(targetName)"])
task.checkCommandLineDoesNotContain("-make_mergeable")
task.checkCommandLineDoesNotContain("-add_mergeable_debug_hook")
task.checkCommandLineDoesNotContain("-no_merge_framework")
}
results.checkTasks(.matchTargetName(targetName), .matchRuleType("Copy")) { _ in /* likely Swift-related */ }
Expand Down
Loading
Loading