update to xcodeproj 6

This commit is contained in:
Yonas Kolb
2018-09-25 21:11:04 +10:00
parent e97b002655
commit 84f1c65632
15 changed files with 326 additions and 369 deletions
+3 -3
View File
@@ -68,9 +68,9 @@
"package": "xcodeproj",
"repositoryURL": "https://github.com/tuist/xcodeproj.git",
"state": {
"branch": "master",
"revision": "f7f497b00e41dae704815ecebfd030b85f82c240",
"version": null
"branch": null,
"revision": "1314329687682864119ecc03c73a413dfc24ade0",
"version": "6.0.1"
}
},
{
+1 -1
View File
@@ -16,7 +16,7 @@ let package = Package(
.package(url: "https://github.com/yonaskolb/JSONUtilities.git", from: "4.0.0"),
.package(url: "https://github.com/kylef/Spectre.git", from: "0.9.0"),
.package(url: "https://github.com/onevcat/Rainbow.git", from: "3.0.0"),
.package(url: "https://github.com/tuist/xcodeproj.git", .branchItem("master")),
.package(url: "https://github.com/tuist/xcodeproj.git", from: "6.0.0"),
],
targets: [
.target(name: "XcodeGen", dependencies: [
+133 -146
View File
@@ -13,11 +13,10 @@ public class PBXProjGenerator {
var targetObjects: [String: PBXTarget] = [:]
var targetAggregateObjects: [String: PBXAggregateTarget] = [:]
var targetBuildFiles: [String: PBXBuildFile] = [:]
var targetFileReferences: [String: PBXObjectReference] = [:]
var targetFileReferences: [String: PBXFileReference] = [:]
var carthageFrameworksByPlatform: [String: Set<PBXObjectReference>] = [:]
var frameworkFiles: [PBXObjectReference] = []
var carthageFrameworksByPlatform: [String: Set<PBXFileElement>] = [:]
var frameworkFiles: [PBXFileElement] = []
var generated = false
@@ -27,20 +26,20 @@ public class PBXProjGenerator {
public init(project: Project) {
self.project = project
pbxProj = PBXProj(objectVersion: 46)
pbxProj = PBXProj(rootObject: nil, objectVersion: 46)
sourceGenerator = SourceGenerator(project: project) { [unowned self] id, object in
_ = self.addObject(id: id, object)
}
}
func addObject<T: PBXObject>(id: String, _ object: T) -> T {
// let reference = pbxProj.objects.generateReference(object, id)
pbxProj.objects.addObject(object)
// let reference = pbxProj.generateReference(object, id)
pbxProj.add(object: object)
return object
}
func createObject<T: PBXObject>(id: String, _ object: T) -> T {
pbxProj.objects.addObject(object)
pbxProj.add(object: object)
return object
}
@@ -56,25 +55,27 @@ public class PBXProjGenerator {
let buildConfigs: [XCBuildConfiguration] = project.configs.map { config in
let buildSettings = project.getProjectBuildSettings(config: config)
var baseConfigurationReference: PBXObjectReference?
if let configPath = project.configFiles[config.name] {
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: project.basePath + configPath)
var baseConfiguration: PBXFileReference?
if let configPath = project.configFiles[config.name],
let fileReference = sourceGenerator.getContainedFileReference(path: project.basePath + configPath) as? PBXFileReference {
baseConfiguration = fileReference
}
return createObject(
let buildConfig = createObject(
id: config.name,
XCBuildConfiguration(
name: config.name,
baseConfigurationReference: baseConfigurationReference,
buildSettings: buildSettings
)
)
buildConfig.baseConfiguration = baseConfiguration
return buildConfig
}
let configName = project.options.defaultConfig ?? buildConfigs.first?.name ?? ""
let buildConfigList = createObject(
id: project.name,
XCConfigurationList(
buildConfigurationsReferences: buildConfigs.map { $0.reference },
buildConfigurations: buildConfigs,
defaultConfigurationName: configName
)
)
@@ -84,7 +85,7 @@ public class PBXProjGenerator {
let mainGroup = createObject(
id: "Project",
PBXGroup(
childrenReferences: [],
children: [],
sourceTree: .group,
usesTabs: project.options.usesTabs,
indentWidth: project.options.indentWidth,
@@ -96,14 +97,14 @@ public class PBXProjGenerator {
id: project.name,
PBXProject(
name: project.name,
buildConfigurationListReference: buildConfigList.reference,
buildConfigurationList: buildConfigList,
compatibilityVersion: "Xcode 3.2",
mainGroupReference: mainGroup.reference,
mainGroup: mainGroup,
developmentRegion: project.options.developmentLanguage ?? "en"
)
)
pbxProj.rootObjectReference = pbxProject.reference
pbxProj.rootObject = pbxProject
for target in project.targets {
let targetObject: PBXTarget
@@ -114,10 +115,11 @@ public class PBXProjGenerator {
buildToolPath: target.legacy?.toolPath,
buildArgumentsString: target.legacy?.arguments,
passBuildSettingsInEnvironment: target.legacy?.passSettings ?? false,
buildWorkingDirectory: target.legacy?.workingDirectory
buildWorkingDirectory: target.legacy?.workingDirectory,
buildPhases: []
)
} else {
targetObject = PBXNativeTarget(name: target.name)
targetObject = PBXNativeTarget(name: target.name, buildPhases: [])
}
targetObjects[target.name] = createObject(id: target.name, targetObject)
@@ -143,11 +145,7 @@ public class PBXProjGenerator {
)
)
targetFileReferences[target.name] = fileReference.reference
targetBuildFiles[target.name] = createObject(
id: "legacy target build file" + target.name,
PBXBuildFile(fileReference: fileReference.reference)
)
targetFileReferences[target.name] = fileReference
}
}
@@ -169,7 +167,7 @@ public class PBXProjGenerator {
let productGroup = createObject(
id: "Products",
PBXGroup(
childrenReferences: Array(targetFileReferences.values),
children: targetFileReferences.valueArray,
sourceTree: .group,
name: "Products"
)
@@ -178,36 +176,34 @@ public class PBXProjGenerator {
if !carthageFrameworksByPlatform.isEmpty {
var platforms: [PBXGroup] = []
var platformReferences: [PBXObjectReference] = []
for (platform, fileReferences) in carthageFrameworksByPlatform {
for (platform, files) in carthageFrameworksByPlatform {
let platformGroup: PBXGroup = createObject(
id: "Carthage" + platform,
PBXGroup(
childrenReferences: fileReferences.sorted(),
children: files.sorted { $0.nameOrPath < $1.nameOrPath },
sourceTree: .group,
path: platform
)
)
platformReferences.append(platformGroup.reference)
platforms.append(platformGroup)
}
let carthageGroup = createObject(
id: "Carthage",
PBXGroup(
childrenReferences: platformReferences.sorted(),
children: platforms,
sourceTree: .group,
name: "Carthage",
path: carthageBuildPath
)
)
frameworkFiles.append(carthageGroup.reference)
frameworkFiles.append(carthageGroup)
}
if !frameworkFiles.isEmpty {
let group = createObject(
id: "Frameworks",
PBXGroup(
childrenReferences: frameworkFiles,
children: frameworkFiles,
sourceTree: .group,
name: "Frameworks"
)
@@ -215,27 +211,25 @@ public class PBXProjGenerator {
derivedGroups.append(group)
}
mainGroup.childrenReferences = Array(sourceGenerator.rootGroups)
mainGroup.children = Array(sourceGenerator.rootGroups)
sortGroups(group: mainGroup)
// add derived groups at the end
derivedGroups.forEach(sortGroups)
mainGroup.childrenReferences += derivedGroups
mainGroup.children += derivedGroups
.sorted { $0.nameOrPath.localizedStandardCompare($1.nameOrPath) == .orderedAscending }
.map { $0.reference }
.map { $0 }
let projectAttributes: [String: Any] = ["LastUpgradeCheck": project.xcodeVersion]
.merged(project.attributes)
.merged(generateTargetAttributes() ?? [:])
let knownRegions = sourceGenerator.knownRegions.sorted()
pbxProject.object.knownRegions = knownRegions.isEmpty ? ["en"] : knownRegions
pbxProject.knownRegions = knownRegions.isEmpty ? ["en"] : knownRegions
let allTargets: [PBXTarget] = Array(targetObjects.values) + Array(targetAggregateObjects.values)
pbxProject.object.targets = allTargets
pbxProject.targets = allTargets
.sorted { $0.name < $1.name }
.map { $0.reference }
pbxProject.attributes = projectAttributes
pbxProject.targetAttributes = generateTargetAttributes()
return pbxProj
}
@@ -247,42 +241,42 @@ public class PBXProjGenerator {
let buildSettings = project.getBuildSettings(settings: target.settings, config: config)
var baseConfigurationReference: PBXObjectReference?
var baseConfiguration: PBXFileReference?
if let configPath = target.configFiles[config.name] {
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: project.basePath + configPath)
baseConfiguration = sourceGenerator.getContainedFileReference(path: project.basePath + configPath) as? PBXFileReference
}
let buildConfig = XCBuildConfiguration(
name: config.name,
baseConfigurationReference: baseConfigurationReference,
baseConfiguration: baseConfiguration,
buildSettings: buildSettings
)
return createObject(id: config.name + target.name, buildConfig)
}
let dependencies: [PBXObjectReference] = target.targets.map { generateTargetDependency(from: target.name, to: $0).reference }
let dependencies = target.targets.map { generateTargetDependency(from: target.name, to: $0) }
let buildConfigList = createObject(id: target.name, XCConfigurationList(
buildConfigurationsReferences: configs.map { $0.reference },
buildConfigurations: configs,
defaultConfigurationName: ""
))
var buildPhases: [PBXObjectReference] = []
var buildPhases: [PBXBuildPhase] = []
buildPhases += try target.buildScripts.map { try generateBuildScript(targetName: target.name, buildScript: $0) }
aggregateTarget.buildPhasesReferences = buildPhases
aggregateTarget.buildConfigurationListReference = buildConfigList.reference
aggregateTarget.dependenciesReferences = dependencies
aggregateTarget.buildPhases = buildPhases
aggregateTarget.buildConfigurationList = buildConfigList
aggregateTarget.dependencies = dependencies
}
func generateTargetDependency(from: String, to target: String) -> PBXTargetDependency {
guard let targetReference = targetObjects[target]?.reference ?? targetAggregateObjects[target]?.reference else {
guard let targetObject = targetObjects[target] ?? targetAggregateObjects[target] else {
fatalError("target not found")
}
let targetProxy = createObject(
id: "\(from)-\(target)",
PBXContainerItemProxy(
containerPortalReference: pbxProj.rootObjectReference!,
remoteGlobalIDReference: targetReference,
containerPortal: pbxProj.rootObject!,
remoteGlobalID: targetObject,
proxyType: .nativeTarget,
remoteInfo: target
)
@@ -291,14 +285,14 @@ public class PBXProjGenerator {
let targetDependency = createObject(
id: "\(from)-\(target)",
PBXTargetDependency(
targetReference: targetReference,
targetProxyReference: targetProxy.reference
target: targetObject,
targetProxy: targetProxy
)
)
return targetDependency
}
func generateBuildScript(targetName: String, buildScript: BuildScript) throws -> PBXObjectReference {
func generateBuildScript(targetName: String, buildScript: BuildScript) throws -> PBXShellScriptBuildPhase {
let shellScript: String
switch buildScript.script {
@@ -309,47 +303,43 @@ public class PBXProjGenerator {
}
let shellScriptPhase = PBXShellScriptBuildPhase(
fileReferences: [],
name: buildScript.name ?? "Run Script",
inputPaths: buildScript.inputFiles,
outputPaths: buildScript.outputFiles,
shellPath: buildScript.shell ?? "/bin/sh",
shellScript: shellScript
shellScript: shellScript,
runOnlyForDeploymentPostprocessing: buildScript.runOnlyWhenInstalling,
showEnvVarsInLog: buildScript.showEnvVars
)
shellScriptPhase.runOnlyForDeploymentPostprocessing = buildScript.runOnlyWhenInstalling
shellScriptPhase.showEnvVarsInLog = buildScript.showEnvVars
return createObject(id: String(describing: buildScript.name) + shellScript + targetName, shellScriptPhase).reference
return createObject(id: String(describing: buildScript.name) + shellScript + targetName, shellScriptPhase)
}
func generateTargetAttributes() -> [String: Any]? {
func generateTargetAttributes() -> [PBXTarget: [String: Any]] {
var targetAttributes: [PBXObjectReference: [String: Any]] = [:]
var targetAttributes: [PBXTarget: [String: Any]] = [:]
let uiTestTargets = pbxProj.objects.nativeTargets.values.filter { $0.productType == .uiTestBundle }
let uiTestTargets = pbxProj.nativeTargets.filter { $0.productType == .uiTestBundle }
for uiTestTarget in uiTestTargets {
// look up TEST_TARGET_NAME build setting
func testTargetName(_ target: PBXTarget) -> String? {
guard let configurationList = target.buildConfigurationListReference else { return nil }
guard let buildConfigurationReferences = self.pbxProj.objects.configurationLists[configurationList]?.buildConfigurationsReferences else { return nil }
guard let buildConfigurations = target.buildConfigurationList?.buildConfigurations else { return nil }
let configs = buildConfigurationReferences
.compactMap { ref in self.pbxProj.objects.buildConfigurations[ref] }
return configs
return buildConfigurations
.compactMap { $0.buildSettings["TEST_TARGET_NAME"] as? String }
.first
}
guard let name = testTargetName(uiTestTarget) else { continue }
guard let target = self.pbxProj.objects.targets(named: name).first else { continue }
guard let target = self.pbxProj.targets(named: name).first else { continue }
targetAttributes[uiTestTarget.reference, default: [:]].merge(["TestTargetID": target.reference])
// FIX: Can't set in xcproj 5.0+
//targetAttributes[uiTestTarget, default: [:]].merge(["TestTargetID": target.reference])
}
func generateTargetAttributes(_ target: ProjectTarget, targetReference: PBXObjectReference) {
func generateTargetAttributes(_ target: ProjectTarget, pbxTarget: PBXTarget) {
if !target.attributes.isEmpty {
targetAttributes[targetReference, default: [:]].merge(target.attributes)
targetAttributes[pbxTarget, default: [:]].merge(target.attributes)
}
func getSingleBuildSetting(_ setting: String) -> String? {
@@ -366,7 +356,7 @@ public class PBXProjGenerator {
func setTargetAttribute(attribute: String, buildSetting: String) {
if let setting = getSingleBuildSetting(buildSetting) {
targetAttributes[targetReference, default: [:]].merge([attribute: setting])
targetAttributes[pbxTarget, default: [:]].merge([attribute: setting])
}
}
@@ -375,26 +365,25 @@ public class PBXProjGenerator {
}
for target in project.aggregateTargets {
guard let targetReference = targetAggregateObjects[target.name]?.reference else {
guard let pbxTarget = targetAggregateObjects[target.name] else {
continue
}
generateTargetAttributes(target, targetReference: targetReference)
generateTargetAttributes(target, pbxTarget: pbxTarget)
}
for target in project.targets {
guard let targetReference = targetObjects[target.name]?.reference else {
guard let pbxTarget = targetObjects[target.name] else {
continue
}
generateTargetAttributes(target, targetReference: targetReference)
generateTargetAttributes(target, pbxTarget: pbxTarget)
}
return targetAttributes.isEmpty ? nil : ["TargetAttributes": targetAttributes]
return targetAttributes
}
func sortGroups(group: PBXGroup) {
// sort children
let children = group.childrenReferences
.compactMap { pbxProj.objects.getFileElement(reference: $0) }
let children = group.children
.sorted { child1, child2 in
let sortOrder1 = child1.getSortOrder(groupSortPosition: project.options.groupSortPosition)
let sortOrder2 = child2.getSortOrder(groupSortPosition: project.options.groupSortPosition)
@@ -405,10 +394,10 @@ public class PBXProjGenerator {
return sortOrder1 < sortOrder2
}
}
group.childrenReferences = children.map { $0.reference }.filter { $0 != group.reference }
group.children = children.filter { $0 != group }
// sort sub groups
let childGroups = group.childrenReferences.compactMap { pbxProj.objects.groups[$0] }
let childGroups = group.children.compactMap { $0 as? PBXGroup }
childGroups.forEach(sortGroups)
}
@@ -423,14 +412,14 @@ public class PBXProjGenerator {
var searchForPlist = true
var anyDependencyRequiresObjCLinking = false
var dependencies: [PBXObjectReference] = []
var targetFrameworkBuildFiles: [PBXObjectReference] = []
var dependencies: [PBXTargetDependency] = []
var targetFrameworkBuildFiles: [PBXBuildFile] = []
var frameworkBuildPaths = Set<String>()
var copyFilesBuildPhasesFiles: [TargetSource.BuildPhase.CopyFilesSettings: [PBXObjectReference]] = [:]
var copyFrameworksReferences: [PBXObjectReference] = []
var copyResourcesReferences: [PBXObjectReference] = []
var copyWatchReferences: [PBXObjectReference] = []
var extensions: [PBXObjectReference] = []
var copyFilesBuildPhasesFiles: [TargetSource.BuildPhase.CopyFilesSettings: [PBXBuildFile]] = [:]
var copyFrameworksReferences: [PBXBuildFile] = []
var copyResourcesReferences: [PBXBuildFile] = []
var copyWatchReferences: [PBXBuildFile] = []
var extensions: [PBXBuildFile] = []
var carthageFrameworksToEmbed: [String] = []
let targetDependencies = (target.transitivelyLinkDependencies ?? project.options.transitivelyLinkDependencies) ?
@@ -457,7 +446,7 @@ public class PBXProjGenerator {
case .target:
let dependencyTargetName = dependency.reference
let targetDependency = generateTargetDependency(from: target.name, to: dependencyTargetName)
dependencies.append(targetDependency.reference)
dependencies.append(targetDependency)
guard let dependencyTarget = project.getTarget(dependencyTargetName) else { continue }
@@ -469,12 +458,12 @@ public class PBXProjGenerator {
|| (dependecyLinkage == .static && target.type.isExecutable)
)
if link {
let dependencyBuildFileReference = targetBuildFiles[dependencyTargetName]!.fileReference!
let dependencyFile = targetFileReferences[dependencyTargetName]!
let buildFile = createObject(
id: "target dependency build file" + target.name,
PBXBuildFile(fileReference: dependencyBuildFileReference)
PBXBuildFile(file: dependencyFile)
)
targetFrameworkBuildFiles.append(buildFile.reference)
targetFrameworkBuildFiles.append(buildFile)
if !anyDependencyRequiresObjCLinking
&& dependencyTarget.requiresObjCLinking ?? (dependencyTarget.type == .staticLibrary) {
@@ -490,29 +479,29 @@ public class PBXProjGenerator {
let embedFile = createObject(
id: "target dependency embed build file" + target.name,
PBXBuildFile(
fileReference: dependencyFileReference,
file: dependencyFileReference,
settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? !dependencyTarget.type.isExecutable)
)
)
if dependencyTarget.type.isExtension {
// embed app extension
extensions.append(embedFile.reference)
extensions.append(embedFile)
} else if dependencyTarget.type.isFramework {
copyFrameworksReferences.append(embedFile.reference)
copyFrameworksReferences.append(embedFile)
} else if dependencyTarget.type.isApp && dependencyTarget.platform == .watchOS {
copyWatchReferences.append(embedFile.reference)
copyWatchReferences.append(embedFile)
} else if dependencyTarget.type == .xpcService {
copyFilesBuildPhasesFiles[.xpcServices, default: []].append(embedFile.reference)
copyFilesBuildPhasesFiles[.xpcServices, default: []].append(embedFile)
} else {
copyResourcesReferences.append(embedFile.reference)
copyResourcesReferences.append(embedFile)
}
}
case .framework:
guard target.type != .staticLibrary else { break }
let fileReference: PBXObjectReference
let fileReference: PBXFileElement
if dependency.implicit {
fileReference = sourceGenerator.getFileReference(
path: Path(dependency.reference),
@@ -528,10 +517,10 @@ public class PBXProjGenerator {
let buildFile = createObject(
id: "framework file reference" + target.name,
PBXBuildFile(fileReference: fileReference)
PBXBuildFile(file: fileReference)
)
targetFrameworkBuildFiles.append(buildFile.reference)
targetFrameworkBuildFiles.append(buildFile)
if !frameworkFiles.contains(fileReference) {
frameworkFiles.append(fileReference)
}
@@ -539,9 +528,9 @@ public class PBXProjGenerator {
if embed {
let embedFile = createObject(
id: "framework embed file" + target.name,
PBXBuildFile(fileReference: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
PBXBuildFile(file: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
)
copyFrameworksReferences.append(embedFile.reference)
copyFrameworksReferences.append(embedFile)
}
let buildPath = Path(dependency.reference).parent().string.quoted
@@ -559,12 +548,12 @@ public class PBXProjGenerator {
let buildFile = createObject(
id: "carthage dependency build file" + target.name,
PBXBuildFile(fileReference: fileReference)
PBXBuildFile(file: fileReference)
)
carthageFrameworksByPlatform[target.platform.carthageDirectoryName, default: []].insert(fileReference)
targetFrameworkBuildFiles.append(buildFile.reference)
targetFrameworkBuildFiles.append(buildFile)
// Embedding handled by iterating over `carthageDependencies` below
}
@@ -586,9 +575,9 @@ public class PBXProjGenerator {
if directlyEmbedCarthage {
let embedFile = createObject(
id: "carthage embed" + target.name,
PBXBuildFile(fileReference: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
PBXBuildFile(file: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
)
copyFrameworksReferences.append(embedFile.reference)
copyFrameworksReferences.append(embedFile)
} else {
carthageFrameworksToEmbed.append(dependency.reference)
}
@@ -596,9 +585,9 @@ public class PBXProjGenerator {
}
let fileReference = targetFileReferences[target.name]
var buildPhases: [PBXObjectReference] = []
var buildPhases: [PBXBuildPhase] = []
func getBuildFilesForSourceFiles(_ sourceFiles: [SourceFile]) -> [PBXObjectReference] {
func getBuildFilesForSourceFiles(_ sourceFiles: [SourceFile]) -> [PBXBuildFile] {
let files = sourceFiles
.reduce(into: [SourceFile]()) { output, sourceFile in
if !output.contains(where: { $0.fileReference == sourceFile.fileReference }) {
@@ -607,16 +596,15 @@ public class PBXProjGenerator {
}
.sorted { $0.path.lastComponent < $1.path.lastComponent }
return files.map { createObject(id: $0.path.string + target.name, $0.buildFile) }
.map { $0.reference }
}
func getBuildFilesForPhase(_ buildPhase: BuildPhase) -> [PBXObjectReference] {
func getBuildFilesForPhase(_ buildPhase: BuildPhase) -> [PBXBuildFile] {
let filteredSourceFiles = sourceFiles
.filter { $0.buildPhase?.buildPhase == buildPhase }
return getBuildFilesForSourceFiles(filteredSourceFiles)
}
func getBuildFilesForCopyFilesPhases() -> [TargetSource.BuildPhase.CopyFilesSettings: [PBXObjectReference]] {
func getBuildFilesForCopyFilesPhases() -> [TargetSource.BuildPhase.CopyFilesSettings: [PBXBuildFile]] {
var sourceFilesByCopyFiles: [TargetSource.BuildPhase.CopyFilesSettings: [SourceFile]] = [:]
for sourceFile in sourceFiles {
guard case let .copyFiles(copyFilesSettings)? = sourceFile.buildPhase else { continue }
@@ -629,18 +617,18 @@ public class PBXProjGenerator {
let headersBuildPhaseFiles = getBuildFilesForPhase(.headers)
if !headersBuildPhaseFiles.isEmpty && (target.type == .framework || target.type == .dynamicLibrary) {
let headersBuildPhase = createObject(id: target.name, PBXHeadersBuildPhase(fileReferences: headersBuildPhaseFiles))
buildPhases.append(headersBuildPhase.reference)
let headersBuildPhase = createObject(id: target.name, PBXHeadersBuildPhase(files: headersBuildPhaseFiles))
buildPhases.append(headersBuildPhase)
}
let sourcesBuildPhaseFiles = getBuildFilesForPhase(.sources)
let sourcesBuildPhase = createObject(id: target.name, PBXSourcesBuildPhase(fileReferences: sourcesBuildPhaseFiles))
buildPhases.append(sourcesBuildPhase.reference)
let sourcesBuildPhase = createObject(id: target.name, PBXSourcesBuildPhase(files: sourcesBuildPhaseFiles))
buildPhases.append(sourcesBuildPhase)
let resourcesBuildPhaseFiles = getBuildFilesForPhase(.resources) + copyResourcesReferences
if !resourcesBuildPhaseFiles.isEmpty {
let resourcesBuildPhase = createObject(id: target.name, PBXResourcesBuildPhase(fileReferences: resourcesBuildPhaseFiles))
buildPhases.append(resourcesBuildPhase.reference)
let resourcesBuildPhase = createObject(id: target.name, PBXResourcesBuildPhase(files: resourcesBuildPhaseFiles))
buildPhases.append(resourcesBuildPhase)
}
let buildSettings = project.getCombinedBuildSettings(basePath: project.basePath, target: target, config: project.configs[0])
@@ -655,7 +643,6 @@ public class PBXProjGenerator {
let script = createObject(
id: "Swift.h" + target.name,
PBXShellScriptBuildPhase(
fileReferences: [],
name: "Copy Swift Objective-C Interface Header",
inputPaths: inputPaths,
outputPaths: outputPaths,
@@ -663,7 +650,7 @@ public class PBXProjGenerator {
shellScript: "ditto \"${SCRIPT_INPUT_FILE_0}\" \"${SCRIPT_OUTPUT_FILE_0}\"\n"
)
)
buildPhases.append(script.reference)
buildPhases.append(script)
}
copyFilesBuildPhasesFiles.merge(getBuildFilesForCopyFilesPhases()) { $0 + $1 }
@@ -674,11 +661,11 @@ public class PBXProjGenerator {
PBXCopyFilesBuildPhase(
dstPath: copyFiles.subpath,
dstSubfolderSpec: copyFiles.destination.destination,
fileReferences: buildPhaseFiles
files: buildPhaseFiles
)
)
buildPhases.append(copyFilesBuildPhase.reference)
buildPhases.append(copyFilesBuildPhase)
}
}
@@ -686,9 +673,9 @@ public class PBXProjGenerator {
let frameworkBuildPhase = createObject(
id: target.name,
PBXFrameworksBuildPhase(fileReferences: targetFrameworkBuildFiles)
PBXFrameworksBuildPhase(files: targetFrameworkBuildFiles)
)
buildPhases.append(frameworkBuildPhase.reference)
buildPhases.append(frameworkBuildPhase)
}
if !extensions.isEmpty {
@@ -699,11 +686,11 @@ public class PBXProjGenerator {
dstPath: "",
dstSubfolderSpec: .plugins,
name: "Embed App Extensions",
fileReferences: extensions
files: extensions
)
)
buildPhases.append(copyFilesPhase.reference)
buildPhases.append(copyFilesPhase)
}
copyFrameworksReferences += getBuildFilesForPhase(.frameworks)
@@ -715,11 +702,11 @@ public class PBXProjGenerator {
dstPath: "",
dstSubfolderSpec: .frameworks,
name: "Embed Frameworks",
fileReferences: copyFrameworksReferences
files: copyFrameworksReferences
)
)
buildPhases.append(copyFilesPhase.reference)
buildPhases.append(copyFilesPhase)
}
if !copyWatchReferences.isEmpty {
@@ -730,11 +717,11 @@ public class PBXProjGenerator {
dstPath: "$(CONTENTS_FOLDER_PATH)/Watch",
dstSubfolderSpec: .productsDirectory,
name: "Embed Watch Content",
fileReferences: copyWatchReferences
files: copyWatchReferences
)
)
buildPhases.append(copyFilesPhase.reference)
buildPhases.append(copyFilesPhase)
}
if !carthageFrameworksToEmbed.isEmpty {
@@ -747,7 +734,6 @@ public class PBXProjGenerator {
let carthageScript = createObject(
id: "Carthage" + target.name,
PBXShellScriptBuildPhase(
fileReferences: [],
name: "Carthage",
inputPaths: inputPaths,
outputPaths: outputPaths,
@@ -755,7 +741,7 @@ public class PBXProjGenerator {
shellScript: "\(carthageExecutable) copy-frameworks\n"
)
)
buildPhases.append(carthageScript.reference)
buildPhases.append(carthageScript)
}
let buildRules = target.buildRules.map { buildRule in
@@ -771,7 +757,7 @@ public class PBXProjGenerator {
outputFilesCompilerFlags: buildRule.outputFilesCompilerFlags,
script: buildRule.action.script
)
).reference
)
}
buildPhases += try target.postbuildScripts.map { try generateBuildScript(targetName: target.name, buildScript: $0) }
@@ -850,32 +836,33 @@ public class PBXProjGenerator {
}
}
var baseConfigurationReference: PBXObjectReference?
if let configPath = target.configFiles[config.name] {
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: project.basePath + configPath)
var baseConfiguration: PBXFileReference?
if let configPath = target.configFiles[config.name],
let fileReference = sourceGenerator.getContainedFileReference(path: project.basePath + configPath) as? PBXFileReference{
baseConfiguration = fileReference
}
let buildConfig = XCBuildConfiguration(
name: config.name,
baseConfigurationReference: baseConfigurationReference,
buildSettings: buildSettings
)
buildConfig.baseConfiguration = baseConfiguration
return createObject(id: config.name + target.name, buildConfig)
}
let buildConfigList = createObject(id: target.name, XCConfigurationList(
buildConfigurationsReferences: configs.map { $0.reference },
buildConfigurations: configs,
defaultConfigurationName: ""
))
let targetObject = targetObjects[target.name]!
targetObject.name = target.name
targetObject.buildConfigurationListReference = buildConfigList.reference
targetObject.buildPhasesReferences = buildPhases
targetObject.dependenciesReferences = dependencies
targetObject.buildConfigurationList = buildConfigList
targetObject.buildPhases = buildPhases
targetObject.dependencies = dependencies
targetObject.productName = target.name
targetObject.buildRulesReferences = buildRules
targetObject.productReference = fileReference
targetObject.buildRules = buildRules
targetObject.product = fileReference
if !target.isLegacy {
targetObject.productType = target.type
}
+3 -3
View File
@@ -40,8 +40,8 @@ public class ProjectGenerator {
func getBuildEntry(_ buildTarget: Scheme.BuildTarget) -> XCScheme.BuildAction.Entry {
guard let targetReference = pbxProject.objects.targets(named: buildTarget.target).first else {
fatalError("Unable to find target named \"\(buildTarget.target)\" in \"PBXProj.objects.targets\"")
guard let pbxTarget = pbxProject.targets(named: buildTarget.target).first else {
fatalError("Unable to find target named \"\(buildTarget.target)\" in \"PBXProj.targets\"")
}
guard let buildableName =
@@ -51,7 +51,7 @@ public class ProjectGenerator {
}
let buildableReference = XCScheme.BuildableReference(
referencedContainer: "container:\(project.name).xcodeproj",
blueprintIdentifier: targetReference.reference,
blueprintIdentifier: "", //FIXME: pbxTarget.reference,
buildableName: buildableName,
blueprintName: buildTarget.target
)
+40 -36
View File
@@ -5,15 +5,15 @@ import xcodeproj
struct SourceFile {
let path: Path
let fileReference: PBXObjectReference
let fileReference: PBXFileElement
let buildFile: PBXBuildFile
let buildPhase: TargetSource.BuildPhase?
}
class SourceGenerator {
var rootGroups: Set<PBXObjectReference> = []
private var fileReferencesByPath: [String: PBXObjectReference] = [:]
var rootGroups: Set<PBXFileElement> = []
private var fileReferencesByPath: [String: PBXFileElement] = [:]
private var groupsByPath: [Path: PBXGroup] = [:]
private var variantGroupsByPath: [Path: PBXVariantGroup] = [:]
@@ -91,7 +91,7 @@ class SourceGenerator {
settings["COMPILER_FLAGS"] = targetSource.compilerFlags.joined(separator: " ")
}
let buildFile = PBXBuildFile(fileReference: fileReference, settings: settings.isEmpty ? nil : settings)
let buildFile = PBXBuildFile(file: fileReference, settings: settings.isEmpty ? nil : settings)
return SourceFile(
path: path,
fileReference: fileReference,
@@ -100,7 +100,7 @@ class SourceGenerator {
)
}
func getContainedFileReference(path: Path) -> PBXObjectReference {
func getContainedFileReference(path: Path) -> PBXFileElement {
let createIntermediateGroups = project.options.createIntermediateGroups
let parentPath = path.parent()
@@ -113,12 +113,12 @@ class SourceGenerator {
)
if createIntermediateGroups {
createIntermediaGroups(for: parentGroup.reference, at: parentPath)
createIntermediaGroups(for: parentGroup, at: parentPath)
}
return fileReference
}
func getFileReference(path: Path, inPath: Path, name: String? = nil, sourceTree: PBXSourceTree = .group, lastKnownFileType: String? = nil) -> PBXObjectReference {
func getFileReference(path: Path, inPath: Path, name: String? = nil, sourceTree: PBXSourceTree = .group, lastKnownFileType: String? = nil) -> PBXFileElement {
let fileReferenceKey = path.string.lowercased()
if let fileReference = fileReferencesByPath[fileReferenceKey] {
return fileReference
@@ -138,7 +138,7 @@ class SourceGenerator {
.filter { $0.extension == "xcdatamodel" }
.sorted { $0.string.localizedStandardCompare($1.string) == .orderedAscending }
let modelFileReference =
let modelFileReferences =
sortedPaths.map { path in
createObject(
id: path.byRemovingBase(path: project.basePath).string,
@@ -154,17 +154,17 @@ class SourceGenerator {
let currentVersionPath = findCurrentCoreDataModelVersionPath(using: versionedModels) ?? sortedPaths.last
let currentVersion: PBXFileReference? = {
guard let indexOf = sortedPaths.index(where: { $0 == currentVersionPath }) else { return nil }
return modelFileReference[indexOf]
return modelFileReferences[indexOf]
}()
let versionGroup = addObject(id: fileReferencePath.string, XCVersionGroup(
currentVersion: currentVersion?.reference,
currentVersion: currentVersion,
path: fileReferencePath.string,
sourceTree: sourceTree,
versionGroupType: "wrapper.xcdatamodel",
childrenReferences: modelFileReference.map { $0.reference }
children: modelFileReferences
))
fileReferencesByPath[fileReferenceKey] = versionGroup.reference
return versionGroup.reference
fileReferencesByPath[fileReferenceKey] = versionGroup
return versionGroup
} else {
// For all extensions other than `xcdatamodeld`
let fileReference = createObject(
@@ -176,8 +176,8 @@ class SourceGenerator {
path: fileReferencePath.string
)
)
fileReferencesByPath[fileReferenceKey] = fileReference.reference
return fileReference.reference
fileReferencesByPath[fileReferenceKey] = fileReference
return fileReference
}
}
}
@@ -208,12 +208,16 @@ class SourceGenerator {
/// Create a group or return an existing one at the path.
/// Any merged children are added to a new group or merged into an existing one.
private func getGroup(path: Path, name: String? = nil, mergingChildren children: [PBXObjectReference], createIntermediateGroups: Bool, isBaseGroup: Bool) -> PBXGroup {
private func getGroup(path: Path, name: String? = nil, mergingChildren children: [PBXFileElement], createIntermediateGroups: Bool, isBaseGroup: Bool) -> PBXGroup {
let groupReference: PBXGroup
if let cachedGroup = groupsByPath[path] {
// only add the children that aren't already in the cachedGroup
cachedGroup.childrenReferences = Array(Set(cachedGroup.childrenReferences + children))
for child in children {
// only add the children that aren't already in the cachedGroup
if !cachedGroup.children.contains(child) {
cachedGroup.children.append(child)
}
}
groupReference = cachedGroup
} else {
@@ -231,7 +235,7 @@ class SourceGenerator {
path.byRemovingBase(path: project.basePath).string :
path.lastComponent
let group = PBXGroup(
childrenReferences: children,
children: children,
sourceTree: .group,
name: groupName != groupPath ? groupName : nil,
path: groupPath
@@ -240,7 +244,7 @@ class SourceGenerator {
groupsByPath[path] = groupReference
if isTopLevelGroup {
rootGroups.insert(groupReference.reference)
rootGroups.insert(groupReference)
}
}
return groupReference
@@ -321,7 +325,7 @@ class SourceGenerator {
.filter { $0.extension == "lproj" }
.sorted { $0.lastComponent < $1.lastComponent }
var groupChildren: [PBXObjectReference] = filePaths.map { getFileReference(path: $0, inPath: path) }
var groupChildren: [PBXFileElement] = filePaths.map { getFileReference(path: $0, inPath: path) }
var allSourceFiles: [SourceFile] = filePaths.map {
generateSourceFile(targetType: targetType, targetSource: targetSource, path: $0)
}
@@ -336,11 +340,11 @@ class SourceGenerator {
allSourceFiles += subGroups.sourceFiles
guard let first = subGroups.groups.first else {
guard let firstGroup = subGroups.groups.first else {
continue
}
groupChildren.append(first.reference)
groupChildren.append(firstGroup)
groups += subGroups.groups
}
@@ -363,13 +367,13 @@ class SourceGenerator {
.filter(isIncludedPath)
.sorted() {
let variantGroup = getVariantGroup(path: filePath, inPath: path)
groupChildren.append(variantGroup.reference)
groupChildren.append(variantGroup)
baseLocalisationVariantGroups.append(variantGroup)
let sourceFile = SourceFile(
path: filePath,
fileReference: variantGroup.reference,
buildFile: PBXBuildFile(fileReference: variantGroup.reference),
fileReference: variantGroup,
buildFile: PBXBuildFile(file: variantGroup),
buildPhase: .resources
)
allSourceFiles.append(sourceFile)
@@ -399,15 +403,15 @@ class SourceGenerator {
)
if let variantGroup = variantGroup {
if !variantGroup.childrenReferences.contains(fileReference) {
variantGroup.childrenReferences.append(fileReference)
if !variantGroup.children.contains(fileReference) {
variantGroup.children.append(fileReference)
}
} else {
// add SourceFile to group if there is no Base.lproj directory
let sourceFile = SourceFile(
path: filePath,
fileReference: fileReference,
buildFile: PBXBuildFile(fileReference: fileReference),
buildFile: PBXBuildFile(file: fileReference),
buildPhase: .resources
)
allSourceFiles.append(sourceFile)
@@ -423,7 +427,7 @@ class SourceGenerator {
isBaseGroup: isBaseGroup
)
if project.options.createIntermediateGroups {
createIntermediaGroups(for: group.reference, at: path)
createIntermediaGroups(for: group, at: path)
}
groups.insert(group, at: 0)
@@ -440,7 +444,7 @@ class SourceGenerator {
let createIntermediateGroups = project.options.createIntermediateGroups
var sourceFiles: [SourceFile] = []
let sourceReference: PBXObjectReference
let sourceReference: PBXFileElement
var sourcePath = path
switch type {
case .folder:
@@ -481,7 +485,7 @@ class SourceGenerator {
} else {
let parentGroup = getGroup(path: parentPath, mergingChildren: [fileReference], createIntermediateGroups: createIntermediateGroups, isBaseGroup: true)
sourcePath = parentPath
sourceReference = parentGroup.reference
sourceReference = parentGroup
}
sourceFiles.append(sourceFile)
@@ -493,7 +497,7 @@ class SourceGenerator {
}
sourceFiles += groupSourceFiles
sourceReference = group.reference
sourceReference = group
}
if createIntermediateGroups {
@@ -504,7 +508,7 @@ class SourceGenerator {
}
// Add groups for all parents recursively
private func createIntermediaGroups(for groupReference: PBXObjectReference, at path: Path) {
private func createIntermediaGroups(for fileElement: PBXFileElement, at path: Path) {
let parentPath = path.parent()
guard parentPath != project.basePath && path.string.contains(project.basePath.string) else {
@@ -513,10 +517,10 @@ class SourceGenerator {
}
let hasParentGroup = groupsByPath[parentPath] != nil
let parentGroup = getGroup(path: parentPath, mergingChildren: [groupReference], createIntermediateGroups: true, isBaseGroup: false)
let parentGroup = getGroup(path: parentPath, mergingChildren: [fileElement], createIntermediateGroups: true, isBaseGroup: false)
if !hasParentGroup {
createIntermediaGroups(for: parentGroup.reference, at: parentPath)
createIntermediaGroups(for: parentGroup, at: parentPath)
}
}
+7 -24
View File
@@ -12,8 +12,8 @@ extension PBXFileElement {
extension PBXProj {
public func printGroups() -> String {
guard let project = objects.projects.first?.value,
let mainGroup = objects.groups.getReference(project.mainGroupReference) else {
guard let project = projects.first,
let mainGroup = project.mainGroup else {
return ""
}
return printGroup(group: mainGroup)
@@ -21,14 +21,14 @@ extension PBXProj {
public func printGroup(group: PBXGroup) -> String {
var string = group.nameOrPath
for reference in group.childrenReferences {
if let group = objects.groups.getReference(reference) {
for child in group.children {
if let group = child as? PBXGroup {
string += "\n 📁 " + printGroup(group: group).replacingOccurrences(of: "\n ", with: "\n ")
} else if let fileReference = objects.fileReferences.getReference(reference) {
} else if let fileReference = child as? PBXFileReference {
string += "\n 📄 " + fileReference.nameOrPath
} else if let variantGroup = objects.variantGroups.getReference(reference) {
} else if let variantGroup = child as? PBXVariantGroup {
string += "\n 🌎 " + variantGroup.nameOrPath
} else if let versionGroup = objects.versionGroups.getReference(reference) {
} else if let versionGroup = child as? XCVersionGroup {
string += "\n 🔢 " + versionGroup.nameOrPath
}
}
@@ -36,16 +36,6 @@ extension PBXProj {
}
}
extension PBXObjects {
public func getFileElement(reference: PBXObjectReference) -> PBXFileElement? {
return groups[reference] ??
fileReferences[reference] ??
versionGroups[reference] ??
variantGroups[reference]
}
}
extension Dictionary {
public var valueArray: Array<Value> {
@@ -53,13 +43,6 @@ extension Dictionary {
}
}
extension Dictionary where Key == PBXObjectReference {
public func getReference(_ reference: PBXObjectReference) -> Value? {
return self[reference]
}
}
extension Xcode {
public static func fileType(path: Path) -> String? {
@@ -76,23 +76,6 @@
A6CCC432869EB6B8A65A89B565B57EA5 /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81E39751EDA257E7F7946E95A67FDBBD /* InterfaceController.swift */; };
AA5AF277386012CD6CC015073239E50F /* StandaloneAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 02537F8F3DAD9BF1F249FF662131F1F5 /* StandaloneAssets.xcassets */; };
AD00993C2491D03BD3A1B6E48D685C29 /* MessagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67BB19DDA48C227FF6E676B89FDFCAEB /* MessagesViewController.swift */; };
AUTO_5VZIHqJ600tEPf73suYa = {isa = PBXBuildFile; fileRef = 28C9901BE3ADBC6102849237424B03D6 /* iMessageExtension.appex */; };
AUTO_7MKZu584cIQuU5pdvEAL = {isa = PBXBuildFile; fileRef = EABA2B52871944E6E80A12C64E198883 /* App_iOS_UITests.xctest */; };
AUTO_9aaVkTyiyQWj9chRFSXC = {isa = PBXBuildFile; fileRef = C7F72C86B98DCABE16D17DDC9894C845 /* App_iOS_Tests.xctest */; };
AUTO_CX9m7izxITPbe6k7gIMS = {isa = PBXBuildFile; fileRef = D26369BE2A7A98A736F7A13BA924A4A2 /* iMessageApp.app */; };
AUTO_FHqmKTu8R9eQcDSHtBl2 = {isa = PBXBuildFile; fileRef = 77532D0489A67876EE56705C71C908C6 /* XPC_Service.h */; settings = {ATTRIBUTES = (Public, ); }; };
AUTO_FI4P0L7mD3dfGGVPVNvx = {isa = PBXBuildFile; fileRef = 948EA9EE1BAE66408843BF6200620E70 /* StaticLibrary_ObjC.a */; };
AUTO_GN80IEuWvCvUcPwoAVnt = {isa = PBXBuildFile; fileRef = DBF5F2565C6807B74F18D4ACCE28D071 /* XPC Service.xpc */; };
AUTO_LFQ2NgxpvrhYJSYshySZ = {isa = PBXBuildFile; fileRef = E3C43679A1164385CDC2FCB5DD62C634 /* Framework.framework */; };
AUTO_Ni16m8Y84i5PMkMaGKaR = {isa = PBXBuildFile; fileRef = 42CEA852937FACF2B5D933EC8EC14418 /* App_watchOS Extension.appex */; };
AUTO_OkqadiIPIeuHfZsWVaT8 = {isa = PBXBuildFile; fileRef = E3C43679A1164385CDC2FCB5DD62C634 /* Framework.framework */; };
AUTO_cBeRILf3hWlctfWZW9JQ = {isa = PBXBuildFile; fileRef = E3C43679A1164385CDC2FCB5DD62C634 /* Framework.framework */; };
AUTO_eO1L3NPJcUbCdbs0LA8S = {isa = PBXBuildFile; fileRef = F8D572C96FEC4C18AE61EB3D4D84466C /* XPC_ServiceProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
AUTO_elwIMiarYGjkKHoLYkNz = {isa = PBXBuildFile; fileRef = 715B87EA4FFA97FECCBA0D1D269A19F4 /* StaticLibrary_Swift.a */; };
AUTO_iHu2o18WOxDYzCUar5IX = {isa = PBXBuildFile; fileRef = AE0CDFA0B5B4F5D2FBB870B59FE51154 /* App_macOS.app */; };
AUTO_m5qNHcIsAuTywjDdFCMx = {isa = PBXBuildFile; fileRef = 9FD5A8B54C9F429451BCCCC3F04CDB99 /* App_iOS.app */; };
AUTO_sv3hFquUhPl9qfllDvyL = {isa = PBXBuildFile; fileRef = CFF173E643CE5FF0AE955580CB2B6641 /* App_watchOS.app */; };
AUTO_vusM5sNOIMe1bxFDS6ZY = {isa = PBXBuildFile; fileRef = E3C43679A1164385CDC2FCB5DD62C634 /* Framework.framework */; };
BD4C8B77EF89CF7F4ED0D1C4713397E4 /* FrameworkFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F657AA556F579E2C56BC6BC04E3CAF4 /* FrameworkFile.swift */; };
BD8FA9115EB29C8438DE82A4C33C249A /* SomeFramework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 065FC8C30C4E0AB09C1E77734E46F252 /* SomeFramework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
BE38983978B6D70795D2924F52F3081D /* ResourceFolder in Resources */ = {isa = PBXBuildFile; fileRef = 138DC1A4CB4E585A69355474092AE0E0 /* ResourceFolder */; };
@@ -111,6 +94,8 @@
FA69E7367B9D2F2CB97F57AE7984D9BD /* Framework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E3C43679A1164385CDC2FCB5DD62C634 /* Framework.framework */; };
FF688241378D1AE956E9A9F46EEBCFAA /* Headers in Headers */ = {isa = PBXBuildFile; fileRef = 224967658A2D92DC2BD9D665A1CA1F5F /* Headers */; settings = {ATTRIBUTES = (Public, ); }; };
FFA6D03EB711292F77E0BB317C750F5A /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 32AE52CAD620F8B92487AA4F5924D0EC /* Model.xcdatamodeld */; settings = {COMPILER_FLAGS = "-Werror"; }; };
irhgJ7FX3id0PscP9V19 = {isa = PBXBuildFile; fileRef = F8D572C96FEC4C18AE61EB3D4D84466C /* XPC_ServiceProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
wRIMwRUI5z90K7MaV9ga = {isa = PBXBuildFile; fileRef = 77532D0489A67876EE56705C71C908C6 /* XPC_Service.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -876,8 +861,8 @@
isa = PBXNativeTarget;
buildConfigurationList = 0AA719054B034D653457F3861CE722A9 /* Build configuration list for PBXNativeTarget "Framework_tvOS" */;
buildPhases = (
E74DACDAB11D89D5B824405B81E48D89 /* Sources */,
B6AA01763EF8349E60D1FA4E652778F3 /* Headers */,
E74DACDAB11D89D5B824405B81E48D89 /* Sources */,
C79A51DBA8AF7631AEF22BA83E104A04 /* Frameworks */,
ADF413AF548A97CB33898BB4F6211314 /* MyScript */,
);
@@ -895,8 +880,8 @@
isa = PBXNativeTarget;
buildConfigurationList = CCF68725DCD5EF7FD03872D0B98C32F0 /* Build configuration list for PBXNativeTarget "Framework_watchOS" */;
buildPhases = (
A0301004CBF36C0004B23102202FA9FE /* Sources */,
9C424B9F3AFC563C6A6CE8FA124F8801 /* Headers */,
A0301004CBF36C0004B23102202FA9FE /* Sources */,
F6C2490C6497837A21966090C77C3602 /* Frameworks */,
DABB7DFD3C5DB4EAC8C5D24C79EA4E35 /* MyScript */,
);
@@ -914,8 +899,8 @@
isa = PBXNativeTarget;
buildConfigurationList = 9BA95DBD7B862EE1F43DC68338281D0E /* Build configuration list for PBXNativeTarget "Framework_macOS" */;
buildPhases = (
1411E21883A09388E140C6D123029288 /* Sources */,
A08871F94C4ADE4FF10D349F4ECC06C9 /* Headers */,
1411E21883A09388E140C6D123029288 /* Sources */,
266AF93F95F8ECC5F62E443DD79D4263 /* Frameworks */,
78EF33E6A08B3BB88D8805DC3588843C /* MyScript */,
);
@@ -1115,8 +1100,8 @@
isa = PBXNativeTarget;
buildConfigurationList = ABBCABD06AD7666C13DD9BAF0C16276E /* Build configuration list for PBXNativeTarget "Framework_iOS" */;
buildPhases = (
AFF1863F9CDDD4DD0B0EB22A6AD9850A /* Sources */,
440F7F1F9382CEDD92D75B89E25552D5 /* Headers */,
AFF1863F9CDDD4DD0B0EB22A6AD9850A /* Sources */,
6F3C985C6701880E8731C4AAFBDC9FEF /* Frameworks */,
2983C9312429A22DF5437C4020B9937E /* MyScript */,
);
@@ -1137,7 +1122,17 @@
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0930;
TargetAttributes = "[xcodeproj.PBXObjectReference: [\"TestTargetID\": xcodeproj.PBXObjectReference], xcodeproj.PBXObjectReference: [\"CUSTOM\": \"value\"], xcodeproj.PBXObjectReference: [\"ProvisioningStyle\": \"Automatic\"], xcodeproj.PBXObjectReference: [\"ProvisioningStyle\": \"Automatic\"]]";
TargetAttributes = {
AB59C0690172FF119F045336C1F1CA0D = {
CUSTOM = value;
};
DB85CB6A2C15660854D634EF1B0C1FAD = {
ProvisioningStyle = Automatic;
};
E165F00BB866D2A7087C93650EDB1138 = {
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 0D5965C1A1D5123D687DA32AC9B957F8 /* Build configuration list for PBXProject "Project" */;
compatibilityVersion = "Xcode 3.2";
@@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB85CB6A2C15660854D634EF1B0C1FAD"
BlueprintIdentifier = ""
BuildableName = "App_iOS.app"
BlueprintName = "App_iOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -33,7 +33,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8CDD0FC5B69DB55054CAECF513716138"
BlueprintIdentifier = ""
BuildableName = "App_iOS_Tests.xctest"
BlueprintName = "App_iOS_Tests"
ReferencedContainer = "container:Project.xcodeproj">
@@ -43,7 +43,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B145BCFEB550C3DDF48510BB85CDE8DC"
BlueprintIdentifier = ""
BuildableName = "App_iOS_UITests.xctest"
BlueprintName = "App_iOS_UITests"
ReferencedContainer = "container:Project.xcodeproj">
@@ -53,21 +53,21 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB85CB6A2C15660854D634EF1B0C1FAD"
BlueprintIdentifier = ""
BuildableName = "App_iOS.app"
BlueprintName = "App_iOS"
ReferencedContainer = "container:Project.xcodeproj">
</BuildableReference>
</MacroExpansion>
<CommandLineArguments>
<CommandLineArgument
argument = "MyEnabledArgument"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "MyDisabledArgument"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "MyEnabledArgument"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
@@ -86,21 +86,21 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB85CB6A2C15660854D634EF1B0C1FAD"
BlueprintIdentifier = ""
BuildableName = "App_iOS.app"
BlueprintName = "App_iOS"
ReferencedContainer = "container:Project.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "MyEnabledArgument"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "MyDisabledArgument"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "MyEnabledArgument"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
@@ -115,21 +115,21 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DB85CB6A2C15660854D634EF1B0C1FAD"
BlueprintIdentifier = ""
BuildableName = "App_iOS.app"
BlueprintName = "App_iOS"
ReferencedContainer = "container:Project.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "MyEnabledArgument"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "MyDisabledArgument"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "MyEnabledArgument"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
</ProfileAction>
<AnalyzeAction
@@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9F21B9C99E75314E51854589C0A2D40C"
BlueprintIdentifier = ""
BuildableName = "App_watchOS.app"
BlueprintName = "App_watchOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -32,7 +32,7 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9F21B9C99E75314E51854589C0A2D40C"
BlueprintIdentifier = ""
BuildableName = "App_watchOS.app"
BlueprintName = "App_watchOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -57,7 +57,7 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9F21B9C99E75314E51854589C0A2D40C"
BlueprintIdentifier = ""
BuildableName = "App_watchOS.app"
BlueprintName = "App_watchOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -78,7 +78,7 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9F21B9C99E75314E51854589C0A2D40C"
BlueprintIdentifier = ""
BuildableName = "App_watchOS.app"
BlueprintName = "App_watchOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -14,7 +14,7 @@
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FE8D0077B0ADF688264AFA16A3FC213E"
BlueprintIdentifier = ""
BuildableName = "Framework.framework"
BlueprintName = "Framework_iOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -32,7 +32,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FE8D0077B0ADF688264AFA16A3FC213E"
BlueprintIdentifier = ""
BuildableName = "Framework.framework"
BlueprintName = "Framework_iOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -50,7 +50,7 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FE8D0077B0ADF688264AFA16A3FC213E"
BlueprintIdentifier = ""
BuildableName = "Framework.framework"
BlueprintName = "Framework_iOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -72,7 +72,7 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FE8D0077B0ADF688264AFA16A3FC213E"
BlueprintIdentifier = ""
BuildableName = "Framework.framework"
BlueprintName = "Framework_iOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -101,7 +101,7 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "FE8D0077B0ADF688264AFA16A3FC213E"
BlueprintIdentifier = ""
BuildableName = "Framework.framework"
BlueprintName = "Framework_iOS"
ReferencedContainer = "container:Project.xcodeproj">
@@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "24B389B0959F4A6CB05BB732DABDFE40"
BlueprintIdentifier = ""
BuildableName = "iMessageApp.app"
BlueprintName = "iMessageApp"
ReferencedContainer = "container:Project.xcodeproj">
@@ -32,7 +32,7 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "24B389B0959F4A6CB05BB732DABDFE40"
BlueprintIdentifier = ""
BuildableName = "iMessageApp.app"
BlueprintName = "iMessageApp"
ReferencedContainer = "container:Project.xcodeproj">
@@ -57,7 +57,7 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "24B389B0959F4A6CB05BB732DABDFE40"
BlueprintIdentifier = ""
BuildableName = "iMessageApp.app"
BlueprintName = "iMessageApp"
ReferencedContainer = "container:Project.xcodeproj">
@@ -78,7 +78,7 @@
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "24B389B0959F4A6CB05BB732DABDFE40"
BlueprintIdentifier = ""
BuildableName = "iMessageApp.app"
BlueprintName = "iMessageApp"
ReferencedContainer = "container:Project.xcodeproj">
@@ -32,12 +32,12 @@ extension PBXProj {
let mainGroup = try getMainGroup()
func validateGroup(_ group: PBXGroup) throws {
let hasDuplicatedChildren = group.childrenReferences.count != Set(group.childrenReferences).count
let hasDuplicatedChildren = group.children.count != Set(group.children).count
if hasDuplicatedChildren {
throw failure("Group \"\(group.nameOrPath)\" has duplicated children:\n - \(group.childrenReferences.map { String(describing: $0) }.joined(separator: "\n - "))")
throw failure("Group \"\(group.nameOrPath)\" has duplicated children:\n - \(group.children.map { String(describing: $0) }.joined(separator: "\n - "))")
}
for child in group.childrenReferences {
if let group = objects.groups.getReference(child) {
for child in group.children {
if let group = child as? PBXGroup {
try validateGroup(group)
}
}
@@ -20,11 +20,11 @@ class ProjectFixtureTests: XCTestCase {
guard let xcodeProject = xcodeProject else { return }
func getFileReferences(_ path: String) -> [PBXFileReference] {
return xcodeProject.pbxproj.objects.fileReferences.values.filter { $0.path == path }
return xcodeProject.pbxproj.fileReferences.filter { $0.path == path }
}
func getVariableGroups(_ name: String?) -> [PBXVariantGroup] {
return xcodeProject.pbxproj.objects.variantGroups.values.filter { $0.name == name }
return xcodeProject.pbxproj.variantGroups.filter { $0.name == name }
}
let resourceName = "LocalizedStoryboard.storyboard"
@@ -36,13 +36,13 @@ class ProjectFixtureTests: XCTestCase {
do {
let refs = getFileReferences(baseResource)
try expect(refs.count) == 1
try expect(variableGroup.childrenReferences.filter { $0 == refs.first?.reference }.count) == 1
try expect(variableGroup.children.filter { $0 == refs.first }.count) == 1
}
do {
let refs = getFileReferences(localizedResource)
try expect(refs.count) == 1
try expect(variableGroup.childrenReferences.filter { $0 == refs.first?.reference }.count) == 1
try expect(variableGroup.children.filter { $0 == refs.first }.count) == 1
}
}
@@ -41,11 +41,9 @@ class ProjectGeneratorTests: XCTestCase {
let options = SpecOptions(bundleIdPrefix: "com.test")
let project = Project(basePath: "", name: "test", targets: [framework], options: options)
let pbxProj = try project.generatePbxProj()
guard let target = pbxProj.objects.nativeTargets.first?.value,
let buildConfigList = target.buildConfigurationListReference,
let buildConfigs = pbxProj.objects.configurationLists.getReference(buildConfigList),
let buildConfigReference = buildConfigs.buildConfigurationsReferences.first,
let buildConfig = pbxProj.objects.buildConfigurations.getReference(buildConfigReference) else {
guard let target = pbxProj.nativeTargets.first,
let buildConfigList = target.buildConfigurationList,
let buildConfig = buildConfigList.buildConfigurations.first else {
throw failure("Build Config not found")
}
try expect(buildConfig.buildSettings["PRODUCT_BUNDLE_IDENTIFIER"] as? String) == "com.test.MyFramework"
@@ -55,7 +53,7 @@ class ProjectGeneratorTests: XCTestCase {
let options = SpecOptions(settingPresets: .none)
let project = Project(basePath: "", name: "test", targets: [framework], options: options)
let pbxProj = try project.generatePbxProj()
let allSettings = pbxProj.objects.buildConfigurations.values.reduce([:]) { $0.merged($1.buildSettings) }.keys.sorted()
let allSettings = pbxProj.buildConfigurations.reduce([:]) { $0.merged($1.buildSettings) }.keys.sorted()
try expect(allSettings) == ["SETTING_2"]
}
@@ -63,7 +61,7 @@ class ProjectGeneratorTests: XCTestCase {
let options = SpecOptions(developmentLanguage: "de")
let project = Project(basePath: "", name: "test", options: options)
let pbxProj = try project.generatePbxProj()
guard let pbxProject = pbxProj.objects.projects.first?.value else {
guard let pbxProject = pbxProj.projects.first else {
throw failure("Could't find PBXProject")
}
try expect(pbxProject.developmentRegion) == "de"
@@ -92,8 +90,8 @@ class ProjectGeneratorTests: XCTestCase {
let project = Project(basePath: "", name: "test", configs: [Config(name: "Aconfig"), Config(name: "Bconfig")], targets: [framework], options: options)
let pbxProject = try project.generatePbxProj()
guard let projectConfigListReference = pbxProject.objects.projects.values.first?.buildConfigurationListReference,
let defaultConfigurationName = pbxProject.objects.configurationLists[projectConfigListReference]?.defaultConfigurationName
guard let projectConfigList = pbxProject.projects.first?.buildConfigurationList,
let defaultConfigurationName = projectConfigList.defaultConfigurationName
else {
throw failure("Default configuration name not found")
}
@@ -109,7 +107,7 @@ class ProjectGeneratorTests: XCTestCase {
$0.it("generates config defaults") {
let project = Project(basePath: "", name: "test")
let pbxProj = try project.generatePbxProj()
let configs = pbxProj.objects.buildConfigurations.valueArray
let configs = pbxProj.buildConfigurations
try expect(configs.count) == 2
try expect(configs).contains(name: "Debug")
try expect(configs).contains(name: "Release")
@@ -122,7 +120,7 @@ class ProjectGeneratorTests: XCTestCase {
configs: [Config(name: "config1"), Config(name: "config2")]
)
let pbxProj = try project.generatePbxProj()
let configs = pbxProj.objects.buildConfigurations.valueArray
let configs = pbxProj.buildConfigurations
try expect(configs.count) == 2
try expect(configs).contains(name: "config1")
try expect(configs).contains(name: "config2")
@@ -135,7 +133,7 @@ class ProjectGeneratorTests: XCTestCase {
configs: [Config(name: "config")]
)
let pbxProj = try project.generatePbxProj()
guard let config = pbxProj.objects.buildConfigurations.first?.value else {
guard let config = pbxProj.buildConfigurations.first else {
throw failure("configuration not found")
}
try expect(config.buildSettings.isEmpty).to.beTrue()
@@ -198,8 +196,8 @@ class ProjectGeneratorTests: XCTestCase {
$0.it("generates aggregate targets") {
let pbxProject = try project.generatePbxProj()
let nativeTargets = pbxProject.objects.nativeTargets.valueArray.sorted { $0.name < $1.name }
let aggregateTargets = pbxProject.objects.aggregateTargets.valueArray.sorted { $0.name < $1.name }
let nativeTargets = pbxProject.nativeTargets.sorted { $0.name < $1.name }
let aggregateTargets = pbxProject.aggregateTargets.sorted { $0.name < $1.name }
try expect(nativeTargets.count) == 4
try expect(aggregateTargets.count) == 2
@@ -216,7 +214,7 @@ class ProjectGeneratorTests: XCTestCase {
let target2 = nativeTargets.first { $0.name == "Other2" }
try expect(target2?.dependencies.count) == 2
try expect(pbxProject.objects.targetDependencies.count) == 7
try expect(pbxProject.targetDependencies.count) == 7
}
}
}
@@ -228,7 +226,7 @@ class ProjectGeneratorTests: XCTestCase {
$0.it("generates targets") {
let pbxProject = try project.generatePbxProj()
let nativeTargets = pbxProject.objects.nativeTargets.values
let nativeTargets = pbxProject.nativeTargets
try expect(nativeTargets.count) == 3
try expect(nativeTargets.contains { $0.name == app.name }).beTrue()
try expect(nativeTargets.contains { $0.name == framework.name }).beTrue()
@@ -245,22 +243,22 @@ class ProjectGeneratorTests: XCTestCase {
let project = Project(basePath: "", name: "test", targets: [appTargetWithAttributes, framework, testTargetWithAttributes])
let pbxProject = try project.generatePbxProj()
guard let targetAttributes = pbxProject.objects.projects.values.first?.attributes["TargetAttributes"] as? [PBXObjectReference: [String: Any]] else {
guard let targetAttributes = pbxProject.projects.first?.targetAttributes else {
throw failure("Couldn't find Project TargetAttributes")
}
guard let appTarget = pbxProject.objects.targets(named: app.name).first else {
guard let appTarget = pbxProject.targets(named: app.name).first else {
throw failure("Couldn't find App Target")
}
guard let uiTestTarget = pbxProject.objects.targets(named: uiTest.name).first else {
guard let uiTestTarget = pbxProject.targets(named: uiTest.name).first else {
throw failure("Couldn't find UITest Target")
}
//try expect(targetAttributes[uiTestTarget.reference]?["TestTargetID"] as? String) == appTarget.reference.value
try expect(targetAttributes[uiTestTarget.reference]?["ProvisioningStyle"] as? String) == "Manual"
try expect(targetAttributes[appTarget.reference]?["ProvisioningStyle"] as? String) == "Automatic"
try expect(targetAttributes[appTarget.reference]?["DevelopmentTeam"] as? String) == "123"
try expect(targetAttributes[uiTestTarget]?["ProvisioningStyle"] as? String) == "Manual"
try expect(targetAttributes[appTarget]?["ProvisioningStyle"] as? String) == "Automatic"
try expect(targetAttributes[appTarget]?["DevelopmentTeam"] as? String) == "123"
}
$0.it("generates platform version") {
@@ -269,16 +267,14 @@ class ProjectGeneratorTests: XCTestCase {
let pbxProject = try project.generatePbxProj()
guard let projectConfigListReference = pbxProject.objects.projects.values.first?.buildConfigurationListReference,
let projectConfigReference = pbxProject.objects.configurationLists[projectConfigListReference]?.buildConfigurationsReferences.first,
let projectConfig = pbxProject.objects.buildConfigurations[projectConfigReference]
guard let projectConfigList = pbxProject.projects.first?.buildConfigurationList,
let projectConfig = projectConfigList.buildConfigurations.first
else {
throw failure("Couldn't find Project config")
}
guard let targetConfigListReference = pbxProject.objects.nativeTargets.values.first?.buildConfigurationListReference,
let targetConfigReference = pbxProject.objects.configurationLists[targetConfigListReference]?.buildConfigurationsReferences.first,
let targetConfig = pbxProject.objects.buildConfigurations[targetConfigReference]
guard let targetConfigList = pbxProject.nativeTargets.first?.buildConfigurationList,
let targetConfig = targetConfigList.buildConfigurations.first
else {
throw failure("Couldn't find Target config")
}
@@ -295,14 +291,14 @@ class ProjectGeneratorTests: XCTestCase {
$0.it("generates dependencies") {
let pbxProject = try project.generatePbxProj()
let nativeTargets = pbxProject.objects.nativeTargets.values
let dependencies = pbxProject.objects.targetDependencies.valueArray.sorted { (try? $0.target())??.name ?? "" < (try? $1.target())??.name ?? "" }
let nativeTargets = pbxProject.nativeTargets
let dependencies = pbxProject.targetDependencies.sorted { $0.target?.name ?? "" < $1.target?.name ?? "" }
try expect(dependencies.count) == 2
let appTarget = nativeTargets.first { $0.object.name == app.name }
let frameworkTarget = nativeTargets.first { $0.object.name == framework.name }
let appTarget = nativeTargets.first { $0.name == app.name }
let frameworkTarget = nativeTargets.first { $0.name == framework.name }
try expect(dependencies).contains { $0.object.target == appTarget?.reference }
try expect(dependencies).contains { $0.object.target == frameworkTarget?.reference }
try expect(dependencies).contains { $0.target == appTarget }
try expect(dependencies).contains { $0.target == frameworkTarget }
}
$0.it("generates targets with correct transitive embeds") {
@@ -542,20 +538,21 @@ class ProjectGeneratorTests: XCTestCase {
let pbxProject = try project.generatePbxProj()
for target in targets {
guard let nativeTarget = pbxProject.objects.nativeTargets.values.first(where: { $0.name == target.name }) else {
guard let nativeTarget = pbxProject.nativeTargets.first(where: { $0.name == target.name }) else {
throw failure("PBXNativeTarget for \(target) not found")
}
let buildPhases = nativeTarget.buildPhasesReferences
let resourcesPhases = pbxProject.objects.resourcesBuildPhases.values.filter { buildPhases.contains($0.reference) }
let frameworkPhases = pbxProject.objects.frameworksBuildPhases.values.filter { buildPhases.contains($0.reference) }
let copyFilesPhases = pbxProject.objects.copyFilesBuildPhases.values.filter { buildPhases.contains($0.reference) }
let buildPhases = nativeTarget.buildPhases
let resourcesPhases = pbxProject.resourcesBuildPhases.filter { buildPhases.contains($0) }
let frameworkPhases = pbxProject.frameworksBuildPhases.filter { buildPhases.contains($0) }
let copyFilesPhases = pbxProject.copyFilesBuildPhases.filter { buildPhases.contains($0) }
// ensure only the right resources are copies, no more, no less
let expectedResourceFiles = expectedResourceFiles[target.name]!
try expect(resourcesPhases.count) == (expectedResourceFiles.isEmpty ? 0 : 1)
if !expectedResourceFiles.isEmpty {
let resourceFiles = resourcesPhases[0].fileReferences
.compactMap { pbxProject.objects.buildFiles[$0]?.fileReference.flatMap { pbxProject.objects.fileReferences[$0]?.nameOrPath } }
let resourceFiles = resourcesPhases[0].files
.compactMap { $0.file }
.map { $0.nameOrPath }
try expect(Set(resourceFiles)) == expectedResourceFiles
}
@@ -563,8 +560,8 @@ class ProjectGeneratorTests: XCTestCase {
let expectedLinkedFiles = expectedLinkedFiles[target.name]!
try expect(frameworkPhases.count) == (expectedLinkedFiles.isEmpty ? 0 : 1)
if !expectedLinkedFiles.isEmpty {
let linkFrameworks = frameworkPhases[0].fileReferences
.compactMap { pbxProject.objects.buildFiles[$0]?.fileReference.flatMap { pbxProject.objects.fileReferences[$0]?.nameOrPath } }
let linkFrameworks = frameworkPhases[0].files
.compactMap { $0.file?.nameOrPath }
try expect(Set(linkFrameworks)) == expectedLinkedFiles
}
@@ -572,8 +569,8 @@ class ProjectGeneratorTests: XCTestCase {
let expectedEmbeddedFrameworks = expectedEmbeddedFrameworks[target.name]!
try expect(copyFilesPhases.count) == (expectedEmbeddedFrameworks.isEmpty ? 0 : 1)
if !expectedEmbeddedFrameworks.isEmpty {
let copyFiles = copyFilesPhases[0].fileReferences
.compactMap { pbxProject.objects.buildFiles[$0]?.fileReference.flatMap { pbxProject.objects.fileReferences[$0]?.nameOrPath } }
let copyFiles = copyFilesPhases[0].files
.compactMap { $0.file?.nameOrPath }
try expect(Set(copyFiles)) == expectedEmbeddedFrameworks
}
}
@@ -640,11 +637,9 @@ class ProjectGeneratorTests: XCTestCase {
let pbxProj = try project.generatePbxProj()
func buildSettings(for target: Target) throws -> BuildSettings {
guard let nativeTarget = pbxProj.objects.targets(named: target.name).first,
let buildConfigList = nativeTarget.buildConfigurationListReference,
let buildConfigs = pbxProj.objects.configurationLists.getReference(buildConfigList),
let buildConfigReference = buildConfigs.buildConfigurationsReferences.first,
let buildConfig = pbxProj.objects.buildConfigurations.getReference(buildConfigReference) else {
guard let nativeTarget = pbxProj.targets(named: target.name).first,
let buildConfigList = nativeTarget.buildConfigurationList,
let buildConfig = buildConfigList.buildConfigurations.first else {
throw failure("XCBuildConfiguration not found for Target \(target.name.quoted)")
}
@@ -698,16 +693,15 @@ class ProjectGeneratorTests: XCTestCase {
let pbxProject = try project.generatePbxProj()
func scriptBuildPhases(target: Target) throws -> [PBXShellScriptBuildPhase] {
guard let nativeTarget = pbxProject.objects.nativeTargets.values.first(where: { $0.name == target.name }) else {
guard let nativeTarget = pbxProject.nativeTargets.first(where: { $0.name == target.name }) else {
throw failure("PBXNativeTarget for \(target) not found")
}
let buildPhases = nativeTarget.buildPhasesReferences
let scriptPhases = pbxProject.objects.shellScriptBuildPhases.values.filter { buildPhases.contains($0.reference) }
let buildPhases = nativeTarget.buildPhases
let scriptPhases = buildPhases.compactMap { $0 as? PBXShellScriptBuildPhase }
return scriptPhases
}
let expectedScriptPhase = PBXShellScriptBuildPhase(
fileReferences: [],
name: "Copy Swift Objective-C Interface Header",
inputPaths: ["$(DERIVED_SOURCES_DIR)/$(SWIFT_OBJC_INTERFACE_HEADER_NAME)"],
outputPaths: ["$(BUILT_PRODUCTS_DIR)/include/$(PRODUCT_MODULE_NAME)/$(SWIFT_OBJC_INTERFACE_HEADER_NAME)"],
@@ -726,18 +720,18 @@ class ProjectGeneratorTests: XCTestCase {
scriptSpec.targets[0].postbuildScripts = [BuildScript(script: .script("script2"))]
let pbxProject = try scriptSpec.generatePbxProj()
guard let nativeTarget = pbxProject.objects.nativeTargets.values
.first(where: { $0.buildPhasesReferences.count >= 2 }) else {
guard let nativeTarget = pbxProject.nativeTargets
.first(where: { $0.buildPhases.count >= 2 }) else {
throw failure("Target with build phases not found")
}
let buildPhases = nativeTarget.buildPhasesReferences
let buildPhases = nativeTarget.buildPhases
let scripts = pbxProject.objects.shellScriptBuildPhases.valueArray
let scripts = pbxProject.shellScriptBuildPhases
let script1 = scripts.first { $0.shellScript == "script1" }
let script2 = scripts.first { $0.shellScript == "script2" }
try expect(scripts.count) == 2
try expect(buildPhases.first) == script1?.reference
try expect(buildPhases.last) == script2?.reference
try expect(buildPhases.first) == script1
try expect(buildPhases.last) == script2
}
$0.it("generates targets with cylical dependencies") {
@@ -779,7 +773,7 @@ class ProjectGeneratorTests: XCTestCase {
]
let pbxProject = try scriptSpec.generatePbxProj()
let buildRules = pbxProject.objects.buildRules.values
let buildRules = pbxProject.buildRules
try expect(buildRules.count) == 2
let first = buildRules.first { $0.name == "My Rule" }!
let second = buildRules.first { $0.name != "My Rule" }!
@@ -821,7 +815,7 @@ class ProjectGeneratorTests: XCTestCase {
schemes: [scheme]
)
let xcodeProject = try project.generateXcodeProject()
guard let target = xcodeProject.pbxproj.objects.nativeTargets.values
guard let target = xcodeProject.pbxproj.nativeTargets
.first(where: { $0.name == app.name }) else {
throw failure("Target not found")
}
@@ -848,7 +842,7 @@ class ProjectGeneratorTests: XCTestCase {
].compactMap { $0 }
for buildableReference in buildableReferences {
try expect(buildableReference.blueprintIdentifier) == target.reference
//FIXME: try expect(buildableReference.blueprintIdentifier) == target.reference
try expect(buildableReference.blueprintName) == target.name
try expect(buildableReference.buildableName) == "\(target.name).\(target.productType!.fileExtension!)"
}
@@ -886,7 +880,7 @@ class ProjectGeneratorTests: XCTestCase {
}
try expect(
xcodeProject.pbxproj.objects.nativeTargets.values
xcodeProject.pbxproj.nativeTargets
.contains(where: { $0.name == app.name })
).beTrue()
try expect(xcscheme.launchAction?.environmentVariables) == runVariables
@@ -910,7 +904,7 @@ class ProjectGeneratorTests: XCTestCase {
try expect(xcodeProject.sharedData?.schemes.count) == 2
guard let nativeTarget = xcodeProject.pbxproj.objects.nativeTargets.values
guard let nativeTarget = xcodeProject.pbxproj.nativeTargets
.first(where: { $0.name == app.name }) else {
throw failure("Target not found")
}
@@ -922,7 +916,7 @@ class ProjectGeneratorTests: XCTestCase {
throw failure("Build Action entry not found")
}
try expect(buildActionEntry.buildableReference.blueprintIdentifier) == nativeTarget.reference
//FIXME: try expect(buildActionEntry.buildableReference.blueprintIdentifier) == nativeTarget
try expect(xcscheme.launchAction?.buildConfiguration) == "Test Debug"
try expect(xcscheme.testAction?.buildConfiguration) == "Test Debug"
@@ -85,18 +85,18 @@ class SourceGeneratorTests: XCTestCase {
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let pbxProj = try project.generatePbxProj()
try pbxProj.expectFile(paths: ["Sources", "Bar.swift"], buildPhase: .sources)
let buildPhase = pbxProj.objects.copyFilesBuildPhases.values.first
let buildPhase = pbxProj.copyFilesBuildPhases.first
try expect(buildPhase?.dstSubfolderSpec) == .frameworks
let fileReference = pbxProj.getFileReference(
paths: ["Sources", "Foo.framework"],
names: ["Sources", "Foo.framework"]
)?.reference
guard let buildFile = pbxProj.objects.buildFiles.valueArray
.first(where: { $0.fileReference == fileReference })?.reference else {
)
guard let buildFile = pbxProj.buildFiles
.first(where: { $0.file == fileReference }) else {
throw failure("Cant find build file")
}
try expect(buildPhase?.fileReferences.count) == 1
try expect(buildPhase?.fileReferences.contains(buildFile)) == true
try expect(buildPhase?.files.count) == 1
try expect(buildPhase?.files.contains(buildFile)) == true
}
$0.it("generates core data models") {
@@ -114,16 +114,16 @@ class SourceGeneratorTests: XCTestCase {
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let pbxProj = try project.generatePbxProj()
guard let fileReference = pbxProj.objects.fileReferences.first(where: { $0.value.nameOrPath == "model2.xcdatamodel" }) else {
guard let fileReference = pbxProj.fileReferences.first(where: { $0.nameOrPath == "model2.xcdatamodel" }) else {
throw failure("Couldn't find model file reference")
}
guard let versionGroup = pbxProj.objects.versionGroups.values.first else {
guard let versionGroup = pbxProj.versionGroups.first else {
throw failure("Couldn't find version group")
}
try expect(versionGroup.currentVersion) == fileReference.key
try expect(versionGroup.childrenReferences.count) == 3
try expect(versionGroup.currentVersion) == fileReference
try expect(versionGroup.children.count) == 3
try expect(versionGroup.path) == "model.xcdatamodeld"
try expect(fileReference.value.path) == "model2.xcdatamodel"
try expect(fileReference.path) == "model2.xcdatamodel"
}
$0.it("handles duplicate names") {
@@ -460,11 +460,9 @@ class SourceGeneratorTests: XCTestCase {
let pbxProj = try project.generatePbxProj()
try pbxProj.expectFile(paths: ["Sources/A", "a.swift"], names: ["A", "a.swift"], buildPhase: .sources)
let sourcesBuildPhase = pbxProj.objects.buildPhases
.first(where: { $0.1.buildPhase == BuildPhase.sources })!
.value
let sourcesBuildPhase = pbxProj.buildPhases.first(where: { $0.buildPhase == BuildPhase.sources })!
try expect(sourcesBuildPhase.fileReferences.count) == 1
try expect(sourcesBuildPhase.files.count) == 1
}
$0.it("derived directories are sorted last") {
@@ -482,7 +480,7 @@ class SourceGeneratorTests: XCTestCase {
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let pbxProj = try project.generatePbxProj()
let groups = try pbxProj.getMainGroup().childrenReferences.compactMap { pbxProj.objects.getFileElement(reference: $0)?.nameOrPath }
let groups = try pbxProj.getMainGroup().children.map { $0.nameOrPath }
try expect(groups) == ["A", "P", "S", "Frameworks", "Products"]
}
@@ -506,8 +504,8 @@ class SourceGeneratorTests: XCTestCase {
let pbxProj = try project.generatePbxProj()
let mainGroup = try pbxProj.getMainGroup()
let group = mainGroup.childrenReferences.compactMap { pbxProj.objects.groups[$0]}.first { $0.nameOrPath == "Sources" }!
let names = group.childrenReferences.compactMap { pbxProj.objects.getFileElement(reference: $0)?.nameOrPath }
let group = mainGroup.children.compactMap { $0 as? PBXGroup }.first { $0.nameOrPath == "Sources" }!
let names = group.children.compactMap { $0.nameOrPath }
try expect(names) == [
"1file.a",
"10file.a",
@@ -535,10 +533,10 @@ extension PBXProj {
}
if let buildPhase = buildPhase {
let buildFile = objects.buildFiles.values
.first(where: { $0.fileReference == fileReference.reference })
let buildFile = buildFiles
.first(where: { $0.file == fileReference })
let actualBuildPhase = buildFile
.flatMap { buildFile in objects.buildPhases.values.first { $0.fileReferences.contains(buildFile.reference) } }?.buildPhase
.flatMap { buildFile in buildPhases.first { $0.files.contains(buildFile) } }?.buildPhase
var error: String?
if let buildPhase = buildPhase.buildPhase {
@@ -567,17 +565,13 @@ extension PBXProj {
}
func getFileReference(paths: [String], names: [String], file: String = #file, line: Int = #line) -> PBXFileReference? {
guard let project = objects.projects.first?.value else { return nil }
guard let mainGroup = objects.groups.getReference(project.mainGroupReference) else { return nil }
guard let mainGroup = projects.first?.mainGroup else { return nil }
return getFileReference(group: mainGroup, paths: paths, names: names)
}
func getMainGroup(function: String = #function, file: String = #file, line: Int = #line) throws -> PBXGroup {
guard let project = objects.projects.first?.value else {
throw failure("Couldn't find project", file: file, line: line)
}
guard let mainGroup = objects.groups.getReference(project.mainGroupReference) else {
guard let mainGroup = projects.first?.mainGroup else {
throw failure("Couldn't find main group", file: file, line: line)
}
return mainGroup
@@ -591,10 +585,10 @@ extension PBXProj {
let restOfPath = Array(paths.dropFirst())
let restOfName = Array(names.dropFirst())
if restOfPath.isEmpty {
let fileReferences: [PBXFileReference] = group.childrenReferences.compactMap { self.objects.fileReferences.getReference($0) }
let fileReferences: [PBXFileReference] = group.children.compactMap { $0 as? PBXFileReference }
return fileReferences.first { $0.path == path && $0.nameOrPath == name }
} else {
let groups = group.childrenReferences.compactMap { self.objects.groups.getReference($0) }
let groups = group.children.compactMap { $0 as? PBXGroup }
guard let group = groups.first(where: { $0.path == path && $0.nameOrPath == name }) else { return nil }
return getFileReference(group: group, paths: restOfPath, names: restOfName)
}