[xcodegen] Allow buildable folders in more cases

We can define exceptions to handle targets with sources that either
have unique arguments or are unbuildable. Eventually this ought to
allow us to ditch the "no outside-target source file" rule, but I'm
leaving that be for now since ideally we'd handle automatically
splitting up umbrella Clang targets such as `stdlib` such that e.g
`swiftCore` is its own buildable folder instead of an exception.
This commit is contained in:
Hamish Knight
2025-05-04 20:38:48 +01:00
parent 2a00a65f05
commit 2199031b0f
9 changed files with 311 additions and 85 deletions

View File

@@ -108,6 +108,28 @@ extension Xcode.Project: PropertyListSerializable {
}
}
extension Xcode.BuildableFolder.TargetException: PropertyListSerializable {
var xcodeClassName: String { "PBXFileSystemSynchronizedBuildFileExceptionSet" }
fileprivate func serialize(
to serializer: PropertyListSerializer
) throws -> [String: PropertyList] {
var dict = [String: PropertyList]()
dict["isa"] = .string(xcodeClassName)
dict["additionalCompilerFlagsByRelativePath"] = .dictionary(
Dictionary(
uniqueKeysWithValues:
extraCompilerArgs.map {
($0.rawPath, PropertyList.string($1.joined(separator: " ")))
}
)
)
dict["membershipExceptions"] = .array(sources.map { .string($0.rawPath) })
dict["target"] = .identifier(serializer.id(of: target))
return dict
}
}
extension Xcode.Reference: PropertyListSerializable {
fileprivate var xcodeClassName: String {
switch self {
@@ -138,6 +160,13 @@ extension Xcode.Reference: PropertyListSerializable {
try .identifier(serializer.serialize(object: reference))
}))
case let fileRef as Xcode.FileReference:
if let buildableFolder = fileRef.buildableFolder {
dict["exceptions"] = try .array(
buildableFolder.makeTargetExceptions().map {
try .identifier(serializer.serialize(object: $0))
}
)
}
if let fileType = fileRef.fileType {
dict["explicitFileType"] = .string(fileType)
}
@@ -202,7 +231,7 @@ extension Xcode.Target: PropertyListSerializable {
}))
if !buildableFolders.isEmpty {
dict["fileSystemSynchronizedGroups"] = .array(
buildableFolders.map { .identifier(serializer.id(of: $0)) }
buildableFolders.map { .identifier(serializer.id(of: $0.ref)) }
)
}
dict["productName"] = .string(productName)