@@ -771,6 +771,9 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
771
771
let packageTargetBundleAccessorResult = await generatePackageTargetBundleAccessorResult ( scope)
772
772
tasks += packageTargetBundleAccessorResult? . tasks ?? [ ]
773
773
774
+ let bundleLookupHelperResult = await generateBundleLookupHelper ( scope)
775
+ tasks += bundleLookupHelperResult? . tasks ?? [ ]
776
+
774
777
let embedInCodeAccessorResult : GeneratedResourceAccessorResult ?
775
778
if scope. evaluate ( BuiltinMacros . GENERATE_EMBED_IN_CODE_ACCESSORS) , let configuredTarget = context. configuredTarget, buildPhase. containsSwiftSources ( context. workspaceContext. workspace, context, scope, context. filePathResolver) {
776
779
let ownTargetBuildFilesToEmbed = ( ( context. workspaceContext. workspace. target ( for: configuredTarget. target. guid) as? StandardTarget ) ? . buildPhases. compactMap { $0 as? BuildPhaseWithBuildFiles } . flatMap { $0. buildFiles } . filter { $0. resourceRule == . embedInCode } ) ?? [ ]
@@ -868,6 +871,10 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
868
871
result. append ( ( packageTargetBundleAccessorResult. fileToBuild, packageTargetBundleAccessorResult. fileToBuildFileType, /* shouldUsePrefixHeader */ false ) )
869
872
}
870
873
874
+ if let bundleLookupHelperResult {
875
+ result. append ( ( bundleLookupHelperResult. fileToBuild, bundleLookupHelperResult. fileToBuildFileType, /* shouldUsePrefixHeader */ false ) )
876
+ }
877
+
871
878
if let embedInCodeAccessorResult {
872
879
result. append ( ( embedInCodeAccessorResult. fileToBuild, embedInCodeAccessorResult. fileToBuildFileType, /* shouldUsePrefixHeader */ false ) )
873
880
}
@@ -1192,11 +1199,17 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
1192
1199
let buildFilesContext = BuildFilesProcessingContext ( scope, belongsToPreferredArch: preferredArch == nil || preferredArch == arch, currentArchSpec: currentArchSpec)
1193
1200
var perArchTasks : [ any PlannedTask ] = [ ]
1194
1201
await groupAndAddTasksForFiles ( self , buildFilesContext, scope, filterToAPIRules: isForAPI, filterToHeaderRules: isForHeaders, & perArchTasks, extraResolvedBuildFiles: {
1202
+ var result : [ ( Path , FileTypeSpec , Bool ) ] = [ ]
1203
+
1195
1204
if let packageTargetBundleAccessorResult {
1196
- return [ ( packageTargetBundleAccessorResult. fileToBuild, packageTargetBundleAccessorResult. fileToBuildFileType, /* shouldUsePrefixHeader */ false ) ]
1197
- } else {
1198
- return [ ]
1205
+ result. append ( ( packageTargetBundleAccessorResult. fileToBuild, packageTargetBundleAccessorResult. fileToBuildFileType, /* shouldUsePrefixHeader */ false ) )
1206
+ }
1207
+
1208
+ if let bundleLookupHelperResult {
1209
+ result. append ( ( bundleLookupHelperResult. fileToBuild, bundleLookupHelperResult. fileToBuildFileType, /* shouldUsePrefixHeader */ false ) )
1199
1210
}
1211
+
1212
+ return result
1200
1213
} ( ) )
1201
1214
1202
1215
// Add all the collected per-arch tasks.
@@ -1725,7 +1738,43 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase
1725
1738
return GeneratedResourceAccessorResult ( tasks: tasks, fileToBuild: filePath, fileToBuildFileType: context. lookupFileType ( fileName: " sourcecode.swift " ) !)
1726
1739
}
1727
1740
1741
+ /// Generates a task for creating the `__BundleLookupHelper` class to enable `#bundle` support in mergeable libraries.
1742
+ private func generateBundleLookupHelper( _ scope: MacroEvaluationScope ) async -> GeneratedResourceAccessorResult ? {
1743
+ // We generate a __BundleLookupHelper class that Foundation's #bundle macro can use to lookup the resource bundle.
1744
+ // ld will inject a mapping of class pointers to the correct resource bundle so that BundleForClass works at runtime.
1745
+
1746
+ // We only need this treatment for mergeable libraries at this time.
1747
+ // Package targets do something similar but they generate the Bundle.module extensions and #bundle calls that.
1748
+
1749
+ // We need to do this for all mergeable libraries, even if it will just be re-exported in this build.
1750
+ guard scope. evaluate ( BuiltinMacros . MERGEABLE_LIBRARY) else {
1751
+ return nil
1752
+ }
1753
+
1754
+ let workspace = self . context. workspaceContext. workspace
1755
+
1756
+ // #bundle is a Swift macro, so this is only needed for Swift code.
1757
+ guard buildPhase. containsSwiftSources ( workspace, context, scope, context. filePathResolver) else {
1758
+ return nil
1759
+ }
1760
+
1761
+ let filePath = scope. evaluate ( BuiltinMacros . DERIVED_SOURCES_DIR) . join ( " bundle_lookup_helper.swift " )
1762
+
1763
+ // We need one class with a relatively unique name that #bundle can use for bundle lookup.
1764
+ // 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.
1765
+ // We intentionally do not want a Foundation dependency in this generated code, so don't import Foundation.
1766
+ let content = " internal class __BundleLookupHelper {} "
1767
+
1768
+ var tasks = [ any PlannedTask ] ( )
1769
+ await appendGeneratedTasks ( & tasks) { delegate in
1770
+ 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] )
1771
+ }
1772
+ return GeneratedResourceAccessorResult ( tasks: tasks, fileToBuild: filePath, fileToBuildFileType: context. lookupFileType ( fileName: " sourcecode.swift " ) !)
1773
+ }
1774
+
1728
1775
/// Generates a task for creating the resource bundle accessor for package targets.
1776
+ ///
1777
+ /// This produces the `Bundle.module` accessor.
1729
1778
private func generatePackageTargetBundleAccessorResult( _ scope: MacroEvaluationScope ) async -> GeneratedResourceAccessorResult ? {
1730
1779
let bundleName = scope. evaluate ( BuiltinMacros . PACKAGE_RESOURCE_BUNDLE_NAME)
1731
1780
let isRegularPackage = scope. evaluate ( BuiltinMacros . PACKAGE_RESOURCE_TARGET_KIND) == . regular
0 commit comments