Rename uses of spec to project

This commit is contained in:
Yonas Kolb committed 2018-04-12 23:17:07 +10:00
1 parent e589364ae8
commit 29f4fa2123
11 files changed
+362 -362

No files matched your search

+14 -14
View File
@@ -21,37 +21,37 @@ func generate(spec: String, project: String, isQuiet: Bool, justVersion: Bool) {
exit(1)
}
let specPath = Path(spec).absolute()
let projectPath = project == "" ? specPath.parent() : Path(project).absolute()
let projectSpecPath = Path(spec).absolute()
let projectPath = project == "" ? projectSpecPath.parent() : Path(project).absolute()
if !specPath.exists {
fatalError("No project spec found at \(specPath.absolute())")
if !projectSpecPath.exists {
fatalError("No project spec found at \(projectSpecPath.absolute())")
}
let spec: Project
let project: Project
do {
spec = try Project(path: specPath)
logger.info("📋 Loaded spec:\n \(spec.debugDescription.replacingOccurrences(of: "\n", with: "\n "))")
project = try Project(path: projectSpecPath)
logger.info("📋 Loaded project:\n \(project.debugDescription.replacingOccurrences(of: "\n", with: "\n "))")
} catch let error as JSONUtilities.DecodingError {
fatalError("Parsing spec failed: \(error.description)")
fatalError("Parsing project spec failed: \(error.description)")
} catch {
fatalError("Parsing spec failed: \(error.localizedDescription)")
fatalError("Parsing project spec failed: \(error.localizedDescription)")
}
do {
logger.info("⚙️ Generating project...")
let projectGenerator = ProjectGenerator(spec: spec)
let project = try projectGenerator.generateProject()
let projectGenerator = ProjectGenerator(project: project)
let xcodeProject = try projectGenerator.generateXcodeProject()
logger.info("⚙️ Writing project...")
let projectFile = projectPath + "\(spec.name).xcodeproj"
let projectFile = projectPath + "\(project.name).xcodeproj"
let tempPath = Path.temporary + "XcodeGen_\(Int(NSTimeIntervalSince1970))"
try? tempPath.delete()
if projectFile.exists {
try projectFile.copy(tempPath)
}
try project.write(path: tempPath, override: true)
try xcodeProject.write(path: tempPath, override: true)
try? projectFile.delete()
try tempPath.copy(projectFile)
try? tempPath.delete()
@@ -69,7 +69,7 @@ command(
"spec",
default: "project.yml",
flag: "s",
description: "The path to the spec file"
description: "The path to the project spec file"
),
Option<String>(
"project",
+60 -60
View File
@@ -7,9 +7,9 @@ import Yams
public class PBXProjGenerator {
let spec: Project
let project: Project
let proj: PBXProj
let pbxProj: PBXProj
var sourceGenerator: SourceGenerator!
var targetObjects: [String: ObjectReference<PBXTarget>] = [:]
@@ -22,20 +22,20 @@ public class PBXProjGenerator {
var generated = false
var carthageBuildPath: String {
return spec.options.carthageBuildPath ?? "Carthage/Build"
return project.options.carthageBuildPath ?? "Carthage/Build"
}
public init(spec: Project) {
self.spec = spec
proj = PBXProj(rootObject: "", objectVersion: 46)
sourceGenerator = SourceGenerator(spec: spec) { [unowned self] id, object in
public init(project: Project) {
self.project = project
pbxProj = PBXProj(rootObject: "", objectVersion: 46)
sourceGenerator = SourceGenerator(project: project) { [unowned self] id, object in
self.addObject(id: id, object)
}
}
func addObject(id: String, _ object: PBXObject) -> String {
let reference = proj.objects.generateReference(object, id)
proj.objects.addObject(object, reference: reference)
let reference = pbxProj.objects.generateReference(object, id)
pbxProj.objects.addObject(object, reference: reference)
return reference
}
@@ -50,15 +50,15 @@ public class PBXProjGenerator {
}
generated = true
for group in spec.fileGroups {
for group in project.fileGroups {
try sourceGenerator.getFileGroups(path: group)
}
let buildConfigs: [ObjectReference<XCBuildConfiguration>] = spec.configs.map { config in
let buildSettings = spec.getProjectBuildSettings(config: config)
let buildConfigs: [ObjectReference<XCBuildConfiguration>] = project.configs.map { config in
let buildSettings = project.getProjectBuildSettings(config: config)
var baseConfigurationReference: String?
if let configPath = spec.configFiles[config.name] {
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: spec.basePath + configPath)
if let configPath = project.configFiles[config.name] {
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: project.basePath + configPath)
}
return createObject(
id: config.name,
@@ -70,9 +70,9 @@ public class PBXProjGenerator {
)
}
let configName = spec.options.defaultConfig ?? buildConfigs.first?.object.name ?? ""
let configName = project.options.defaultConfig ?? buildConfigs.first?.object.name ?? ""
let buildConfigList = createObject(
id: spec.name,
id: project.name,
XCConfigurationList(
buildConfigurations: buildConfigs.map { $0.reference },
defaultConfigurationName: configName
@@ -84,26 +84,26 @@ public class PBXProjGenerator {
PBXGroup(
children: [],
sourceTree: .group,
usesTabs: spec.options.usesTabs,
indentWidth: spec.options.indentWidth,
tabWidth: spec.options.tabWidth
usesTabs: project.options.usesTabs,
indentWidth: project.options.indentWidth,
tabWidth: project.options.tabWidth
)
)
let project = createObject(
id: spec.name,
let pbxProject = createObject(
id: project.name,
PBXProject(
name: spec.name,
name: project.name,
buildConfigurationList: buildConfigList.reference,
compatibilityVersion: "Xcode 3.2",
mainGroup: mainGroup.reference,
developmentRegion: spec.options.developmentLanguage ?? "en"
developmentRegion: project.options.developmentLanguage ?? "en"
)
)
proj.rootObject = project.reference
pbxProj.rootObject = pbxProject.reference
for target in spec.targets {
for target in project.targets {
let targetObject: PBXTarget
if target.isLegacy {
@@ -147,7 +147,7 @@ public class PBXProjGenerator {
)
}
try spec.targets.forEach(generateTarget)
try project.targets.forEach(generateTarget)
let productGroup = createObject(
id: "Products",
@@ -205,31 +205,31 @@ public class PBXProjGenerator {
mainGroup.object.children = Array(topLevelGroups)
sortGroups(group: mainGroup)
let projectAttributes: [String: Any] = ["LastUpgradeCheck": spec.xcodeVersion]
.merged(spec.attributes)
let projectAttributes: [String: Any] = ["LastUpgradeCheck": project.xcodeVersion]
.merged(project.attributes)
.merged(generateTargetAttributes() ?? [:])
project.object.knownRegions = sourceGenerator.knownRegions.sorted()
project.object.targets = targetObjects.values.sorted { $0.object.name < $1.object.name }.map { $0.reference }
project.object.attributes = projectAttributes
pbxProject.object.knownRegions = sourceGenerator.knownRegions.sorted()
pbxProject.object.targets = targetObjects.values.sorted { $0.object.name < $1.object.name }.map { $0.reference }
pbxProject.object.attributes = projectAttributes
return proj
return pbxProj
}
func generateTargetAttributes() -> [String: Any]? {
var targetAttributes: [String: [String: Any]] = [:]
let uiTestTargets = proj.objects.nativeTargets.objectReferences.filter { $0.object.productType == .uiTestBundle }
let uiTestTargets = pbxProj.objects.nativeTargets.objectReferences.filter { $0.object.productType == .uiTestBundle }
for uiTestTarget in uiTestTargets {
// look up TEST_TARGET_NAME build setting
func testTargetName(_ target: PBXTarget) -> String? {
guard let configurationList = target.buildConfigurationList else { return nil }
guard let buildConfigurationReferences = self.proj.objects.configurationLists[configurationList]?.buildConfigurations else { return nil }
guard let buildConfigurationReferences = self.pbxProj.objects.configurationLists[configurationList]?.buildConfigurations else { return nil }
let configs = buildConfigurationReferences
.flatMap { ref in self.proj.objects.buildConfigurations[ref] }
.flatMap { ref in self.pbxProj.objects.buildConfigurations[ref] }
return configs
.flatMap { $0.buildSettings["TEST_TARGET_NAME"] as? String }
@@ -237,12 +237,12 @@ public class PBXProjGenerator {
}
guard let name = testTargetName(uiTestTarget.object) else { continue }
guard let target = self.proj.objects.targets(named: name).first else { continue }
guard let target = self.pbxProj.objects.targets(named: name).first else { continue }
targetAttributes[uiTestTarget.reference, default: [:]].merge(["TestTargetID": target.reference])
}
for target in spec.targets {
for target in project.targets {
guard let targetReference = targetObjects[target.name]?.reference else {
continue
}
@@ -251,10 +251,10 @@ public class PBXProjGenerator {
}
func getSingleBuildSetting(_ setting: String) -> String? {
let settings = spec.configs.flatMap {
spec.getCombinedBuildSettings(basePath: spec.basePath, target: target, config: $0)[setting] as? String
let settings = project.configs.flatMap {
project.getCombinedBuildSettings(basePath: project.basePath, target: target, config: $0)[setting] as? String
}
guard settings.count == spec.configs.count,
guard settings.count == project.configs.count,
let firstSetting = settings.first,
settings.filter({ $0 == firstSetting }).count == settings.count else {
return nil
@@ -279,7 +279,7 @@ public class PBXProjGenerator {
// sort children
let children = group.object.children
.flatMap { reference -> ObjectReference<PBXFileElement>? in
guard let fileElement = proj.objects.getFileElement(reference: reference) else {
guard let fileElement = pbxProj.objects.getFileElement(reference: reference) else {
return nil
}
return ObjectReference(reference: reference, object: fileElement)
@@ -290,12 +290,12 @@ public class PBXProjGenerator {
} else {
return child1.object.sortOrder < child2.object.sortOrder
}
}
}
group.object.children = children.map { $0.reference }.filter { $0 != group.reference }
// sort sub groups
let childGroups = group.object.children.flatMap { reference -> ObjectReference<PBXGroup>? in
guard let group = proj.objects.groups[reference] else {
guard let group = pbxProj.objects.groups[reference] else {
return nil
}
return ObjectReference(reference: reference, object: group) }
@@ -312,23 +312,23 @@ public class PBXProjGenerator {
var plistPath: Path?
var searchForPlist = true
let configs: [ObjectReference<XCBuildConfiguration>] = spec.configs.map { config in
var buildSettings = spec.getTargetBuildSettings(target: target, config: config)
let configs: [ObjectReference<XCBuildConfiguration>] = project.configs.map { config in
var buildSettings = project.getTargetBuildSettings(target: target, config: config)
// automatically set INFOPLIST_FILE path
if !spec.targetHasBuildSetting("INFOPLIST_FILE", basePath: spec.basePath, target: target, config: config) {
if !project.targetHasBuildSetting("INFOPLIST_FILE", basePath: project.basePath, target: target, config: config) {
if searchForPlist {
plistPath = getInfoPlist(target.sources)
searchForPlist = false
}
if let plistPath = plistPath {
buildSettings["INFOPLIST_FILE"] = plistPath.byRemovingBase(path: spec.basePath)
buildSettings["INFOPLIST_FILE"] = plistPath.byRemovingBase(path: project.basePath)
}
}
// automatically calculate bundle id
if let bundleIdPrefix = spec.options.bundleIdPrefix,
!spec.targetHasBuildSetting("PRODUCT_BUNDLE_IDENTIFIER", basePath: spec.basePath, target: target, config: config) {
if let bundleIdPrefix = project.options.bundleIdPrefix,
!project.targetHasBuildSetting("PRODUCT_BUNDLE_IDENTIFIER", basePath: project.basePath, target: target, config: config) {
let characterSet = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-.")).inverted
let escapedTargetName = target.name
.replacingOccurrences(of: "_", with: "-")
@@ -339,10 +339,10 @@ public class PBXProjGenerator {
// automatically set test target name
if target.type == .uiTestBundle,
!spec.targetHasBuildSetting("TEST_TARGET_NAME", basePath: spec.basePath, target: target, config: config) {
!project.targetHasBuildSetting("TEST_TARGET_NAME", basePath: project.basePath, target: target, config: config) {
for dependency in target.dependencies {
if dependency.type == .target,
let dependencyTarget = spec.getTarget(dependency.reference),
let dependencyTarget = project.getTarget(dependency.reference),
dependencyTarget.type == .application {
buildSettings["TEST_TARGET_NAME"] = dependencyTarget.name
break
@@ -367,7 +367,7 @@ public class PBXProjGenerator {
var baseConfigurationReference: String?
if let configPath = target.configFiles[config.name] {
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: spec.basePath + configPath)
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: project.basePath + configPath)
}
let buildConfig = XCBuildConfiguration(
name: config.name,
@@ -395,13 +395,13 @@ public class PBXProjGenerator {
switch dependency.type {
case .target:
let dependencyTargetName = dependency.reference
guard let dependencyTarget = spec.getTarget(dependencyTargetName) else { continue }
guard let dependencyTarget = project.getTarget(dependencyTargetName) else { continue }
let dependencyFileReference = targetFileReferences[dependencyTargetName]!
let targetProxy = createObject(
id: target.name,
PBXContainerItemProxy(
containerPortal: proj.rootObject,
containerPortal: pbxProj.rootObject,
remoteGlobalIDString: targetObjects[dependencyTargetName]!.reference,
proxyType: .nativeTarget,
remoteInfo: dependencyTargetName
@@ -454,13 +454,13 @@ public class PBXProjGenerator {
if dependency.implicit {
fileReference = sourceGenerator.getFileReference(
path: Path(dependency.reference),
inPath: spec.basePath,
inPath: project.basePath,
sourceTree: .buildProductsDir
)
} else {
fileReference = sourceGenerator.getFileReference(
path: Path(dependency.reference),
inPath: spec.basePath
inPath: project.basePath
)
}
@@ -528,7 +528,7 @@ public class PBXProjGenerator {
let shellScript: String
switch buildScript.script {
case let .path(path):
shellScript = try (spec.basePath + path).read()
shellScript = try (project.basePath + path).read()
case let .script(script):
shellScript = script
}
@@ -630,7 +630,7 @@ public class PBXProjGenerator {
.map { "$(SRCROOT)/\(carthageBuildPath)/\(target.platform)/\($0)\($0.contains(".") ? "" : ".framework")" }
let outputPaths = carthageFrameworksToEmbed
.map { "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/\($0)\($0.contains(".") ? "" : ".framework")" }
let carthageExecutable = spec.options.carthageExecutablePath ?? "carthage"
let carthageExecutable = project.options.carthageExecutablePath ?? "carthage"
let carthageScript = createObject(
id: "Carthage" + target.name,
PBXShellScriptBuildPhase(
@@ -663,7 +663,7 @@ public class PBXProjGenerator {
func getInfoPlist(_ sources: [TargetSource]) -> Path? {
return sources
.lazy
.map { self.spec.basePath + $0.path }
.map { self.project.basePath + $0.path }
.flatMap { (path) -> Path? in
if path.isFile {
return path.lastComponent == "Info.plist" ? path : nil
@@ -698,7 +698,7 @@ public class PBXProjGenerator {
if visitedTargets[targetName] == true {
return []
}
if let target = spec.getTarget(targetName) {
if let target = project.getTarget(targetName) {
frameworks += getAllCarthageDependencies(target: target, visitedTargets: visitedTargets)
}
default: break
+18 -18
View File
@@ -7,23 +7,23 @@ import Yams
public class ProjectGenerator {
let spec: Project
let project: Project
public init(spec: Project) {
self.spec = spec
public init(project: Project) {
self.project = project
}
var defaultDebugConfig: Config {
return spec.configs.first { $0.type == .debug }!
return project.configs.first { $0.type == .debug }!
}
var defaultReleaseConfig: Config {
return spec.configs.first { $0.type == .release }!
return project.configs.first { $0.type == .release }!
}
public func generateProject() throws -> XcodeProj {
try spec.validate()
let pbxProjGenerator = PBXProjGenerator(spec: spec)
public func generateXcodeProject() throws -> XcodeProj {
try project.validate()
let pbxProjGenerator = PBXProjGenerator(project: project)
let pbxProject = try pbxProjGenerator.generate()
let workspace = try generateWorkspace()
let sharedData = try generateSharedData(pbxProject: pbxProject)
@@ -41,9 +41,9 @@ public class ProjectGenerator {
func getBuildEntry(_ buildTarget: Scheme.BuildTarget) -> XCScheme.BuildAction.Entry {
let targetReference = pbxProject.objects.targets(named: buildTarget.target).first!
let target = spec.getTarget(buildTarget.target)!
let target = project.getTarget(buildTarget.target)!
let buildableReference = XCScheme.BuildableReference(
referencedContainer: "container:\(spec.name).xcodeproj",
referencedContainer: "container:\(project.name).xcodeproj",
blueprintIdentifier: targetReference.reference,
buildableName: target.filename,
blueprintName: buildTarget.target
@@ -136,8 +136,8 @@ public class ProjectGenerator {
return XCScheme(
name: scheme.name,
lastUpgradeVersion: spec.xcodeVersion,
version: spec.schemeVersion,
lastUpgradeVersion: project.xcodeVersion,
version: project.schemeVersion,
buildAction: buildAction,
testAction: testAction,
launchAction: launchAction,
@@ -150,19 +150,19 @@ public class ProjectGenerator {
func generateSharedData(pbxProject: PBXProj) throws -> XCSharedData {
var xcschemes: [XCScheme] = []
for scheme in spec.schemes {
for scheme in project.schemes {
let xcscheme = try generateScheme(scheme, pbxProject: pbxProject)
xcschemes.append(xcscheme)
}
for target in spec.targets {
for target in project.targets {
if let targetScheme = target.scheme {
if targetScheme.configVariants.isEmpty {
let schemeName = target.name
let debugConfig = spec.configs.first { $0.type == .debug }!
let releaseConfig = spec.configs.first { $0.type == .release }!
let debugConfig = project.configs.first { $0.type == .debug }!
let releaseConfig = project.configs.first { $0.type == .release }!
let scheme = Scheme(
name: schemeName,
@@ -178,9 +178,9 @@ public class ProjectGenerator {
let schemeName = "\(target.name) \(configVariant)"
let debugConfig = spec.configs
let debugConfig = project.configs
.first { $0.type == .debug && $0.name.contains(configVariant) }!
let releaseConfig = spec.configs
let releaseConfig = project.configs
.first { $0.type == .release && $0.name.contains(configVariant) }!
let scheme = Scheme(
+23 -23
View File
@@ -17,7 +17,7 @@ class SourceGenerator {
private var groupsByPath: [Path: ObjectReference<PBXGroup>] = [:]
private var variantGroupsByPath: [Path: ObjectReference<PBXVariantGroup>] = [:]
private let spec: Project
private let project: Project
var addObjectClosure: (String, PBXObject) -> String
var targetSourceExcludePaths: Set<Path> = []
var defaultExcludedFiles = [
@@ -28,8 +28,8 @@ class SourceGenerator {
private(set) var knownRegions: Set<String> = []
init(spec: Project, addObjectClosure: @escaping (String, PBXObject) -> String) {
self.spec = spec
init(project: Project, addObjectClosure: @escaping (String, PBXObject) -> String) {
self.project = project
self.addObjectClosure = addObjectClosure
}
@@ -43,12 +43,12 @@ class SourceGenerator {
}
func getAllSourceFiles(sources: [TargetSource]) throws -> [SourceFile] {
return try sources.flatMap { try getSourceFiles(targetSource: $0, path: spec.basePath + $0.path) }
return try sources.flatMap { try getSourceFiles(targetSource: $0, path: project.basePath + $0.path) }
}
// get groups without build files. Use for Project.fileGroups
func getFileGroups(path: String) throws {
let fullPath = spec.basePath + path
let fullPath = project.basePath + path
_ = try getSourceFiles(targetSource: TargetSource(path: path), path: fullPath)
}
@@ -86,7 +86,7 @@ class SourceGenerator {
}
func getContainedFileReference(path: Path) -> String {
let createIntermediateGroups = spec.options.createIntermediateGroups
let createIntermediateGroups = project.options.createIntermediateGroups
let parentPath = path.parent()
let fileReference = getFileReference(path: path, inPath: parentPath)
@@ -122,7 +122,7 @@ class SourceGenerator {
.sorted()
.map { path in
createObject(
id: path.byRemovingBase(path: spec.basePath).string,
id: path.byRemovingBase(path: project.basePath).string,
PBXFileReference(
sourceTree: .group,
lastKnownFileType: "wrapper.xcdatamodel",
@@ -141,7 +141,7 @@ class SourceGenerator {
return versionGroup
} else {
let fileReference = createObject(
id: path.byRemovingBase(path: spec.basePath).string,
id: path.byRemovingBase(path: project.basePath).string,
PBXFileReference(
sourceTree: sourceTree,
name: fileReferenceName,
@@ -182,18 +182,18 @@ class SourceGenerator {
groupReference = cachedGroup
} else {
// lives outside the spec base path
let isOutOfBasePath = !path.absolute().string.contains(spec.basePath.absolute().string)
// lives outside the project base path
let isOutOfBasePath = !path.absolute().string.contains(project.basePath.absolute().string)
// has no valid parent paths
let isRootPath = isOutOfBasePath || path.parent() == spec.basePath
let isRootPath = isOutOfBasePath || path.parent() == project.basePath
// is a top level group in the project
let isTopLevelGroup = (isBaseGroup && !createIntermediateGroups) || isRootPath
let groupName = name ?? path.lastComponent
let groupPath = isTopLevelGroup ?
path.byRemovingBase(path: spec.basePath).string :
path.byRemovingBase(path: project.basePath).string :
path.lastComponent
let group = PBXGroup(
children: children,
@@ -201,7 +201,7 @@ class SourceGenerator {
name: groupName != groupPath ? groupName : nil,
path: groupPath
)
groupReference = createObject(id: path.byRemovingBase(path: spec.basePath).string, group)
groupReference = createObject(id: path.byRemovingBase(path: project.basePath).string, group)
groupsByPath[path] = groupReference
if isTopLevelGroup {
@@ -222,7 +222,7 @@ class SourceGenerator {
sourceTree: .group,
name: path.lastComponent
)
variantGroup = createObject(id: path.byRemovingBase(path: spec.basePath).string, group)
variantGroup = createObject(id: path.byRemovingBase(path: project.basePath).string, group)
variantGroupsByPath[path] = variantGroup
}
return variantGroup
@@ -230,7 +230,7 @@ class SourceGenerator {
/// Collects all the excluded paths within the targetSource
private func getSourceExcludes(targetSource: TargetSource) -> Set<Path> {
let rootSourcePath = spec.basePath + targetSource.path
let rootSourcePath = project.basePath + targetSource.path
return Set(
targetSource.excludes.map {
@@ -316,7 +316,7 @@ class SourceGenerator {
return localisedDirectories.first { $0.lastComponent == "\(languageId).lproj" }
}
return findLocalisedDirectory(by: "Base") ??
findLocalisedDirectory(by: NSLocale.canonicalLanguageIdentifier(from: spec.options.developmentLanguage ?? "en"))
findLocalisedDirectory(by: NSLocale.canonicalLanguageIdentifier(from: project.options.developmentLanguage ?? "en"))
}()
knownRegions.formUnion(localisedDirectories.map { $0.lastComponentWithoutExtension })
@@ -385,10 +385,10 @@ class SourceGenerator {
let group = getGroup(
path: path,
mergingChildren: groupChildren,
createIntermediateGroups: spec.options.createIntermediateGroups,
createIntermediateGroups: project.options.createIntermediateGroups,
isBaseGroup: isBaseGroup
)
if spec.options.createIntermediateGroups {
if project.options.createIntermediateGroups {
createIntermediaGroups(for: group.reference, at: path)
}
@@ -403,7 +403,7 @@ class SourceGenerator {
targetSourceExcludePaths = getSourceExcludes(targetSource: targetSource)
let type = targetSource.type ?? (path.isFile || path.extension != nil ? .file : .group)
let createIntermediateGroups = spec.options.createIntermediateGroups
let createIntermediateGroups = project.options.createIntermediateGroups
var sourceFiles: [SourceFile] = []
let sourceReference: String
@@ -413,13 +413,13 @@ class SourceGenerator {
let folderPath = Path(targetSource.path)
let fileReference = getFileReference(
path: folderPath,
inPath: spec.basePath,
inPath: project.basePath,
name: targetSource.name ?? folderPath.lastComponent,
sourceTree: .sourceRoot,
lastKnownFileType: "folder"
)
if !createIntermediateGroups || path.parent() == spec.basePath {
if !createIntermediateGroups || path.parent() == project.basePath {
rootGroups.insert(fileReference)
}
@@ -440,7 +440,7 @@ class SourceGenerator {
let sourceFile = generateSourceFile(targetSource: targetSource, path: path)
if parentPath == spec.basePath {
if parentPath == project.basePath {
sourcePath = path
sourceReference = fileReference
rootGroups.insert(fileReference)
@@ -473,7 +473,7 @@ class SourceGenerator {
private func createIntermediaGroups(for groupReference: String, at path: Path) {
let parentPath = path.parent()
guard parentPath != spec.basePath && path.string.contains(spec.basePath.string) else {
guard parentPath != project.basePath && path.string.contains(project.basePath.string) else {
// we've reached the top or are out of the root directory
return
}
Binary file not shown.
File renamed without changes.
+12 -12
View File
@@ -6,14 +6,14 @@ import xcproj
let fixturePath = Path(#file).parent().parent() + "Fixtures"
func generate(specPath: Path, projectPath: Path) throws -> XcodeProj {
let spec = try Project(path: specPath)
let generator = ProjectGenerator(spec: spec)
let project = try generator.generateProject()
func generateXcodeProject(specPath: Path, projectPath: Path) throws -> XcodeProj {
let project = try Project(path: specPath)
let generator = ProjectGenerator(project: project)
let xcodeProject = try generator.generateXcodeProject()
let oldProject = try XcodeProj(path: projectPath)
let pbxProjPath = projectPath + XcodeProj.pbxprojPath(projectPath)
let oldProjectString: String = try pbxProjPath.read()
try project.write(path: projectPath, override: true)
try xcodeProject.write(path: projectPath, override: true)
let newProjectString: String = try pbxProjPath.read()
let newProject = try XcodeProj(path: projectPath)
@@ -32,21 +32,21 @@ func generate(specPath: Path, projectPath: Path) throws -> XcodeProj {
func fixtureTests() {
describe("Test Project") {
var project: XcodeProj?
var xcodeProject: XcodeProj?
$0.it("generates") {
project = try generate(specPath: fixturePath + "TestProject/spec.yml", projectPath: fixturePath + "TestProject/Project.xcodeproj")
xcodeProject = try generateXcodeProject(specPath: fixturePath + "TestProject/project.yml", projectPath: fixturePath + "TestProject/Project.xcodeproj")
}
$0.it("generates variant group") {
guard let project = project else { return }
guard let xcodeProject = xcodeProject else { return }
func getFileReferences(_ path: String) -> [ObjectReference<PBXFileReference>] {
return project.pbxproj.objects.fileReferences.objectReferences.filter { $0.object.path == path }
return xcodeProject.pbxproj.objects.fileReferences.objectReferences.filter { $0.object.path == path }
}
func getVariableGroups(_ name: String?) -> [PBXVariantGroup] {
return project.pbxproj.objects.variantGroups.referenceValues.filter { $0.name == name }
return xcodeProject.pbxproj.objects.variantGroups.referenceValues.filter { $0.name == name }
}
let resourceName = "LocalizedStoryboard.storyboard"
@@ -69,9 +69,9 @@ func fixtureTests() {
}
$0.it("generates scheme execution actions") {
guard let project = project else { return }
guard let xcodeProject = xcodeProject else { return }
let frameworkScheme = project.sharedData?.schemes.first { $0.name == "Framework" }
let frameworkScheme = xcodeProject.sharedData?.schemes.first { $0.name == "Framework" }
try expect(frameworkScheme?.buildAction?.preActions.first?.scriptText) == "echo Starting Framework Build"
try expect(frameworkScheme?.buildAction?.preActions.first?.title) == "Run Script"
try expect(frameworkScheme?.buildAction?.preActions.first?.environmentBuildable?.blueprintName) == "Framework_iOS"
+161 -161
View File
@@ -7,15 +7,15 @@ import Yams
func projectGeneratorTests() {
func getProject(_ spec: Project) throws -> XcodeProj {
let generator = ProjectGenerator(spec: spec)
return try generator.generateProject()
func getXcodeProject(_ project: Project) throws -> XcodeProj {
let generator = ProjectGenerator(project: project)
return try generator.generateXcodeProject()
}
func getPbxProj(_ spec: Project) throws -> PBXProj {
let project = try getProject(spec).pbxproj
try project.validate()
return project
func getPbxProj(_ project: Project) throws -> PBXProj {
let xcodeProject = try getXcodeProject(project).pbxproj
try xcodeProject.validate()
return xcodeProject
}
describe("Project Generator") {
@@ -49,13 +49,13 @@ func projectGeneratorTests() {
$0.it("generates bundle id") {
let options = SpecOptions(bundleIdPrefix: "com.test")
let spec = Project(basePath: "", name: "test", targets: [framework], options: options)
let project = try getProject(spec)
guard let target = project.pbxproj.objects.nativeTargets.first?.value,
let project = Project(basePath: "", name: "test", targets: [framework], options: options)
let pbxProj = try getPbxProj(project)
guard let target = pbxProj.objects.nativeTargets.first?.value,
let buildConfigList = target.buildConfigurationList,
let buildConfigs = project.pbxproj.objects.configurationLists.getReference(buildConfigList),
let buildConfigs = pbxProj.objects.configurationLists.getReference(buildConfigList),
let buildConfigReference = buildConfigs.buildConfigurations.first,
let buildConfig = project.pbxproj.objects.buildConfigurations.getReference(buildConfigReference) else {
let buildConfig = pbxProj.objects.buildConfigurations.getReference(buildConfigReference) else {
throw failure("Build Config not found")
}
try expect(buildConfig.buildSettings["PRODUCT_BUNDLE_IDENTIFIER"] as? String) == "com.test.MyFramework"
@@ -63,17 +63,17 @@ func projectGeneratorTests() {
$0.it("clears setting presets") {
let options = SpecOptions(settingPresets: .none)
let spec = Project(basePath: "", name: "test", targets: [framework], options: options)
let project = try getProject(spec)
let allSettings = project.pbxproj.objects.buildConfigurations.referenceValues.reduce([:]) { $0.merged($1.buildSettings) }.keys.sorted()
let project = Project(basePath: "", name: "test", targets: [framework], options: options)
let pbxProj = try getPbxProj(project)
let allSettings = pbxProj.objects.buildConfigurations.referenceValues.reduce([:]) { $0.merged($1.buildSettings) }.keys.sorted()
try expect(allSettings) == ["SETTING_2"]
}
$0.it("generates development language") {
let options = SpecOptions(developmentLanguage: "de")
let spec = Project(basePath: "", name: "test", options: options)
let project = try getProject(spec)
guard let pbxProject = project.pbxproj.objects.projects.first?.value else {
let project = Project(basePath: "", name: "test", options: options)
let pbxProj = try getPbxProj(project)
guard let pbxProject = pbxProj.objects.projects.first?.value else {
throw failure("Could't find PBXProject")
}
try expect(pbxProject.developmentRegion) == "de"
@@ -99,8 +99,8 @@ func projectGeneratorTests() {
$0.it("uses the default configuration name") {
let options = SpecOptions(defaultConfig: "Bconfig")
let spec = Project(basePath: "", name: "test", configs: [Config(name: "Aconfig"), Config(name: "Bconfig")], targets: [framework], options: options)
let pbxProject = try getPbxProj(spec)
let project = Project(basePath: "", name: "test", configs: [Config(name: "Aconfig"), Config(name: "Bconfig")], targets: [framework], options: options)
let pbxProject = try getPbxProj(project)
guard let projectConfigListReference = pbxProject.objects.projects.values.first?.buildConfigurationList,
let defaultConfigurationName = pbxProject.objects.configurationLists[projectConfigListReference]?.defaultConfigurationName
@@ -115,47 +115,47 @@ func projectGeneratorTests() {
$0.describe("Config") {
$0.it("generates config defaults") {
let spec = Project(basePath: "", name: "test")
let project = try getProject(spec)
let configs = project.pbxproj.objects.buildConfigurations.referenceValues
let project = Project(basePath: "", name: "test")
let pbxProj = try getPbxProj(project)
let configs = pbxProj.objects.buildConfigurations.referenceValues
try expect(configs.count) == 2
try expect(configs).contains(name: "Debug")
try expect(configs).contains(name: "Release")
}
$0.it("generates configs") {
let spec = Project(
let project = Project(
basePath: "",
name: "test",
configs: [Config(name: "config1"), Config(name: "config2")]
)
let project = try getProject(spec)
let configs = project.pbxproj.objects.buildConfigurations.referenceValues
let pbxProj = try getPbxProj(project)
let configs = pbxProj.objects.buildConfigurations.referenceValues
try expect(configs.count) == 2
try expect(configs).contains(name: "config1")
try expect(configs).contains(name: "config2")
}
$0.it("clears config settings when missing type") {
let spec = Project(
let project = Project(
basePath: "",
name: "test",
configs: [Config(name: "config")]
)
let project = try getProject(spec)
guard let config = project.pbxproj.objects.buildConfigurations.first?.value else {
let pbxProj = try getPbxProj(project)
guard let config = pbxProj.objects.buildConfigurations.first?.value else {
throw failure("configuration not found")
}
try expect(config.buildSettings.isEmpty).to.beTrue()
}
$0.it("merges settings") {
let spec = try Project(path: fixturePath + "settings_test.yml")
guard let config = spec.getConfig("config1") else { throw failure("Couldn't find config1") }
let debugProjectSettings = spec.getProjectBuildSettings(config: config)
let project = try Project(path: fixturePath + "settings_test.yml")
guard let config = project.getConfig("config1") else { throw failure("Couldn't find config1") }
let debugProjectSettings = project.getProjectBuildSettings(config: config)
guard let target = spec.getTarget("Target") else { throw failure("Couldn't find Target") }
let targetDebugSettings = spec.getTargetBuildSettings(target: target, config: config)
guard let target = project.getTarget("Target") else { throw failure("Couldn't find Target") }
let targetDebugSettings = project.getTargetBuildSettings(target: target, config: config)
var buildSettings = BuildSettings()
buildSettings += SettingsPresetFile.base.getBuildSettings()
@@ -178,7 +178,7 @@ func projectGeneratorTests() {
}
$0.it("applies partial config settings") {
let spec = Project(
let project = Project(
basePath: "",
name: "test",
configs: [
@@ -188,7 +188,7 @@ func projectGeneratorTests() {
settings: Settings(configSettings: ["staging": ["SETTING1": "VALUE1"], "debug": ["SETTING2": "VALUE2"]])
)
var buildSettings = spec.getProjectBuildSettings(config: spec.configs.first!)
var buildSettings = project.getProjectBuildSettings(config: project.configs.first!)
try expect(buildSettings["SETTING1"] as? String) == "VALUE1"
try expect(buildSettings["SETTING2"] as? String) == "VALUE2"
}
@@ -196,10 +196,10 @@ func projectGeneratorTests() {
$0.describe("Targets") {
let spec = Project(basePath: "", name: "test", targets: targets)
let project = Project(basePath: "", name: "test", targets: targets)
$0.it("generates targets") {
let pbxProject = try getPbxProj(spec)
let pbxProject = try getPbxProj(project)
let nativeTargets = pbxProject.objects.nativeTargets.referenceValues
try expect(nativeTargets.count) == 3
try expect(nativeTargets.contains { $0.name == application.name }).beTrue()
@@ -214,8 +214,8 @@ func projectGeneratorTests() {
var testTargetWithAttributes = uiTest
testTargetWithAttributes.settings.buildSettings["CODE_SIGN_STYLE"] = "Manual"
var spec = Project(basePath: "", name: "test", targets: [appTargetWithAttributes, framework, testTargetWithAttributes])
let pbxProject = try getPbxProj(spec)
var project = Project(basePath: "", name: "test", targets: [appTargetWithAttributes, framework, testTargetWithAttributes])
let pbxProject = try getPbxProj(project)
guard let targetAttributes = pbxProject.objects.projects.referenceValues.first?.attributes["TargetAttributes"] as? [String: [String: Any]] else {
throw failure("Couldn't find Project TargetAttributes")
@@ -237,9 +237,9 @@ func projectGeneratorTests() {
$0.it("generates platform version") {
let target = Target(name: "Target", type: .application, platform: .watchOS, deploymentTarget: "2.0")
let spec = Project(basePath: "", name: "", targets: [target], options: .init(deploymentTarget: DeploymentTarget(iOS: "10.0", watchOS: "3.0")))
let project = Project(basePath: "", name: "", targets: [target], options: .init(deploymentTarget: DeploymentTarget(iOS: "10.0", watchOS: "3.0")))
let pbxProject = try getPbxProj(spec)
let pbxProject = try getPbxProj(project)
guard let projectConfigListReference = pbxProject.objects.projects.values.first?.buildConfigurationList,
let projectConfigReference = pbxProject.objects.configurationLists[projectConfigListReference]?.buildConfigurations.first,
@@ -265,7 +265,7 @@ func projectGeneratorTests() {
}
$0.it("generates dependencies") {
let pbxProject = try getPbxProj(spec)
let pbxProject = try getPbxProj(project)
let nativeTargets = pbxProject.objects.nativeTargets.objectReferences
let dependencies = pbxProject.objects.targetDependencies.objectReferences
@@ -275,7 +275,7 @@ func projectGeneratorTests() {
}
$0.it("generates run scripts") {
var scriptSpec = spec
var scriptSpec = project
scriptSpec.targets[0].prebuildScripts = [BuildScript(script: .script("script1"))]
scriptSpec.targets[0].postbuildScripts = [BuildScript(script: .script("script2"))]
let pbxProject = try getPbxProj(scriptSpec)
@@ -310,13 +310,13 @@ func projectGeneratorTests() {
platform: .iOS,
dependencies: [Dependency(type: .target, reference: "target1")]
)
let spec = Project(
let project = Project(
basePath: "",
name: "test",
targets: [target1, target2]
)
_ = try getPbxProj(spec)
_ = try getPbxProj(project)
}
}
@@ -329,18 +329,18 @@ func projectGeneratorTests() {
name: "MyScheme",
build: Scheme.Build(targets: [buildTarget], preActions: [preAction])
)
let spec = Project(
let project = Project(
basePath: "",
name: "test",
targets: [application, framework],
schemes: [scheme]
)
let project = try getProject(spec)
guard let target = project.pbxproj.objects.nativeTargets.objectReferences
let xcodeProject = try getXcodeProject(project)
guard let target = xcodeProject.pbxproj.objects.nativeTargets.objectReferences
.first(where: { $0.object.name == application.name }) else {
throw failure("Target not found")
}
guard let xcscheme = project.sharedData?.schemes.first else {
guard let xcscheme = xcodeProject.sharedData?.schemes.first else {
throw failure("Scheme not found")
}
try expect(scheme.name) == "MyScheme"
@@ -388,20 +388,20 @@ func projectGeneratorTests() {
test: Scheme.Test(config: "Debug"),
profile: Scheme.Profile(config: "Debug")
)
let spec = Project(
let project = Project(
basePath: "",
name: "test",
targets: [application, framework],
schemes: [scheme]
)
let project = try getProject(spec)
let xcodeProject = try getXcodeProject(project)
guard let target = project.pbxproj.objects.nativeTargets.objectReferences
guard let target = xcodeProject.pbxproj.objects.nativeTargets.objectReferences
.first(where: { $0.object.name == application.name }) else {
throw failure("Target not found")
}
guard let xcscheme = project.sharedData?.schemes.first else {
guard let xcscheme = xcodeProject.sharedData?.schemes.first else {
throw failure("Scheme not found")
}
@@ -421,16 +421,16 @@ func projectGeneratorTests() {
Config(name: "Production Release", type: .release),
]
let spec = Project(basePath: "", name: "test", configs: configs, targets: [target, framework])
let project = try getProject(spec)
let project = Project(basePath: "", name: "test", configs: configs, targets: [target, framework])
let xcodeProject = try getXcodeProject(project)
try expect(project.sharedData?.schemes.count) == 2
try expect(xcodeProject.sharedData?.schemes.count) == 2
guard let nativeTarget = project.pbxproj.objects.nativeTargets.objectReferences
guard let nativeTarget = xcodeProject.pbxproj.objects.nativeTargets.objectReferences
.first(where: { $0.object.name == application.name }) else {
throw failure("Target not found")
}
guard let xcscheme = project.sharedData?.schemes
guard let xcscheme = xcodeProject.sharedData?.schemes
.first(where: { $0.name == "\(target.name) Test" }) else {
throw failure("Scheme not found")
}
@@ -451,12 +451,12 @@ func projectGeneratorTests() {
var target = application
target.scheme = TargetScheme(environmentVariables: variables)
let spec = Project(basePath: "", name: "test", targets: [target, framework])
let project = try getProject(spec)
let project = Project(basePath: "", name: "test", targets: [target, framework])
let xcodeProject = try getXcodeProject(project)
try expect(project.sharedData?.schemes.count) == 1
try expect(xcodeProject.sharedData?.schemes.count) == 1
guard let xcscheme = project.sharedData?.schemes.first else {
guard let xcscheme = xcodeProject.sharedData?.schemes.first else {
throw failure("Scheme not found")
}
@@ -472,12 +472,12 @@ func projectGeneratorTests() {
postActions: [.init(name: "Run2", script: "post", settingsTarget: "MyApp")]
)
let spec = ProjectSpec(basePath: "", name: "test", targets: [target, framework])
let project = try getProject(spec)
let project = Project(basePath: "", name: "test", targets: [target, framework])
let xcodeProject = try getXcodeProject(project)
try expect(project.sharedData?.schemes.count) == 1
try expect(xcodeProject.sharedData?.schemes.count) == 1
guard let xcscheme = project.sharedData?.schemes.first else {
guard let xcscheme = xcodeProject.sharedData?.schemes.first else {
throw failure("Scheme not found")
}
@@ -548,11 +548,11 @@ func projectGeneratorTests() {
try createDirectories(directories)
let target = Target(name: "Test", type: .application, platform: .iOS, sources: ["Sources"])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = try getPbxProj(spec)
try project.expectFile(paths: ["Sources", "A", "a.swift"], buildPhase: .sources)
try project.expectFile(paths: ["Sources", "A", "B", "b.swift"], buildPhase: .sources)
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["Sources", "A", "a.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["Sources", "A", "B", "b.swift"], buildPhase: .sources)
}
$0.it("generates core data models") {
@@ -564,13 +564,13 @@ func projectGeneratorTests() {
try createDirectories(directories)
let target = Target(name: "Test", type: .application, platform: .iOS, sources: ["Sources"])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = try getPbxProj(spec)
guard let fileReference = project.objects.fileReferences.first(where: { $0.value.nameOrPath == "model.xcdatamodel" }) else {
let pbxProj = try getPbxProj(project)
guard let fileReference = pbxProj.objects.fileReferences.first(where: { $0.value.nameOrPath == "model.xcdatamodel" }) else {
throw failure("Couldn't find model file reference")
}
guard let versionGroup = project.objects.versionGroups.values.first else {
guard let versionGroup = pbxProj.objects.versionGroups.values.first else {
throw failure("Couldn't find version group")
}
try expect(versionGroup.currentVersion) == fileReference.key
@@ -592,17 +592,17 @@ func projectGeneratorTests() {
try createDirectories(directories)
let target = Target(name: "Test", type: .application, platform: .iOS, sources: ["Sources"])
let spec = Project(
let project = Project(
basePath: directoryPath,
name: "Test",
targets: [target],
fileGroups: ["Sources"]
)
let project = try getPbxProj(spec)
try project.expectFile(paths: ["Sources", "a.swift"], buildPhase: .sources)
try project.expectFile(paths: ["Sources", "a", "a.swift"], buildPhase: .sources)
try project.expectFile(paths: ["Sources", "a", "a", "a.swift"], buildPhase: .sources)
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["Sources", "a.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["Sources", "a", "a.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["Sources", "a", "a", "a.swift"], buildPhase: .sources)
}
$0.it("renames sources") {
@@ -618,11 +618,11 @@ func projectGeneratorTests() {
TargetSource(path: "Sources", name: "NewSource"),
TargetSource(path: "OtherSource/b.swift", name: "c.swift"),
])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = try getPbxProj(spec)
try project.expectFile(paths: ["Sources", "a.swift"], names: ["NewSource", "a.swift"], buildPhase: .sources)
try project.expectFile(paths: ["OtherSource", "b.swift"], names: ["OtherSource", "c.swift"], buildPhase: .sources)
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["Sources", "a.swift"], names: ["NewSource", "a.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["OtherSource", "b.swift"], names: ["OtherSource", "c.swift"], buildPhase: .sources)
}
$0.it("excludes sources") {
@@ -681,28 +681,28 @@ func projectGeneratorTests() {
]
let target = Target(name: "Test", type: .application, platform: .iOS, sources: [TargetSource(path: "Sources", excludes: excludes)])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = try getPbxProj(spec)
try project.expectFile(paths: ["Sources", "A", "a.swift"])
try project.expectFile(paths: ["Sources", "D", "d.h"])
try project.expectFile(paths: ["Sources", "D", "d.m"])
try project.expectFile(paths: ["Sources", "E", "e.jpg"])
try project.expectFile(paths: ["Sources", "E", "e.m"])
try project.expectFile(paths: ["Sources", "E", "e.h"])
try project.expectFile(paths: ["Sources", "types", "a.swift"])
try project.expectFile(paths: ["Sources", "numbers", "file1.a"])
try project.expectFile(paths: ["Sources", "numbers", "file4.a"])
try project.expectFileMissing(paths: ["Sources", "B", "b.swift"])
try project.expectFileMissing(paths: ["Sources", "E", "F", "f.swift"])
try project.expectFileMissing(paths: ["Sources", "G", "H", "h.swift"])
try project.expectFileMissing(paths: ["Sources", "types", "a.h"])
try project.expectFileMissing(paths: ["Sources", "types", "a.x"])
try project.expectFileMissing(paths: ["Sources", "numbers", "file2.a"])
try project.expectFileMissing(paths: ["Sources", "numbers", "file3.a"])
try project.expectFileMissing(paths: ["Sources", "partial", "file_part"])
try project.expectFileMissing(paths: ["Sources", "a.ignored"])
try project.expectFileMissing(paths: ["Sources", "ignore.file"])
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["Sources", "A", "a.swift"])
try pbxProj.expectFile(paths: ["Sources", "D", "d.h"])
try pbxProj.expectFile(paths: ["Sources", "D", "d.m"])
try pbxProj.expectFile(paths: ["Sources", "E", "e.jpg"])
try pbxProj.expectFile(paths: ["Sources", "E", "e.m"])
try pbxProj.expectFile(paths: ["Sources", "E", "e.h"])
try pbxProj.expectFile(paths: ["Sources", "types", "a.swift"])
try pbxProj.expectFile(paths: ["Sources", "numbers", "file1.a"])
try pbxProj.expectFile(paths: ["Sources", "numbers", "file4.a"])
try pbxProj.expectFileMissing(paths: ["Sources", "B", "b.swift"])
try pbxProj.expectFileMissing(paths: ["Sources", "E", "F", "f.swift"])
try pbxProj.expectFileMissing(paths: ["Sources", "G", "H", "h.swift"])
try pbxProj.expectFileMissing(paths: ["Sources", "types", "a.h"])
try pbxProj.expectFileMissing(paths: ["Sources", "types", "a.x"])
try pbxProj.expectFileMissing(paths: ["Sources", "numbers", "file2.a"])
try pbxProj.expectFileMissing(paths: ["Sources", "numbers", "file3.a"])
try pbxProj.expectFileMissing(paths: ["Sources", "partial", "file_part"])
try pbxProj.expectFileMissing(paths: ["Sources", "a.ignored"])
try pbxProj.expectFileMissing(paths: ["Sources", "ignore.file"])
}
$0.it("generates file sources") {
@@ -723,13 +723,13 @@ func projectGeneratorTests() {
"Sources/A/Assets.xcassets",
"Sources/A/B/c.jpg",
])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = try getPbxProj(spec)
try project.expectFile(paths: ["Sources/A", "a.swift"], names: ["A", "a.swift"], buildPhase: .sources)
try project.expectFile(paths: ["Sources/A/B", "b.swift"], names: ["B", "b.swift"], buildPhase: .sources)
try project.expectFile(paths: ["Sources/A/B", "c.jpg"], names: ["B", "c.jpg"], buildPhase: .resources)
try project.expectFile(paths: ["Sources/A", "Assets.xcassets"], names: ["A", "Assets.xcassets"], buildPhase: .resources)
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["Sources/A", "a.swift"], names: ["A", "a.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["Sources/A/B", "b.swift"], names: ["B", "b.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["Sources/A/B", "c.jpg"], names: ["B", "c.jpg"], buildPhase: .resources)
try pbxProj.expectFile(paths: ["Sources/A", "Assets.xcassets"], names: ["A", "Assets.xcassets"], buildPhase: .resources)
}
$0.it("generates shared sources") {
@@ -745,9 +745,9 @@ func projectGeneratorTests() {
let target1 = Target(name: "Test1", type: .framework, platform: .iOS, sources: ["Sources"])
let target2 = Target(name: "Test2", type: .framework, platform: .tvOS, sources: ["Sources"])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target1, target2])
let project = Project(basePath: directoryPath, name: "Test", targets: [target1, target2])
_ = try getPbxProj(spec)
_ = try getPbxProj(project)
// TODO: check there are build files for both targets
}
@@ -772,12 +772,12 @@ func projectGeneratorTests() {
"../OtherDirectory/C/D/e.swift",
])
let options = SpecOptions(createIntermediateGroups: true)
let spec = Project(basePath: directoryPath, name: "Test", targets: [target], options: options)
let project = Project(basePath: directoryPath, name: "Test", targets: [target], options: options)
let project = try getPbxProj(spec)
try project.expectFile(paths: ["Sources", "A", "b.swift"], buildPhase: .sources)
try project.expectFile(paths: ["Sources", "F", "G", "h.swift"], buildPhase: .sources)
try project.expectFile(paths: [(outOfRootPath + "C/D").string, "e.swift"], names: ["D", "e.swift"], buildPhase: .sources)
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["Sources", "A", "b.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["Sources", "F", "G", "h.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: [(outOfRootPath + "C/D").string, "e.swift"], names: ["D", "e.swift"], buildPhase: .sources)
}
$0.it("generates folder references") {
@@ -792,11 +792,11 @@ func projectGeneratorTests() {
let target = Target(name: "Test", type: .application, platform: .iOS, sources: [
TargetSource(path: "Sources/A", type: .folder),
])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = try getPbxProj(spec)
try project.expectFile(paths: ["Sources/A"], names: ["A"], buildPhase: .resources)
try project.expectFileMissing(paths: ["Sources", "A", "a.swift"])
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["Sources/A"], names: ["A"], buildPhase: .resources)
try pbxProj.expectFileMissing(paths: ["Sources", "A", "a.swift"])
}
$0.it("adds files to correct build phase") {
@@ -842,44 +842,44 @@ func projectGeneratorTests() {
TargetSource(path: "B", buildPhase: .none),
TargetSource(path: "C", buildPhase: nil),
])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = try getPbxProj(spec)
try project.expectFile(paths: ["A", "file.swift"], buildPhase: .resources)
try project.expectFile(paths: ["A", "file.xcassets"], buildPhase: .resources)
try project.expectFile(paths: ["A", "file.h"], buildPhase: .resources)
try project.expectFile(paths: ["A", "Info.plist"], buildPhase: .none)
try project.expectFile(paths: ["A", "file.xcconfig"], buildPhase: .resources)
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["A", "file.swift"], buildPhase: .resources)
try pbxProj.expectFile(paths: ["A", "file.xcassets"], buildPhase: .resources)
try pbxProj.expectFile(paths: ["A", "file.h"], buildPhase: .resources)
try pbxProj.expectFile(paths: ["A", "Info.plist"], buildPhase: .none)
try pbxProj.expectFile(paths: ["A", "file.xcconfig"], buildPhase: .resources)
try project.expectFile(paths: ["B", "file.swift"], buildPhase: .none)
try project.expectFile(paths: ["B", "file.xcassets"], buildPhase: .none)
try project.expectFile(paths: ["B", "file.h"], buildPhase: .none)
try project.expectFile(paths: ["B", "Info.plist"], buildPhase: .none)
try project.expectFile(paths: ["B", "file.xcconfig"], buildPhase: .none)
try pbxProj.expectFile(paths: ["B", "file.swift"], buildPhase: .none)
try pbxProj.expectFile(paths: ["B", "file.xcassets"], buildPhase: .none)
try pbxProj.expectFile(paths: ["B", "file.h"], buildPhase: .none)
try pbxProj.expectFile(paths: ["B", "Info.plist"], buildPhase: .none)
try pbxProj.expectFile(paths: ["B", "file.xcconfig"], buildPhase: .none)
try project.expectFile(paths: ["C", "file.swift"], buildPhase: .sources)
try project.expectFile(paths: ["C", "file.m"], buildPhase: .sources)
try project.expectFile(paths: ["C", "file.mm"], buildPhase: .sources)
try project.expectFile(paths: ["C", "file.cpp"], buildPhase: .sources)
try project.expectFile(paths: ["C", "file.c"], buildPhase: .sources)
try project.expectFile(paths: ["C", "file.S"], buildPhase: .sources)
try project.expectFile(paths: ["C", "file.h"], buildPhase: .headers)
try project.expectFile(paths: ["C", "file.hh"], buildPhase: .headers)
try project.expectFile(paths: ["C", "file.hpp"], buildPhase: .headers)
try project.expectFile(paths: ["C", "file.ipp"], buildPhase: .headers)
try project.expectFile(paths: ["C", "file.tpp"], buildPhase: .headers)
try project.expectFile(paths: ["C", "file.hxx"], buildPhase: .headers)
try project.expectFile(paths: ["C", "file.def"], buildPhase: .headers)
try project.expectFile(paths: ["C", "file.xcconfig"], buildPhase: .none)
try project.expectFile(paths: ["C", "file.entitlements"], buildPhase: .none)
try project.expectFile(paths: ["C", "file.gpx"], buildPhase: .none)
try project.expectFile(paths: ["C", "file.apns"], buildPhase: .none)
try project.expectFile(paths: ["C", "file.xcconfig"], buildPhase: .none)
try project.expectFile(paths: ["C", "file.xcconfig"], buildPhase: .none)
try project.expectFile(paths: ["C", "file.xcconfig"], buildPhase: .none)
try project.expectFile(paths: ["C", "file.xcassets"], buildPhase: .resources)
try project.expectFile(paths: ["C", "file.123"], buildPhase: .resources)
try project.expectFile(paths: ["C", "Info.plist"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.swift"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["C", "file.m"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["C", "file.mm"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["C", "file.cpp"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["C", "file.c"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["C", "file.S"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["C", "file.h"], buildPhase: .headers)
try pbxProj.expectFile(paths: ["C", "file.hh"], buildPhase: .headers)
try pbxProj.expectFile(paths: ["C", "file.hpp"], buildPhase: .headers)
try pbxProj.expectFile(paths: ["C", "file.ipp"], buildPhase: .headers)
try pbxProj.expectFile(paths: ["C", "file.tpp"], buildPhase: .headers)
try pbxProj.expectFile(paths: ["C", "file.hxx"], buildPhase: .headers)
try pbxProj.expectFile(paths: ["C", "file.def"], buildPhase: .headers)
try pbxProj.expectFile(paths: ["C", "file.xcconfig"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.entitlements"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.gpx"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.apns"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.xcconfig"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.xcconfig"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.xcconfig"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.xcassets"], buildPhase: .resources)
try pbxProj.expectFile(paths: ["C", "file.123"], buildPhase: .resources)
try pbxProj.expectFile(paths: ["C", "Info.plist"], buildPhase: .none)
}
$0.it("duplicate TargetSource is included once in sources build phase") {
@@ -894,12 +894,12 @@ func projectGeneratorTests() {
"Sources/A/a.swift",
"Sources/A/a.swift",
])
let spec = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
let project = try getPbxProj(spec)
try project.expectFile(paths: ["Sources/A", "a.swift"], names: ["A", "a.swift"], buildPhase: .sources)
let pbxProj = try getPbxProj(project)
try pbxProj.expectFile(paths: ["Sources/A", "a.swift"], names: ["A", "a.swift"], buildPhase: .sources)
let sourcesBuildPhase = project.objects.buildPhases
let sourcesBuildPhase = pbxProj.objects.buildPhases
.first(where: { $0.1.buildPhase == BuildPhase.sources })!
.value
+44 -44
View File
@@ -27,9 +27,9 @@ func projectSpecTests() {
settings: Settings(buildSettings: ["SETTING_2": "VALUE"])
)
func expectValidationError(_ spec: Project, _ expectedError: SpecValidationError.ValidationError) throws {
func expectValidationError(_ project: Project, _ expectedError: SpecValidationError.ValidationError) throws {
do {
try spec.validate()
try project.validate()
} catch let error as SpecValidationError {
if !error.errors
.contains(where: { $0.description == expectedError.description }) {
@@ -80,41 +80,41 @@ func projectSpecTests() {
$0.describe("Validation") {
let baseSpec = Project(basePath: "", name: "", configs: [Config(name: "invalid")])
let baseProject = Project(basePath: "", name: "", configs: [Config(name: "invalid")])
let invalidSettings = Settings(
configSettings: ["invalidConfig": [:]],
groups: ["invalidSettingGroup"]
)
$0.it("fails with invalid project") {
var spec = baseSpec
spec.settings = invalidSettings
spec.configFiles = ["invalidConfig": "invalidConfigFile"]
spec.fileGroups = ["invalidFileGroup"]
spec.settingGroups = ["settingGroup1": Settings(
var project = baseProject
project.settings = invalidSettings
project.configFiles = ["invalidConfig": "invalidConfigFile"]
project.fileGroups = ["invalidFileGroup"]
project.settingGroups = ["settingGroup1": Settings(
configSettings: ["invalidSettingGroupConfig": [:]],
groups: ["invalidSettingGroupSettingGroup"]
)]
try expectValidationError(spec, .invalidConfigFileConfig("invalidConfig"))
try expectValidationError(spec, .invalidBuildSettingConfig("invalidConfig"))
try expectValidationError(spec, .invalidConfigFile(configFile: "invalidConfigFile", config: "invalidConfig"))
try expectValidationError(spec, .invalidSettingsGroup("invalidSettingGroup"))
try expectValidationError(spec, .invalidFileGroup("invalidFileGroup"))
try expectValidationError(spec, .invalidSettingsGroup("invalidSettingGroupSettingGroup"))
try expectValidationError(spec, .invalidBuildSettingConfig("invalidSettingGroupConfig"))
try expectValidationError(project, .invalidConfigFileConfig("invalidConfig"))
try expectValidationError(project, .invalidBuildSettingConfig("invalidConfig"))
try expectValidationError(project, .invalidConfigFile(configFile: "invalidConfigFile", config: "invalidConfig"))
try expectValidationError(project, .invalidSettingsGroup("invalidSettingGroup"))
try expectValidationError(project, .invalidFileGroup("invalidFileGroup"))
try expectValidationError(project, .invalidSettingsGroup("invalidSettingGroupSettingGroup"))
try expectValidationError(project, .invalidBuildSettingConfig("invalidSettingGroupConfig"))
}
$0.it("allows non-existent configurations") {
var spec = baseSpec
spec.options = SpecOptions(disabledValidations: [.missingConfigs])
var project = baseProject
project.options = SpecOptions(disabledValidations: [.missingConfigs])
let configPath = fixturePath + "test.xcconfig"
spec.configFiles = ["missingConfiguration": configPath.string]
try spec.validate()
project.configFiles = ["missingConfiguration": configPath.string]
try project.validate()
}
$0.it("fails with invalid target") {
var spec = baseSpec
spec.targets = [Target(
var project = baseProject
project.targets = [Target(
name: "target1",
type: .application,
platform: .iOS,
@@ -127,51 +127,51 @@ func projectSpecTests() {
scheme: TargetScheme(testTargets: ["invalidTarget"])
)]
try expectValidationError(spec, .invalidTargetDependency(target: "target1", dependency: "invalidDependency"))
try expectValidationError(spec, .invalidTargetConfigFile(target: "target1", configFile: "invalidConfigFile", config: "invalidConfig"))
try expectValidationError(spec, .invalidTargetSchemeTest(target: "target1", testTarget: "invalidTarget"))
try expectValidationError(spec, .invalidTargetSource(target: "target1", source: "invalidSource"))
try expectValidationError(spec, .invalidBuildSettingConfig("invalidConfig"))
try expectValidationError(spec, .invalidSettingsGroup("invalidSettingGroup"))
try expectValidationError(spec, .invalidBuildScriptPath(target: "target1", name: "prebuildScript1", path: "invalidPrebuildScript"))
try expectValidationError(spec, .invalidBuildScriptPath(target: "target1", name: nil, path: "invalidPostbuildScript"))
try expectValidationError(project, .invalidTargetDependency(target: "target1", dependency: "invalidDependency"))
try expectValidationError(project, .invalidTargetConfigFile(target: "target1", configFile: "invalidConfigFile", config: "invalidConfig"))
try expectValidationError(project, .invalidTargetSchemeTest(target: "target1", testTarget: "invalidTarget"))
try expectValidationError(project, .invalidTargetSource(target: "target1", source: "invalidSource"))
try expectValidationError(project, .invalidBuildSettingConfig("invalidConfig"))
try expectValidationError(project, .invalidSettingsGroup("invalidSettingGroup"))
try expectValidationError(project, .invalidBuildScriptPath(target: "target1", name: "prebuildScript1", path: "invalidPrebuildScript"))
try expectValidationError(project, .invalidBuildScriptPath(target: "target1", name: nil, path: "invalidPostbuildScript"))
try expectValidationError(spec, .missingConfigForTargetScheme(target: "target1", configType: .debug))
try expectValidationError(spec, .missingConfigForTargetScheme(target: "target1", configType: .release))
try expectValidationError(project, .missingConfigForTargetScheme(target: "target1", configType: .debug))
try expectValidationError(project, .missingConfigForTargetScheme(target: "target1", configType: .release))
spec.targets[0].scheme?.configVariants = ["invalidVariant"]
try expectValidationError(spec, .invalidTargetSchemeConfigVariant(target: "target1", configVariant: "invalidVariant", configType: .debug))
project.targets[0].scheme?.configVariants = ["invalidVariant"]
try expectValidationError(project, .invalidTargetSchemeConfigVariant(target: "target1", configVariant: "invalidVariant", configType: .debug))
}
$0.it("fails with invalid scheme") {
var spec = baseSpec
spec.schemes = [Scheme(
var project = baseProject
project.schemes = [Scheme(
name: "scheme1",
build: .init(targets: [.init(target: "invalidTarget")]),
run: .init(config: "debugInvalid"),
archive: .init(config: "releaseInvalid")
)]
try expectValidationError(spec, .invalidSchemeTarget(scheme: "scheme1", target: "invalidTarget"))
try expectValidationError(spec, .invalidSchemeConfig(scheme: "scheme1", config: "debugInvalid"))
try expectValidationError(spec, .invalidSchemeConfig(scheme: "scheme1", config: "releaseInvalid"))
try expectValidationError(project, .invalidSchemeTarget(scheme: "scheme1", target: "invalidTarget"))
try expectValidationError(project, .invalidSchemeConfig(scheme: "scheme1", config: "debugInvalid"))
try expectValidationError(project, .invalidSchemeConfig(scheme: "scheme1", config: "releaseInvalid"))
}
$0.it("allows missing optional file") {
var spec = baseSpec
spec.targets = [Target(
var project = baseProject
project.targets = [Target(
name: "target1",
type: .application,
platform: .iOS,
sources: [.init(path: "generated.swift", optional: true)]
)]
try spec.validate()
try project.validate()
}
$0.it("validates missing default configurations") {
var spec = baseSpec
spec.options = SpecOptions(defaultConfig: "foo")
try expectValidationError(spec, .missingDefaultConfig(configName: "foo"))
var project = baseProject
project.options = SpecOptions(defaultConfig: "foo")
try expectValidationError(project, .missingDefaultConfig(configName: "foo"))
}
}
}
+29 -29
View File
@@ -5,20 +5,20 @@ import Spectre
import XcodeGenKit
import xcproj
func specLoadingTests() {
func projectLoadingTests() {
@discardableResult
func getProjectSpec(_ spec: [String: Any]) throws -> Project {
var specDictionary: [String: Any] = ["name": "test"]
for (key, value) in spec {
specDictionary[key] = value
func getProjectSpec(_ project: [String: Any]) throws -> Project {
var projectDictionary: [String: Any] = ["name": "test"]
for (key, value) in project {
projectDictionary[key] = value
}
return try Project(basePath: "", jsonDictionary: specDictionary)
return try Project(basePath: "", jsonDictionary: projectDictionary)
}
func expectSpecError(_ spec: [String: Any], _ expectedError: SpecParsingError) throws {
func expectSpecError(_ project: [String: Any], _ expectedError: SpecParsingError) throws {
try expectError(expectedError) {
try getProjectSpec(spec)
try getProjectSpec(project)
}
}
@@ -34,15 +34,15 @@ func specLoadingTests() {
describe("Spec Loader") {
$0.it("merges includes") {
let path = fixturePath + "include_test.yml"
let spec = try Project(path: path)
let project = try Project(path: path)
try expect(spec.name) == "NewName"
try expect(spec.settingGroups) == [
try expect(project.name) == "NewName"
try expect(project.settingGroups) == [
"test": Settings(dictionary: ["MY_SETTING1": "NEW VALUE", "MY_SETTING2": "VALUE2", "MY_SETTING3": "VALUE3"]),
"new": Settings(dictionary: ["MY_SETTING": "VALUE"]),
"toReplace": Settings(dictionary: ["MY_SETTING2": "VALUE2"]),
]
try expect(spec.targets) == [
try expect(project.targets) == [
Target(name: "IncludedTargetNew", type: .application, platform: .tvOS, sources: ["NewSource"]),
Target(name: "NewTarget", type: .application, platform: .iOS),
]
@@ -88,15 +88,15 @@ func specLoadingTests() {
describe("Spec Loader JSON") {
$0.it("merges includes") {
let path = fixturePath + "include_test.json"
let spec = try Project(path: path)
let project = try Project(path: path)
try expect(spec.name) == "NewName"
try expect(spec.settingGroups) == [
try expect(project.name) == "NewName"
try expect(project.settingGroups) == [
"test": Settings(dictionary: ["MY_SETTING1": "NEW VALUE", "MY_SETTING2": "VALUE2", "MY_SETTING3": "VALUE3"]),
"new": Settings(dictionary: ["MY_SETTING": "VALUE"]),
"toReplace": Settings(dictionary: ["MY_SETTING2": "VALUE2"]),
]
try expect(spec.targets) == [
try expect(project.targets) == [
Target(name: "IncludedTargetNew", type: .application, platform: .tvOS, sources: ["NewSource"]),
Target(name: "NewTarget", type: .application, platform: .iOS),
]
@@ -178,7 +178,7 @@ func specLoadingTests() {
"settings": ["SETTING": "value_$platform"],
]
let spec = try getProjectSpec(["targets": ["Framework": targetDictionary]])
let project = try getProjectSpec(["targets": ["Framework": targetDictionary]])
var target_iOS = Target(name: "Framework_iOS", type: .framework, platform: .iOS)
var target_tvOS = Target(name: "Framework_tvOS", type: .framework, platform: .tvOS)
@@ -187,8 +187,8 @@ func specLoadingTests() {
target_iOS.settings = ["PRODUCT_NAME": "Framework", "SETTING": "value_iOS"]
target_tvOS.settings = ["PRODUCT_NAME": "Framework", "SETTING": "value_tvOS"]
try expect(spec.targets.count) == 2
try expect(spec.targets) == [target_iOS, target_tvOS]
try expect(project.targets.count) == 2
try expect(project.targets) == [target_iOS, target_tvOS]
}
$0.it("parses target schemes") {
@@ -320,7 +320,7 @@ func specLoadingTests() {
}
$0.it("parses settings") {
let spec = try Project(path: fixturePath + "settings_test.yml")
let project = try Project(path: fixturePath + "settings_test.yml")
let buildSettings: BuildSettings = ["SETTING": "value"]
let configSettings: [String: Settings] = ["config1": Settings(buildSettings: ["SETTING1": "value"])]
let groups = ["preset1"]
@@ -334,15 +334,15 @@ func specLoadingTests() {
let preset7 = Settings(buildSettings: buildSettings, configSettings: ["config1": Settings(buildSettings: buildSettings, groups: groups)])
let preset8 = Settings(buildSettings: [:], configSettings: ["config1": Settings(configSettings: configSettings)])
try expect(spec.settingGroups.count) == 8
try expect(spec.settingGroups["preset1"]) == preset1
try expect(spec.settingGroups["preset2"]) == preset2
try expect(spec.settingGroups["preset3"]) == preset3
try expect(spec.settingGroups["preset4"]) == preset4
try expect(spec.settingGroups["preset5"]) == preset5
try expect(spec.settingGroups["preset6"]) == preset6
try expect(spec.settingGroups["preset7"]) == preset7
try expect(spec.settingGroups["preset8"]) == preset8
try expect(project.settingGroups.count) == 8
try expect(project.settingGroups["preset1"]) == preset1
try expect(project.settingGroups["preset2"]) == preset2
try expect(project.settingGroups["preset3"]) == preset3
try expect(project.settingGroups["preset4"]) == preset4
try expect(project.settingGroups["preset5"]) == preset5
try expect(project.settingGroups["preset6"]) == preset6
try expect(project.settingGroups["preset7"]) == preset7
try expect(project.settingGroups["preset8"]) == preset8
}
$0.it("parses run scripts") {
+1 -1
View File
@@ -5,7 +5,7 @@ class XCodeGenKitTests: XCTestCase {
func testXcodeGenKit() {
projectGeneratorTests()
specLoadingTests()
projectLoadingTests()
fixtureTests()
projectSpecTests()
}