Skip to content

Commit 0dd66e8

Browse files
Introduce new defines to enable #bundle in Swift Packages (#8556)
Introduce Swift compilation conditions to support `#bundle` in Foundation. ### Motivation: This is the SwiftPM companion to `#bundle`. Pitch: https://forums.swift.org/t/pitch-introduce-bundle-macro/79288 Proposal: swiftlang/swift-foundation#1251 Implementation: swiftlang/swift-foundation#1274 ### Modifications: Define `SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE` when we'd like `#bundle` to call our generated `Bundle.module`. Define `SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE` when there are no resources and `#bundle` should complain about that. Leave them both undefined when we'd like `#bundle` to keep its default behavior of using the same bundle where the source code lives. ### Result: `#bundle` will point to the correct resource bundle when called from Swift Packages.
1 parent 1e1fecb commit 0dd66e8

File tree

7 files changed

+123
-6
lines changed

7 files changed

+123
-6
lines changed

Sources/Build/BuildDescription/SwiftModuleBuildDescription.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,12 @@ public final class SwiftModuleBuildDescription {
969969
break
970970
}
971971

972+
if bundlePath != nil {
973+
compilationConditions += ["-DSWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE"]
974+
} else {
975+
compilationConditions += ["-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE"]
976+
}
977+
972978
return compilationConditions
973979
}
974980

Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,20 @@ extension PackagePIFProjectBuilder {
596596
settings[.COREML_COMPILER_CONTAINER] = "swift-package"
597597
}
598598

