Skip to content

Commit 9612ab4

Browse files
authored
Merge pull request #623 from swiftlang/automerge/merge-main-2025-06-30_09-02
Merge `release/6.2` into `main`
2 parents 6988bf1 + ec83172 commit 9612ab4

File tree

8 files changed

+374
-46
lines changed

8 files changed

+374
-46
lines changed

Sources/SWBCore/Settings/BuiltinMacros.swift

Lines changed: 4 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")
@@ -1000,6 +1001,7 @@ public final class BuiltinMacros {
10001001
public static let SWIFT_ABI_CHECKER_EXCEPTIONS_FILE = BuiltinMacros.declareStringMacro("SWIFT_ABI_CHECKER_EXCEPTIONS_FILE")
10011002
public static let SWIFT_ABI_GENERATION_TOOL_OUTPUT_DIR = BuiltinMacros.declareStringMacro("SWIFT_ABI_GENERATION_TOOL_OUTPUT_DIR")
10021003
public static let SWIFT_ACCESS_NOTES_PATH = BuiltinMacros.declareStringMacro("SWIFT_ACCESS_NOTES_PATH")
1004+
public static let SWIFT_ACTIVE_COMPILATION_CONDITIONS = BuiltinMacros.declareStringListMacro("SWIFT_ACTIVE_COMPILATION_CONDITIONS")
10031005
public static let SWIFT_ALLOW_INSTALL_OBJC_HEADER = BuiltinMacros.declareBooleanMacro("SWIFT_ALLOW_INSTALL_OBJC_HEADER")
10041006
public static let __SWIFT_ALLOW_INSTALL_OBJC_HEADER_MESSAGE = BuiltinMacros.declareStringMacro("__SWIFT_ALLOW_INSTALL_OBJC_HEADER_MESSAGE")
10051007
public static let SWIFT_COMPILATION_MODE = BuiltinMacros.declareStringMacro("SWIFT_COMPILATION_MODE")
@@ -1377,6 +1379,7 @@ public final class BuiltinMacros {
13771379
ADDITIONAL_SDK_DIRS,
13781380
AD_HOC_CODE_SIGNING_ALLOWED,
13791381
__AD_HOC_CODE_SIGNING_NOT_ALLOWED_SUPPLEMENTAL_MESSAGE,
1382+
ADD_MERGEABLE_DEBUG_HOOK,
13801383
AGGREGATE_TRACKED_DOMAINS,
13811384
ALLOW_BUILD_REQUEST_OVERRIDES,
13821385
ALLOW_DISJOINTED_DIRECTORIES_AS_DEPENDENCIES,
@@ -2174,6 +2177,7 @@ public final class BuiltinMacros {
21742177
SWIFT_ABI_CHECKER_EXCEPTIONS_FILE,
21752178
SWIFT_ABI_GENERATION_TOOL_OUTPUT_DIR,
21762179
SWIFT_ACCESS_NOTES_PATH,
2180+
SWIFT_ACTIVE_COMPILATION_CONDITIONS,
21772181
SWIFT_ALLOW_INSTALL_OBJC_HEADER,
21782182
__SWIFT_ALLOW_INSTALL_OBJC_HEADER_MESSAGE,
21792183
SWIFT_COMPILATION_MODE,

Sources/SWBCore/Settings/Settings.swift

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,7 @@ private class SettingsBuilder {
15451545
}
15461546

15471547
// Push the target derived overriding settings.
1548-
addTargetDerivedSettings(self.target, boundProperties.platform, boundProperties.sdk, boundProperties.sdkVariant)
1548+
addTargetDerivedSettings(self.target, boundProperties.platform, boundProperties.sdk, boundProperties.sdkVariant, specLookupContext)
15491549

15501550
if boundDeploymentTarget.platformDeploymentTargetMacro == BuiltinMacros.DRIVERKIT_DEPLOYMENT_TARGET, let deploymentTarget = boundDeploymentTarget.platformDeploymentTarget, deploymentTarget < Version(20) {
15511551
var table = MacroValueAssignmentTable(namespace: userNamespace)
@@ -2030,13 +2030,13 @@ private class SettingsBuilder {
20302030
/// Add the derived overriding settings for the target. These are settings whose values depend on the whole stack of build settings, and include settings which are forced to a value under certain conditions, and settings whose value is wholly derived from other settings. They override settings from all lower levels, and thus cannot be overridden by (for example) xcodebuild or run destination overrides, so settings should only be assigned here when they represent true boundary conditions which users should never want to or be able to override.
20312031
///
20322032
/// These are only added if we're constructing settings for a target.
2033-
func addTargetDerivedSettings(_ target: Target?, _ platform: Platform?, _ sdk: SDK?, _ sdkVariant: SDKVariant?) {
2033+
func addTargetDerivedSettings(_ target: Target?, _ platform: Platform?, _ sdk: SDK?, _ sdkVariant: SDKVariant?, _ specLookupContext: any SpecLookupContext) {
20342034
guard target != nil else {
20352035
return
20362036
}
20372037

20382038
push(getTargetDerivedSettings(platform, sdk, sdkVariant), .exportedForNative)
2039-
addSecondaryTargetDerivedSettings(sdk)
2039+
addSecondaryTargetDerivedSettings(sdk, specLookupContext)
20402040
}
20412041

20422042
/// Add the core derived overriding settings for the target.
@@ -2129,7 +2129,7 @@ private class SettingsBuilder {
21292129
/// Add derived settings for the target which are themselves derived from the core target derived settings computed above. (Whee!)
21302130
///
21312131
/// This is called from `addTargetDerivedSettings().
2132-
func addSecondaryTargetDerivedSettings(_ sdk: SDK?) {
2132+
func addSecondaryTargetDerivedSettings(_ sdk: SDK?, _ specLookupContext: any SpecLookupContext) {
21332133
// Mergeable library/merged binary support.
21342134
do {
21352135
let scope = createScope(sdkToUse: sdk)
@@ -2155,22 +2155,36 @@ private class SettingsBuilder {
21552155
table.push(BuiltinMacros.MERGE_LINKED_LIBRARIES, literal: true)
21562156
}
21572157

2158-
// If this is a mergeable library, then build it as mergeable if this is a release build.
2159-
if scope.evaluate(BuiltinMacros.MERGEABLE_LIBRARY), !scope.evaluate(BuiltinMacros.IS_UNOPTIMIZED_BUILD) {
2160-
table.push(BuiltinMacros.MAKE_MERGEABLE, literal: true)
2158+
// 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.
2159+
if scope.evaluate(BuiltinMacros.MERGEABLE_LIBRARY) {
2160+
if scope.evaluate(BuiltinMacros.IS_UNOPTIMIZED_BUILD) {
2161+
table.push(BuiltinMacros.ADD_MERGEABLE_DEBUG_HOOK, literal: true)
2162+
}
2163+
else {
2164+
table.push(BuiltinMacros.MAKE_MERGEABLE, literal: true)
2165+
}
21612166
}
21622167

21632168
push(table, .exportedForNative)
21642169
}
21652170
do {
21662171
let scope = createScope(sdkToUse: sdk)
2172+
var table = MacroValueAssignmentTable(namespace: core.specRegistry.internalMacroNamespace)
21672173

21682174
// If the product is being built as mergeable, then that overrides certain other settings.
21692175
if scope.evaluate(BuiltinMacros.MAKE_MERGEABLE) {
2170-
var table = MacroValueAssignmentTable(namespace: core.specRegistry.internalMacroNamespace)
21712176
table.push(BuiltinMacros.STRIP_INSTALLED_PRODUCT, literal: false)
2172-
push(table, .exportedForNative)
21732177
}
2178+
2179+
// Even if not being merged in this build, a mergeable library still uses a generated bundle lookup helper to power #bundle support.
2180+
if scope.evaluate(BuiltinMacros.MERGEABLE_LIBRARY) {
2181+
let pathResolver = FilePathResolver(scope: scope)
2182+
if (target as? StandardTarget)?.sourcesBuildPhase?.containsSwiftSources(workspaceContext.workspace, specLookupContext, scope, pathResolver) ?? false {
2183+
table.push(BuiltinMacros.SWIFT_ACTIVE_COMPILATION_CONDITIONS, BuiltinMacros.namespace.parseStringList(["$(inherited)", "SWIFT_BUNDLE_LOOKUP_HELPER_AVAILABLE"]))
2184+
}
2185+
}
2186+
2187+
push(table, .exportedForNative)
21742188
}
21752189
}
21762190

Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,9 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
774774
let packageTargetBundleAccessorResult = await generatePackageTargetBundleAccessorResult(scope)
775775
tasks += packageTargetBundleAccessorResult?.tasks ?? []
776776

777+
let bundleLookupHelperResult = await generateBundleLookupHelper(scope)
778+
tasks += bundleLookupHelperResult?.tasks ?? []
779+
777780
let embedInCodeAccessorResult: GeneratedResourceAccessorResult?
778781
if scope.evaluate(BuiltinMacros.GENERATE_EMBED_IN_CODE_ACCESSORS), let configuredTarget = context.configuredTarget, buildPhase.containsSwiftSources(context.workspaceContext.workspace, context, scope, context.filePathResolver) {
779782
let ownTargetBuildFilesToEmbed = ((context.workspaceContext.workspace.target(for: configuredTarget.target.guid) as? StandardTarget)?.buildPhases.compactMap { $0 as? BuildPhaseWithBuildFiles }.flatMap { $0.buildFiles }.filter { $0.resourceRule == .embedInCode }) ?? []
@@ -871,6 +874,10 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
871874
result.append((packageTargetBundleAccessorResult.fileToBuild, packageTargetBundleAccessorResult.fileToBuildFileType, /* shouldUsePrefixHeader */ false))
872875
}
873876

877+
if let bundleLookupHelperResult {
878+
result.append((bundleLookupHelperResult.fileToBuild, bundleLookupHelperResult.fileToBuildFileType, /* shouldUsePrefixHeader */ false))
879+
}
880+
874881
if let embedInCodeAccessorResult {
875882
result.append((embedInCodeAccessorResult.fileToBuild, embedInCodeAccessorResult.fileToBuildFileType, /* shouldUsePrefixHeader */ false))
876883
}
@@ -1195,11 +1202,17 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
11951202
let buildFilesContext = BuildFilesProcessingContext(scope, belongsToPreferredArch: preferredArch == nil || preferredArch == arch, currentArchSpec: currentArchSpec)
11961203
var perArchTasks: [any PlannedTask] = []
11971204
await groupAndAddTasksForFiles(self, buildFilesContext, scope, filterToAPIRules: isForAPI, filterToHeaderRules: isForHeaders, &perArchTasks, extraResolvedBuildFiles: {
1205+
var result: [(Path, FileTypeSpec, Bool)] = []
1206+
11981207
if let packageTargetBundleAccessorResult {
1199-
return [(packageTargetBundleAccessorResult.fileToBuild, packageTargetBundleAccessorResult.fileToBuildFileType, /* shouldUsePrefixHeader */ false)]
1200-
} else {
1201-
return []
1208+
result.append((packageTargetBundleAccessorResult.fileToBuild, packageTargetBundleAccessorResult.fileToBuildFileType, /* shouldUsePrefixHeader */ false))
1209+
}
1210+
1211+
if let bundleLookupHelperResult {
1212+
result.append((bundleLookupHelperResult.fileToBuild, bundleLookupHelperResult.fileToBuildFileType, /* shouldUsePrefixHeader */ false))
12021213
}
1214+
1215+
return result
12031216
}())
12041217

12051218
// Add all the collected per-arch tasks.
@@ -1728,7 +1741,43 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
17281741
return GeneratedResourceAccessorResult(tasks: tasks, fileToBuild: filePath, fileToBuildFileType: context.lookupFileType(fileName: "sourcecode.swift")!)
17291742
}
17301743

1744+
/// Generates a task for creating the `__BundleLookupHelper` class to enable `#bundle` support in mergeable libraries.
1745+
private func generateBundleLookupHelper(_ scope: MacroEvaluationScope) async -> GeneratedResourceAccessorResult? {
1746+
// We generate a __BundleLookupHelper class that Foundation's #bundle macro can use to lookup the resource bundle.
1747+
// ld will inject a mapping of class pointers to the correct resource bundle so that BundleForClass works at runtime.
1748+
1749+
// We only need this treatment for mergeable libraries at this time.
1750+
// Package targets do something similar but they generate the Bundle.module extensions and #bundle calls that.
1751+
1752+
// We need to do this for all mergeable libraries, even if it will just be re-exported in this build.
1753+
guard scope.evaluate(BuiltinMacros.MERGEABLE_LIBRARY) else {
1754+
return nil
1755+
}
1756+
1757+
let workspace = self.context.workspaceContext.workspace
1758+
1759+
// #bundle is a Swift macro, so this is only needed for Swift code.
1760+
guard buildPhase.containsSwiftSources(workspace, context, scope, context.filePathResolver) else {
1761+
return nil
1762+
}
1763+
1764+
let filePath = scope.evaluate(BuiltinMacros.DERIVED_SOURCES_DIR).join("bundle_lookup_helper.swift")
1765+
1766+
// We need one class with a relatively unique name that #bundle can use for bundle lookup.
1767+
// It cannot be less visible than internal since the #bundle expansion needs to be able to resolve it AND so ld will record the class->bundle mapping.
1768+
// We intentionally do not want a Foundation dependency in this generated code, so don't import Foundation.
1769+
let content = "internal class __BundleLookupHelper {}"
1770+
1771+
var tasks = [any PlannedTask]()
1772+
await appendGeneratedTasks(&tasks) { delegate in
1773+
context.writeFileSpec.constructFileTasks(CommandBuildContext(producer: context, scope: context.settings.globalScope, inputs: [], output: filePath), delegate, contents: ByteString(encodingAsUTF8: content), permissions: nil, preparesForIndexing: true, additionalTaskOrderingOptions: [.immediate, .ignorePhaseOrdering])
1774+
}
1775+
return GeneratedResourceAccessorResult(tasks: tasks, fileToBuild: filePath, fileToBuildFileType: context.lookupFileType(fileName: "sourcecode.swift")!)
1776+
}
1777+
17311778
/// Generates a task for creating the resource bundle accessor for package targets.
1779+
///
1780+
/// This produces the `Bundle.module` accessor.
17321781
private func generatePackageTargetBundleAccessorResult(_ scope: MacroEvaluationScope) async -> GeneratedResourceAccessorResult? {
17331782
let bundleName = scope.evaluate(BuiltinMacros.PACKAGE_RESOURCE_BUNDLE_NAME)
17341783
let isRegularPackage = scope.evaluate(BuiltinMacros.PACKAGE_RESOURCE_TARGET_KIND) == .regular

Sources/SWBTaskExecution/TaskActions/InfoPlistProcessorTaskAction.swift

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,35 +1451,49 @@ public final class InfoPlistProcessorTaskAction: TaskAction
14511451
case iOS
14521452
case tvOS
14531453
case watchOS
1454+
case visionOS = "xrOS" // must be "xrOS" as it's compared against Platform.familyName
14541455
}
14551456

14561457
/// The values of the key that are deprecated, if only specific values are deprecated. `nil` indicates the key as a whole is deprecated.
14571458
let values: [PropertyListItem]?
14581459

1459-
/// An infix to display in the "use (alternative) instead" portion of the deprecation message.
1460-
let alternate: String
1460+
enum MoreInfo {
1461+
/// An infix to display in the "use (alternative) instead" portion of the deprecation message.
1462+
case alternate(String)
1463+
1464+
case ignored(String)
1465+
}
1466+
1467+
let moreInfo: MoreInfo
14611468

14621469
/// Mapping of platforms and the version of that platform beginning in which the deprecation warning should be shown.
14631470
///
14641471
/// If the version is empty, the warning will always be shown for that platform.
14651472
/// If there is no version value present for a platform at all, no warning will ever be shown for that platform.
14661473
let deprecationVersions: [DeprecationPlatform: Version]
14671474

1468-
init(values: [PropertyListItem]? = nil, alternate: String, deprecationVersions: [DeprecationPlatform: Version]) {
1475+
init(values: [PropertyListItem]? = nil, moreInfo: MoreInfo, deprecationVersions: [DeprecationPlatform: Version]) {
14691476
self.values = values
1470-
self.alternate = alternate
1477+
self.moreInfo = moreInfo
14711478
self.deprecationVersions = deprecationVersions
14721479
}
14731480
}
14741481

14751482
let plistKeyDeprecationInfo: [PropertyListKeyPath: DeprecationInfo] = [
1476-
"UILaunchImages": .init(alternate: "launch storyboards", deprecationVersions: [.iOS: Version(), .tvOS: Version(13)]),
1477-
"CLKComplicationSupportedFamilies": .init(alternate: "the ClockKit complications API", deprecationVersions: [.watchOS: Version(7)]),
1478-
PropertyListKeyPath(.dict(.equal("NSAppTransportSecurity")), .dict(.equal("NSExceptionDomains")), .dict(.any), .any(.equal("NSExceptionMinimumTLSVersion"))): .init(values: [.plString("TLSv1.0"), .plString("TLSv1.1")], alternate: "TLSv1.2 or TLSv1.3", deprecationVersions: [
1483+
"UILaunchImages": .init(moreInfo: .alternate("launch storyboards"), deprecationVersions: [.iOS: Version(), .tvOS: Version(13)]),
1484+
"CLKComplicationSupportedFamilies": .init(moreInfo: .alternate("the ClockKit complications API"), deprecationVersions: [.watchOS: Version(7)]),
1485+
PropertyListKeyPath(.dict(.equal("NSAppTransportSecurity")), .dict(.equal("NSExceptionDomains")), .dict(.any), .any(.equal("NSExceptionMinimumTLSVersion"))): .init(values: [.plString("TLSv1.0"), .plString("TLSv1.1")], moreInfo: .alternate("TLSv1.2 or TLSv1.3"), deprecationVersions: [
14791486
.macOS: Version(12),
14801487
.iOS: Version(15),
14811488
.tvOS: Version(15),
14821489
.watchOS: Version(8)
1490+
]),
1491+
"UIRequiresFullScreen": .init(moreInfo: .ignored("See the UIRequiresFullScreen documentation for more details."), deprecationVersions: [
1492+
.macOS: Version(26),
1493+
.iOS: Version(26),
1494+
.tvOS: Version(26),
1495+
.watchOS: Version(26),
1496+
.visionOS: Version(26),
14831497
])
14841498
]
14851499

@@ -1497,11 +1511,19 @@ public final class InfoPlistProcessorTaskAction: TaskAction
14971511
prefixPart = "'\(item.actualKeyPath.joined(separator: "' => '"))'"
14981512
}
14991513

1514+
let suffixPart: String
1515+
switch info.moreInfo {
1516+
case let .alternate(alternate):
1517+
suffixPart = ", use \(alternate) instead."
1518+
case let .ignored(ignored):
1519+
suffixPart = " and will be ignored in a future release. \(ignored)"
1520+
}
1521+
15001522
let message: String
15011523
if deprecationVersion > Version() {
1502-
message = "\(prefixPart) has been deprecated starting in \(context.platform?.familyDisplayName ?? "") \(deprecationVersion.canonicalDeploymentTargetForm.description), use \(info.alternate) instead."
1524+
message = "\(prefixPart) has been deprecated starting in \(context.platform?.familyDisplayName ?? "") \(deprecationVersion.canonicalDeploymentTargetForm.description)\(suffixPart)"
15031525
} else {
1504-
message = "\(prefixPart) has been deprecated, use \(info.alternate) instead."
1526+
message = "\(prefixPart) has been deprecated\(suffixPart)"
15051527
}
15061528

15071529
if let deploymentTarget = deploymentTarget, deploymentTarget >= deprecationVersion {

Sources/SWBTestSupport/CoreBasedTests.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,13 @@ extension CoreBasedTests {
371371
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)
372372
}
373373

374+
package func discoveredLdLinkerInfo(at toolPath: Path) async throws -> DiscoveredLdLinkerToolSpecInfo {
375+
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 {
376+
throw StubError.error("Could not get tool spec info for LdLinkerSpec")
377+
}
378+
return info
379+
}
380+
374381
package func discoveredTAPIToolInfo(at toolPath: Path) async throws -> DiscoveredTAPIToolSpecInfo {
375382
try await SWBCore.discoveredTAPIToolInfo(MockCommandProducer(core: getCore(), productTypeIdentifier: "com.apple.product-type.framework", platform: nil, useStandardExecutableSearchPaths: true, toolchain: nil, fs: PseudoFS()), AlwaysDeferredCoreClientDelegate(), at: toolPath)
376383
}

0 commit comments

Comments
 (0)