diff --git a/Sources/XcodeProj/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSet.swift b/Sources/XcodeProj/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSet.swift index c375f16d0..e007bb879 100644 --- a/Sources/XcodeProj/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSet.swift +++ b/Sources/XcodeProj/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSet.swift @@ -25,6 +25,11 @@ public class PBXFileSystemSynchronizedBuildFileExceptionSet: PBXFileSystemSynchr /// This is used for example when linking frameworks to specify that they are optional with the attribute "Weak" public var attributesByRelativePath: [String: [String]]? + /// Platform filters by relative path. + /// Every item in the list is the relative path inside the root synchronized group. + /// The value is the list of platform filters (e.g. "ios", "tvos") that the file should be included for. + public var platformFiltersByRelativePath: [String: [String]]? + var targetReference: PBXObjectReference public var target: PBXTarget! { @@ -43,13 +48,15 @@ public class PBXFileSystemSynchronizedBuildFileExceptionSet: PBXFileSystemSynchr publicHeaders: [String]?, privateHeaders: [String]?, additionalCompilerFlagsByRelativePath: [String: String]?, - attributesByRelativePath: [String: [String]]?) { + attributesByRelativePath: [String: [String]]?, + platformFiltersByRelativePath: [String: [String]]? = nil) { targetReference = target.reference self.membershipExceptions = membershipExceptions self.publicHeaders = publicHeaders self.privateHeaders = privateHeaders self.additionalCompilerFlagsByRelativePath = additionalCompilerFlagsByRelativePath self.attributesByRelativePath = attributesByRelativePath + self.platformFiltersByRelativePath = platformFiltersByRelativePath super.init() } @@ -62,6 +69,7 @@ public class PBXFileSystemSynchronizedBuildFileExceptionSet: PBXFileSystemSynchr case privateHeaders case additionalCompilerFlagsByRelativePath case attributesByRelativePath + case platformFiltersByRelativePath } public required init(from decoder: Decoder) throws { @@ -75,6 +83,7 @@ public class PBXFileSystemSynchronizedBuildFileExceptionSet: PBXFileSystemSynchr privateHeaders = try container.decodeIfPresent(.privateHeaders) additionalCompilerFlagsByRelativePath = try container.decodeIfPresent(.additionalCompilerFlagsByRelativePath) attributesByRelativePath = try container.decodeIfPresent(.attributesByRelativePath) + platformFiltersByRelativePath = try container.decodeIfPresent(.platformFiltersByRelativePath) try super.init(from: decoder) } @@ -109,6 +118,11 @@ public class PBXFileSystemSynchronizedBuildFileExceptionSet: PBXFileSystemSynchr (CommentedString(key), .array(value.map { .string(CommentedString($0)) })) })) } + if let platformFiltersByRelativePath { + dictionary["platformFiltersByRelativePath"] = .dictionary(Dictionary(uniqueKeysWithValues: platformFiltersByRelativePath.map { key, value in + (CommentedString(key), .array(value.map { .string(CommentedString($0)) })) + })) + } dictionary["target"] = .string(CommentedString(target.reference.value, comment: target.name)) return (key: CommentedString(reference, comment: "PBXFileSystemSynchronizedBuildFileExceptionSet"), value: .dictionary(dictionary)) } diff --git a/Sources/XcodeProj/Objects/Sourcery/Equality.generated.swift b/Sources/XcodeProj/Objects/Sourcery/Equality.generated.swift index cd69699a9..016c323ca 100644 --- a/Sources/XcodeProj/Objects/Sourcery/Equality.generated.swift +++ b/Sources/XcodeProj/Objects/Sourcery/Equality.generated.swift @@ -319,6 +319,7 @@ extension PBXFileSystemSynchronizedBuildFileExceptionSet { if targetReference != rhs.targetReference { return false } if publicHeaders != rhs.publicHeaders { return false } if privateHeaders != rhs.privateHeaders { return false } + if platformFiltersByRelativePath != rhs.platformFiltersByRelativePath { return false } return super.isEqual(to: rhs) } } diff --git a/Tests/XcodeProjTests/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSet+Fixtures.swift b/Tests/XcodeProjTests/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSet+Fixtures.swift index 17e0b1f0d..bda5f78ea 100644 --- a/Tests/XcodeProjTests/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSet+Fixtures.swift +++ b/Tests/XcodeProjTests/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSet+Fixtures.swift @@ -6,12 +6,14 @@ extension PBXFileSystemSynchronizedBuildFileExceptionSet { publicHeaders: [String]? = [], privateHeaders: [String]? = [], additionalCompilerFlagsByRelativePath: [String: String]? = nil, - attributesByRelativePath: [String: [String]]? = nil) -> PBXFileSystemSynchronizedBuildFileExceptionSet { + attributesByRelativePath: [String: [String]]? = nil, + platformFiltersByRelativePath: [String: [String]]? = nil) -> PBXFileSystemSynchronizedBuildFileExceptionSet { PBXFileSystemSynchronizedBuildFileExceptionSet(target: target, membershipExceptions: membershipExceptions, publicHeaders: publicHeaders, privateHeaders: privateHeaders, additionalCompilerFlagsByRelativePath: additionalCompilerFlagsByRelativePath, - attributesByRelativePath: attributesByRelativePath) + attributesByRelativePath: attributesByRelativePath, + platformFiltersByRelativePath: platformFiltersByRelativePath) } } diff --git a/Tests/XcodeProjTests/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSetTests.swift b/Tests/XcodeProjTests/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSetTests.swift index 842954846..0ef9fda58 100644 --- a/Tests/XcodeProjTests/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSetTests.swift +++ b/Tests/XcodeProjTests/Objects/Files/PBXFileSystemSynchronizedBuildFileExceptionSetTests.swift @@ -26,4 +26,53 @@ final class PBXFileSystemSynchronizedBuildFileExceptionSetTests: XCTestCase { let another = PBXFileSystemSynchronizedBuildFileExceptionSet.fixture(target: target) XCTAssertEqual(subject, another) } + + func test_equal_withDifferentPlatformFilters_returnsNotEqual() { + let one = PBXFileSystemSynchronizedBuildFileExceptionSet.fixture( + target: target, + platformFiltersByRelativePath: ["file.swift": ["ios"]] + ) + let another = PBXFileSystemSynchronizedBuildFileExceptionSet.fixture( + target: target, + platformFiltersByRelativePath: ["file.swift": ["tvos"]] + ) + XCTAssertNotEqual(one, another) + } + + func test_plistKeyAndValue_platformFiltersByRelativePath_serializesCorrectly() throws { + let proj = PBXProj() + let exceptionSet = PBXFileSystemSynchronizedBuildFileExceptionSet.fixture( + target: target, + platformFiltersByRelativePath: [ + "Resources/ios_only.mp4": ["ios"], + "Resources/multi.mp4": ["ios", "tvos"], + ] + ) + proj.add(object: exceptionSet) + + let (_, plistValue) = try exceptionSet.plistKeyAndValue(proj: proj, reference: "ref") + + let dict = try XCTUnwrap(plistValue.dictionary?[CommentedString("platformFiltersByRelativePath")]?.dictionary) + XCTAssertEqual( + dict[CommentedString("Resources/ios_only.mp4")], + .array([.string(CommentedString("ios"))]) + ) + XCTAssertEqual( + dict[CommentedString("Resources/multi.mp4")], + .array([.string(CommentedString("ios")), .string(CommentedString("tvos"))]) + ) + } + + func test_plistKeyAndValue_platformFiltersByRelativePath_omittedWhenNil() throws { + let proj = PBXProj() + let exceptionSet = PBXFileSystemSynchronizedBuildFileExceptionSet.fixture( + target: target, + platformFiltersByRelativePath: nil + ) + proj.add(object: exceptionSet) + + let (_, plistValue) = try exceptionSet.plistKeyAndValue(proj: proj, reference: "ref") + + XCTAssertNil(plistValue.dictionary?[CommentedString("platformFiltersByRelativePath")]) + } }