599+
if sourceModule.usesSwift {
600+
// Leave an explicit indicator regarding whether we are generating a Bundle.module accessor.
601+
// This will be read by the #bundle macro defined in Foundation.
602+
if !shouldGenerateBundleAccessor {
603+
// No resources, so explicitly indicate that.
604+
// #bundle will then produce an error about there being no resources.
605+
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS].lazilyInitializeAndMutate(initialValue: ["$(inherited)"]) { $0.append("SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE") }
606+
} else if !(resourceBundleName?.isEmpty ?? true) {
607+
// We have an explicit resource bundle via Bundle.module.
608+
// #bundle should call into that.
609+
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS].lazilyInitializeAndMutate(initialValue: ["$(inherited)"]) { $0.append("SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE") }
610+
} // else we won't set either of those and just let #bundle point to the same bundle as the source code.
611+
}
612+
599613
if desiredModuleType == .macro {
600614
settings[.SWIFT_IMPLEMENTS_MACROS_FOR_MODULE_NAMES] = [sourceModule.c99name]
601615
}

Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ extension PackagePIFProjectBuilder {
245245

246246
if result.shouldGenerateBundleAccessor {
247247
settings[.GENERATE_RESOURCE_ACCESSORS] = "YES"
248+
249+
// Do not set `SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE` here since it is just going to point to the same bundle as code.
250+
// #bundle can use its default implementation for that.
248251
}
249252
if result.shouldGenerateEmbedInCodeAccessor {
250253
settings[.GENERATE_EMBED_IN_CODE_ACCESSORS] = "YES"
@@ -264,6 +267,12 @@ extension PackagePIFProjectBuilder {
264267

265268
if result.shouldGenerateBundleAccessor {
266269
settings[.GENERATE_RESOURCE_ACCESSORS] = "YES"
270+
271+
if mainModule.usesSwift {
272+
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS].lazilyInitializeAndMutate(initialValue: ["$(inherited)"]) { $0.append("SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE") }
273+
}
274+
} else if mainModule.usesSwift {
275+
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS].lazilyInitializeAndMutate(initialValue: ["$(inherited)"]) { $0.append("SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE") }
267276
}
268277
if result.shouldGenerateEmbedInCodeAccessor {
269278
settings[.GENERATE_EMBED_IN_CODE_ACCESSORS] = "YES"
@@ -305,6 +314,9 @@ extension PackagePIFProjectBuilder {
305314
settings[.GENERATE_RESOURCE_ACCESSORS] = "YES"
306315
settings[.GENERATE_EMBED_IN_CODE_ACCESSORS] = "NO"
307316

317+
// Do not set `SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE` here since it is just going to point to the same bundle as code.
318+
// #bundle can use its default implementation for that.
319+
308320
// If we did not create a resource bundle target,
309321
// we still need to add build tool commands for any generated files.
310322
addBuildToolCommands(

Sources/XCBuildSupport/PIFBuilder.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,19 +488,27 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder {
488488
settings[.GENERATE_INFOPLIST_FILE] = "YES"
489489
}
490490

491+
var isSwiftModule = false
491492
if let clangTarget = mainTarget.underlying as? ClangModule {
492493
// Let the target itself find its own headers.
493494
settings[.HEADER_SEARCH_PATHS, default: ["$(inherited)"]].append(clangTarget.includeDir.pathString)
494495
settings[.GCC_C_LANGUAGE_STANDARD] = clangTarget.cLanguageStandard
495496
settings[.CLANG_CXX_LANGUAGE_STANDARD] = clangTarget.cxxLanguageStandard
496497
} else if let swiftTarget = mainTarget.underlying as? SwiftModule {
498+
isSwiftModule = true
497499
try settings.addSwiftVersionSettings(target: swiftTarget, parameters: self.parameters)
498500
settings.addCommonSwiftSettings(package: self.package, target: mainTarget, parameters: self.parameters)
499501
}
500502

501503
if let resourceBundle = addResourceBundle(for: mainTarget, in: pifTarget) {
502504
settings[.PACKAGE_RESOURCE_BUNDLE_NAME] = resourceBundle
503505
settings[.GENERATE_RESOURCE_ACCESSORS] = "YES"
506+
507+
if isSwiftModule {
508+
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS, default: ["$(inherited)"]].append("SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE")
509+
}
510+
} else if isSwiftModule {
511+
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS, default: ["$(inherited)"]].append("SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE")
504512
}
505513

506514
// For targets, we use the common build settings for both the "Debug" and the "Release" configurations (all
@@ -654,6 +662,7 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder {
654662
let moduleMapFileContents: String?
655663
let shouldImpartModuleMap: Bool
656664

665+
var isSwiftModule = false
657666
if let clangTarget = target.underlying as? ClangModule {
658667
// Let the target itself find its own headers.
659668
settings[.HEADER_SEARCH_PATHS, default: ["$(inherited)"]].append(clangTarget.includeDir.pathString)
@@ -680,6 +689,7 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder {
680689
shouldImpartModuleMap = false
681690
}
682691
} else if let swiftTarget = target.underlying as? SwiftModule {
692+
isSwiftModule = true
683693
try settings.addSwiftVersionSettings(target: swiftTarget, parameters: self.parameters)
684694

685695
// Generate ObjC compatibility header for Swift library targets.
@@ -729,7 +739,12 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder {
729739
if let resourceBundle = addResourceBundle(for: target, in: pifTarget) {
730740
settings[.PACKAGE_RESOURCE_BUNDLE_NAME] = resourceBundle
731741
settings[.GENERATE_RESOURCE_ACCESSORS] = "YES"
742+
if isSwiftModule {
743+
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS, default: ["$(inherited)"]].append("SWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE")
744+
}
732745
impartedSettings[.EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES, default: ["$(inherited)"]].append(resourceBundle)
746+
} else if isSwiftModule {
747+
settings[.SWIFT_ACTIVE_COMPILATION_CONDITIONS, default: ["$(inherited)"]].append("SWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE")
733748
}
734749

735750
// For targets, we use the common build settings for both the "Debug" and the "Release" configurations (all

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
792792
.equal(self.j),
793793
"-DSWIFT_PACKAGE",
794794
"-DDEBUG",
795+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
795796
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
796797
.anySequence,
797798
"-swift-version", "4",
@@ -811,6 +812,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
811812
.equal(self.j),
812813
"-DSWIFT_PACKAGE",
813814
"-DDEBUG",
815+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
814816
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
815817
.anySequence,
816818
"-swift-version", "4",
@@ -1224,6 +1226,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
12241226
"-O",
12251227
.equal(self.j),
12261228
"-DSWIFT_PACKAGE",
1229+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
12271230
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
12281231
.anySequence,
12291232
"-swift-version", "4",
@@ -1318,6 +1321,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
13181321
"-O",
13191322
.equal(self.j),
13201323
"-DSWIFT_PACKAGE",
1324+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
13211325
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
13221326
.anySequence,
13231327
"-swift-version", "4",
@@ -1863,6 +1867,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
18631867
.equal(self.j),
18641868
"-DSWIFT_PACKAGE",
18651869
"-DDEBUG",
1870+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
18661871
"-Xcc",
18671872
"-fmodule-map-file=\(buildPath.appending(components: "lib.build", "module.modulemap"))",
18681873
"-Xcc", "-I", "-Xcc", "\(Pkg.appending(components: "Sources", "lib", "include"))",
@@ -2365,6 +2370,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
23652370
.equal(self.j),
23662371
"-DSWIFT_PACKAGE",
23672372
"-DDEBUG",
2373+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
23682374
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
23692375
.anySequence,
23702376
"-swift-version", "4",
@@ -2387,6 +2393,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
23872393
.equal(self.j),
23882394
"-DSWIFT_PACKAGE",
23892395
"-DDEBUG",
2396+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
23902397
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
23912398
.anySequence,
23922399
"-swift-version", "4",
@@ -2499,6 +2506,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
24992506
"-O",
25002507
.equal(self.j),
25012508
"-DSWIFT_PACKAGE",
2509+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
25022510
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
25032511
.anySequence,
25042512
"-swift-version", "4",
@@ -2864,6 +2872,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
28642872
.equal(self.j),
28652873
"-DSWIFT_PACKAGE",
28662874
"-DDEBUG",
2875+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
28672876
"-Xcc", "-fmodule-map-file=\(Clibgit.appending(components: "module.modulemap"))",
28682877
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
28692878
.anySequence,
@@ -3166,6 +3175,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
31663175
.equal(self.j),
31673176
"-DSWIFT_PACKAGE",
31683177
"-DDEBUG",
3178+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
31693179
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
31703180
.anySequence,
31713181
"-swift-version", "4",
@@ -3185,6 +3195,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
31853195
.equal(self.j),
31863196
"-DSWIFT_PACKAGE",
31873197
"-DDEBUG",
3198+
"-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
31883199
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
31893200
.anySequence,
31903201
"-swift-version", "4",
@@ -3824,7 +3835,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
38243835
"-Onone",
38253836
"-enable-testing",
38263837
.equal(self.j),
3827-
"-DSWIFT_PACKAGE", "-DDEBUG",
3838+
"-DSWIFT_PACKAGE", "-DDEBUG", "-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE",
38283839
"-Xcc", "-fmodule-map-file=\(buildPath.appending(components: "lib.build", "module.modulemap"))",
38293840
"-Xcc", "-I", "-Xcc", "\(Pkg.appending(components: "Sources", "lib", "include"))",
38303841
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))",
@@ -5888,6 +5899,9 @@ class BuildPlanTestCase: BuildSystemProviderTestCase {
58885899
XCTAssertEqual(try barTarget.objects.map(\.pathString), [
58895900
buildPath.appending(components: "Bar.build", "Bar.swift.o").pathString,
58905901
])
5902+
5903+
XCTAssertTrue(try fooTarget.compileArguments().contains(["-DSWIFT_MODULE_RESOURCE_BUNDLE_AVAILABLE"]))
5904+
XCTAssertTrue(try barTarget.compileArguments().contains(["-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE"]))
58915905
}
58925906

58935907
func testSwiftWASIBundleAccessor() async throws {

Tests/BuildTests/CrossCompilationBuildPlanTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ final class CrossCompilationBuildPlanTests: XCTestCase {
179179
exe,
180180
[
181181
"-enable-batch-mode", "-serialize-diagnostics", "-Onone", "-enable-testing",
182-
"-j3", "-DSWIFT_PACKAGE", "-DDEBUG", "-Xcc",
182+
"-j3", "-DSWIFT_PACKAGE", "-DDEBUG", "-DSWIFT_MODULE_RESOURCE_BUNDLE_UNAVAILABLE", "-Xcc",
183183
"-fmodule-map-file=\(buildPath.appending(components: "lib.build", "module.modulemap"))",
184184
"-Xcc", "-I", "-Xcc", "\(pkgPath.appending(components: "Sources", "lib", "include"))",
185185
"-module-cache-path", "\(buildPath.appending(components: "ModuleCache"))", .anySequence,

0 commit comments

Comments
 (0)