diff --git a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift index 2239072df56..7a58e0f14f5 100644 --- a/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift +++ b/Sources/SwiftBuildSupport/PackagePIFProjectBuilder.swift @@ -334,6 +334,14 @@ struct PackagePIFProjectBuilder { self.log(.debug, indent: 2, "Added asset catalog as source file '\(resourcePath)'") } + // String Catalogs can also generate symbols. + if SwiftBuild.SwiftBuildFileType.xcstrings.fileTypes.contains(resourcePath.pathExtension) { + self.project[keyPath: sourceModuleTargetKeyPath].addSourceFile { id in + BuildFile(id: id, fileRef: ref) + } + self.log(.debug, indent: 2, "Added string catalog as source file '\(resourcePath)'") + } + self.log(.debug, indent: 2, "Added resource file '\(resourcePath)'") } diff --git a/Sources/XCBuildSupport/PIF.swift b/Sources/XCBuildSupport/PIF.swift index fcd30ea9b50..d418da1f15c 100644 --- a/Sources/XCBuildSupport/PIF.swift +++ b/Sources/XCBuildSupport/PIF.swift @@ -1124,6 +1124,11 @@ public struct XCBuildFileType: CaseIterable { fileTypeIdentifier: "folder.abstractassetcatalog" ) + public static let xcstrings: XCBuildFileType = XCBuildFileType( + fileType: "xcstrings", + fileTypeIdentifier: "text.json.xcstrings" + ) + public static let xcdatamodeld: XCBuildFileType = XCBuildFileType( fileType: "xcdatamodeld", fileTypeIdentifier: "wrapper.xcdatamodeld" @@ -1140,6 +1145,8 @@ public struct XCBuildFileType: CaseIterable { ) public static let allCases: [XCBuildFileType] = [ + .xcassets, + .xcstrings, .xcdatamodeld, .xcdatamodel, .xcmappingmodel, diff --git a/Sources/XCBuildSupport/PIFBuilder.swift b/Sources/XCBuildSupport/PIFBuilder.swift index 283379fedd1..1b231f68592 100644 --- a/Sources/XCBuildSupport/PIFBuilder.swift +++ b/Sources/XCBuildSupport/PIFBuilder.swift @@ -946,6 +946,11 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder { pifTarget.addSourceFile(resourceFile) } + // String Catalogs can also generate symbols. + if XCBuildFileType.xcstrings.fileTypes.contains(resource.path.extension ?? "") { + pifTarget.addSourceFile(resourceFile) + } + resourcesTarget.addResourceFile(resourceFile) } diff --git a/Tests/XCBuildSupportTests/PIFBuilderTests.swift b/Tests/XCBuildSupportTests/PIFBuilderTests.swift index 36f280978be..4e28ea1c57f 100644 --- a/Tests/XCBuildSupportTests/PIFBuilderTests.swift +++ b/Tests/XCBuildSupportTests/PIFBuilderTests.swift @@ -2201,12 +2201,18 @@ final class PIFBuilderTests: XCTestCase { "/Foo/Sources/foo/main.swift", "/Foo/Sources/foo/Resources/Data.plist", "/Foo/Sources/foo/Resources/Database.xcdatamodel", + "/Foo/Sources/foo/Resources/Assets.xcassets", + "/Foo/Sources/foo/Resources/Localizable.xcstrings", "/Foo/Sources/FooLib/lib.swift", "/Foo/Sources/FooLib/Resources/Data.plist", "/Foo/Sources/FooLib/Resources/Database.xcdatamodel", + "/Foo/Sources/FooLib/Resources/Assets.xcassets", + "/Foo/Sources/FooLib/Resources/Localizable.xcstrings", "/Foo/Sources/FooTests/FooTests.swift", "/Foo/Sources/FooTests/Resources/Data.plist", - "/Foo/Sources/FooTests/Resources/Database.xcdatamodel" + "/Foo/Sources/FooTests/Resources/Database.xcdatamodel", + "/Foo/Sources/FooTests/Resources/Assets.xcassets", + "/Foo/Sources/FooTests/Resources/Localizable.xcstrings", ) let observability = ObservabilitySystem.makeForTesting() @@ -2216,7 +2222,7 @@ final class PIFBuilderTests: XCTestCase { Manifest.createRootManifest( displayName: "Foo", path: "/Foo", - toolsVersion: .v5_3, + toolsVersion: .v5_9, products: [ .init(name: "FooLib", type: .library(.automatic), targets: ["FooLib"]), ], @@ -2224,7 +2230,7 @@ final class PIFBuilderTests: XCTestCase { .init(name: "foo", resources: [ // This is intentionally specific to test that we pick up `.xcdatamodel` implicitly. .init(rule: .process(localization: .none), path: "Resources/Data.plist"), - ]), + ], type: .executable), .init(name: "FooLib", resources: [ .init(rule: .process(localization: .none), path: "Resources"), ]), @@ -2253,7 +2259,10 @@ final class PIFBuilderTests: XCTestCase { try workspace.checkProject("PACKAGE:/Foo") { project in project.checkTarget("PACKAGE-PRODUCT:foo") { target in XCTAssertEqual(target.dependencies, ["PACKAGE-RESOURCE:foo"]) + // All of these file types can generate code. XCTAssert(target.sources.contains("/Foo/Sources/foo/Resources/Database.xcdatamodel")) + XCTAssert(target.sources.contains("/Foo/Sources/foo/Resources/Assets.xcassets")) + XCTAssert(target.sources.contains("/Foo/Sources/foo/Resources/Localizable.xcstrings")) target.checkBuildConfiguration("Debug") { configuration in configuration.checkBuildSettings { settings in @@ -2290,6 +2299,8 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.resources, [ "/Foo/Sources/foo/Resources/Data.plist", "/Foo/Sources/foo/Resources/Database.xcdatamodel", + "/Foo/Sources/foo/Resources/Assets.xcassets", + "/Foo/Sources/foo/Resources/Localizable.xcstrings", ]) target.checkBuildConfiguration("Debug") { configuration in @@ -2322,6 +2333,8 @@ final class PIFBuilderTests: XCTestCase { project.checkTarget("PACKAGE-PRODUCT:FooLib") { target in XCTAssert(!target.dependencies.contains("PACKAGE-RESOURCE:FooLib")) XCTAssert(!target.sources.contains("/Foo/Sources/FooLib/Resources/Database.xcdatamodel")) + XCTAssert(!target.sources.contains("/Foo/Sources/FooLib/Resources/Assets.xcassets")) + XCTAssert(!target.sources.contains("/Foo/Sources/FooLib/Resources/Localizable.xcstrings")) target.checkBuildConfiguration("Debug") { configuration in configuration.checkBuildSettings { settings in @@ -2343,6 +2356,8 @@ final class PIFBuilderTests: XCTestCase { project.checkTarget("PACKAGE-TARGET:FooLib") { target in XCTAssertEqual(target.dependencies, ["PACKAGE-RESOURCE:FooLib"]) XCTAssert(target.sources.contains("/Foo/Sources/FooLib/Resources/Database.xcdatamodel")) + XCTAssert(target.sources.contains("/Foo/Sources/FooLib/Resources/Assets.xcassets")) + XCTAssert(target.sources.contains("/Foo/Sources/FooLib/Resources/Localizable.xcstrings")) target.checkBuildConfiguration("Debug") { configuration in configuration.checkBuildSettings { settings in @@ -2372,6 +2387,8 @@ final class PIFBuilderTests: XCTestCase { project.checkTarget("PACKAGE-PRODUCT:FooTests") { target in XCTAssertEqual(target.dependencies, ["PACKAGE-RESOURCE:FooTests"]) XCTAssert(target.sources.contains("/Foo/Sources/FooTests/Resources/Database.xcdatamodel")) + XCTAssert(target.sources.contains("/Foo/Sources/FooTests/Resources/Assets.xcassets")) + XCTAssert(target.sources.contains("/Foo/Sources/FooTests/Resources/Localizable.xcstrings")) target.checkBuildConfiguration("Debug") { configuration in configuration.checkBuildSettings { settings in @@ -2408,6 +2425,8 @@ final class PIFBuilderTests: XCTestCase { XCTAssertEqual(target.resources, [ "/Foo/Sources/FooTests/Resources/Data.plist", "/Foo/Sources/FooTests/Resources/Database.xcdatamodel", + "/Foo/Sources/FooTests/Resources/Assets.xcassets", + "/Foo/Sources/FooTests/Resources/Localizable.xcstrings", ]) target.checkBuildConfiguration("Debug") { configuration in