diff --git a/Fixtures/TestProject/spec.xcodeproj/project.pbxproj b/Fixtures/TestProject/spec.xcodeproj/project.pbxproj index adaae506..ff3742c7 100644 --- a/Fixtures/TestProject/spec.xcodeproj/project.pbxproj +++ b/Fixtures/TestProject/spec.xcodeproj/project.pbxproj @@ -7,145 +7,215 @@ objects = { /* Begin PBXBuildFile section */ - OBJECT_10 /* MyFramework.h in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_6 /* MyFramework.h */; }; - OBJECT_23 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_17 /* AppDelegate.swift */; }; - OBJECT_24 /* Assets.xcassets in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_18 /* Assets.xcassets */; }; - OBJECT_25 /* Base.lproj in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_19 /* Base.lproj */; }; - OBJECT_26 /* Info.plist in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_20 /* Info.plist */; }; - OBJECT_27 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_21 /* ViewController.swift */; }; - OBJECT_8 /* FrameworkFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_4 /* FrameworkFile.swift */; }; - OBJECT_9 /* Info.plist in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_5 /* Info.plist */; }; + OBJECT_10 = {isa = PBXBuildFile; fileRef = OBJECT_9 /* TestProject.app */; }; + OBJECT_15 /* FrameworkFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_11 /* FrameworkFile.swift */; }; + OBJECT_16 /* Info.plist in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_12 /* Info.plist */; }; + OBJECT_17 /* MyFramework.h in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_13 /* MyFramework.h */; }; + OBJECT_30 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_24 /* AppDelegate.swift */; }; + OBJECT_31 /* Assets.xcassets in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_25 /* Assets.xcassets */; }; + OBJECT_32 /* Base.lproj in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_26 /* Base.lproj */; }; + OBJECT_33 /* Info.plist in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_27 /* Info.plist */; }; + OBJECT_34 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJECT_28 /* ViewController.swift */; }; + OBJECT_7 /* MyFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = OBJECT_6 /* MyFramework.framework */; }; + OBJECT_7 /* MyFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = OBJECT_6 /* MyFramework.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + OBJECT_38 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = OBJECT_1 /* Project object */; + proxyType = 1; + remoteGlobalIDString = OBJECT_5; + remoteInfo = MyFramework; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + OBJECT_23 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + OBJECT_42 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + OBJECT_7 /* MyFramework.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ - OBJECT_15 /* MyFramework */ = {isa = PBXFileReference; includeInIndex = 0; path = MyFramework; sourceTree = BUILT_PRODUCTS_DIR; }; - OBJECT_17 /* AppDelegate.swift */ = {isa = PBXFileReference; path = AppDelegate.swift; sourceTree = ""; }; - OBJECT_18 /* Assets.xcassets */ = {isa = PBXFileReference; path = Assets.xcassets; sourceTree = ""; }; - OBJECT_19 /* Base.lproj */ = {isa = PBXFileReference; path = Base.lproj; sourceTree = ""; }; - OBJECT_20 /* Info.plist */ = {isa = PBXFileReference; path = Info.plist; sourceTree = ""; }; - OBJECT_21 /* ViewController.swift */ = {isa = PBXFileReference; path = ViewController.swift; sourceTree = ""; }; - OBJECT_32 /* TestProject */ = {isa = PBXFileReference; includeInIndex = 0; path = TestProject; sourceTree = BUILT_PRODUCTS_DIR; }; - OBJECT_4 /* FrameworkFile.swift */ = {isa = PBXFileReference; path = FrameworkFile.swift; sourceTree = ""; }; - OBJECT_5 /* Info.plist */ = {isa = PBXFileReference; path = Info.plist; sourceTree = ""; }; - OBJECT_6 /* MyFramework.h */ = {isa = PBXFileReference; path = MyFramework.h; sourceTree = ""; }; + OBJECT_11 /* FrameworkFile.swift */ = {isa = PBXFileReference; path = FrameworkFile.swift; sourceTree = ""; }; + OBJECT_12 /* Info.plist */ = {isa = PBXFileReference; path = Info.plist; sourceTree = ""; }; + OBJECT_13 /* MyFramework.h */ = {isa = PBXFileReference; path = MyFramework.h; sourceTree = ""; }; + OBJECT_24 /* AppDelegate.swift */ = {isa = PBXFileReference; path = AppDelegate.swift; sourceTree = ""; }; + OBJECT_25 /* Assets.xcassets */ = {isa = PBXFileReference; path = Assets.xcassets; sourceTree = ""; }; + OBJECT_26 /* Base.lproj */ = {isa = PBXFileReference; path = Base.lproj; sourceTree = ""; }; + OBJECT_27 /* Info.plist */ = {isa = PBXFileReference; path = Info.plist; sourceTree = ""; }; + OBJECT_28 /* ViewController.swift */ = {isa = PBXFileReference; path = ViewController.swift; sourceTree = ""; }; + OBJECT_6 /* MyFramework.framework */ = {isa = PBXFileReference; explicitFileType = framework; includeInIndex = 0; path = MyFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + OBJECT_9 /* TestProject.app */ = {isa = PBXFileReference; explicitFileType = app; includeInIndex = 0; path = TestProject.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFrameworksBuildPhase section */ + OBJECT_22 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + OBJECT_41 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + OBJECT_7, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + /* Begin PBXGroup section */ - OBJECT_22 /* TestProject */ = { + OBJECT_14 /* MyFramework */ = { isa = PBXGroup; children = ( - OBJECT_20 /* Info.plist */, - OBJECT_19 /* Base.lproj */, - OBJECT_21 /* ViewController.swift */, - OBJECT_17 /* AppDelegate.swift */, - OBJECT_18 /* Assets.xcassets */, - ); - name = TestProject; - path = TestProject; - sourceTree = ""; - }; - OBJECT_34 = { - isa = PBXGroup; - children = ( - OBJECT_7 /* MyFramework */, - OBJECT_22 /* TestProject */, - ); - sourceTree = ""; - }; - OBJECT_7 /* MyFramework */ = { - isa = PBXGroup; - children = ( - OBJECT_5 /* Info.plist */, - OBJECT_6 /* MyFramework.h */, - OBJECT_4 /* FrameworkFile.swift */, + OBJECT_13 /* MyFramework.h */, + OBJECT_11 /* FrameworkFile.swift */, + OBJECT_12 /* Info.plist */, ); name = MyFramework; path = MyFramework; sourceTree = ""; }; + OBJECT_29 /* TestProject */ = { + isa = PBXGroup; + children = ( + OBJECT_25 /* Assets.xcassets */, + OBJECT_28 /* ViewController.swift */, + OBJECT_24 /* AppDelegate.swift */, + OBJECT_26 /* Base.lproj */, + OBJECT_27 /* Info.plist */, + ); + name = TestProject; + path = TestProject; + sourceTree = ""; + }; + OBJECT_43 /* Products */ = { + isa = PBXGroup; + children = ( + OBJECT_6 /* MyFramework.framework */, + OBJECT_9 /* TestProject.app */, + ); + name = Products; + sourceTree = ""; + }; + OBJECT_44 = { + isa = PBXGroup; + children = ( + OBJECT_14 /* MyFramework */, + OBJECT_29 /* TestProject */, + OBJECT_43 /* Products */, + ); + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - OBJECT_16 /* MyFramework */ = { + OBJECT_5 /* MyFramework */ = { isa = PBXNativeTarget; - buildConfigurationList = OBJECT_14 /* Build configuration list for PBXNativeTarget "MyFramework" */; + buildConfigurationList = OBJECT_20 /* Build configuration list for PBXNativeTarget "MyFramework" */; buildPhases = ( - OBJECT_11 /* Sources */, + OBJECT_21 /* Sources */, + OBJECT_22 /* Frameworks */, + OBJECT_23 /* Copy Files */, ); buildRules = ( ); dependencies = ( ); name = MyFramework; - productReference = OBJECT_15; + productReference = OBJECT_6; productType = "com.apple.product-type.framework"; }; - OBJECT_33 /* TestProject */ = { + OBJECT_8 /* TestProject */ = { isa = PBXNativeTarget; - buildConfigurationList = OBJECT_31 /* Build configuration list for PBXNativeTarget "TestProject" */; + buildConfigurationList = OBJECT_37 /* Build configuration list for PBXNativeTarget "TestProject" */; buildPhases = ( - OBJECT_28 /* Sources */, + OBJECT_40 /* Sources */, + OBJECT_41 /* Frameworks */, + OBJECT_42 /* Copy Files */, ); buildRules = ( ); dependencies = ( + OBJECT_39 /* PBXTargetDependency */, ); name = TestProject; - productReference = OBJECT_32; + productReference = OBJECT_9; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - OBJECT_35 /* Project object */ = { + OBJECT_1 /* Project object */ = { isa = PBXProject; attributes = { }; - buildConfigurationList = OBJECT_3 /* Build configuration list for PBXProject "spec" */; + buildConfigurationList = OBJECT_4 /* Build configuration list for PBXProject "spec" */; compatibilityVersion = "Xcode 3.2"; knownRegions = ( ); - mainGroup = OBJECT_34; + mainGroup = OBJECT_44; targets = ( - OBJECT_16 /* MyFramework */, - OBJECT_33 /* TestProject */, + OBJECT_5 /* MyFramework */, + OBJECT_8 /* TestProject */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ - OBJECT_11 /* Sources */ = { + OBJECT_21 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - OBJECT_8 /* FrameworkFile.swift in Sources */, - OBJECT_9 /* Info.plist in Sources */, - OBJECT_10 /* MyFramework.h in Sources */, + OBJECT_15 /* FrameworkFile.swift in Sources */, + OBJECT_17 /* MyFramework.h in Sources */, + OBJECT_16 /* Info.plist in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - OBJECT_28 /* Sources */ = { + OBJECT_40 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - OBJECT_25 /* Base.lproj in Sources */, - OBJECT_24 /* Assets.xcassets in Sources */, - OBJECT_23 /* AppDelegate.swift in Sources */, - OBJECT_26 /* Info.plist in Sources */, - OBJECT_27 /* ViewController.swift in Sources */, + OBJECT_33 /* Info.plist in Sources */, + OBJECT_31 /* Assets.xcassets in Sources */, + OBJECT_34 /* ViewController.swift in Sources */, + OBJECT_30 /* AppDelegate.swift in Sources */, + OBJECT_32 /* Base.lproj in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin XCBuildConfiguration section */ - OBJECT_1 /* debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - }; - name = debug; +/* Begin PBXTargetDependency section */ + OBJECT_39 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = OBJECT_5 /* MyFramework */; + targetProxy = OBJECT_38 /* PBXContainerItemProxy */; }; - OBJECT_12 /* debug */ = { +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + OBJECT_18 /* debug */ = { isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -203,7 +273,7 @@ }; name = debug; }; - OBJECT_13 /* release */ = { + OBJECT_19 /* release */ = { isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -256,13 +326,19 @@ }; name = release; }; - OBJECT_2 /* release */ = { + OBJECT_2 /* debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = debug; + }; + OBJECT_3 /* release */ = { isa = XCBuildConfiguration; buildSettings = { }; name = release; }; - OBJECT_29 /* debug */ = { + OBJECT_35 /* debug */ = { isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -317,7 +393,7 @@ }; name = debug; }; - OBJECT_30 /* release */ = { + OBJECT_36 /* release */ = { isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -369,34 +445,34 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - OBJECT_14 /* Build configuration list for PBXNativeTarget "MyFramework" */ = { + OBJECT_20 /* Build configuration list for PBXNativeTarget "MyFramework" */ = { isa = XCConfigurationList; buildConfigurations = ( - OBJECT_12 /* debug */, - OBJECT_13 /* release */, + OBJECT_19 /* release */, + OBJECT_18 /* debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = ""; }; - OBJECT_3 /* Build configuration list for PBXProject "spec" */ = { + OBJECT_37 /* Build configuration list for PBXNativeTarget "TestProject" */ = { isa = XCConfigurationList; buildConfigurations = ( - OBJECT_1 /* debug */, - OBJECT_2 /* release */, + OBJECT_35 /* debug */, + OBJECT_36 /* release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = ""; + }; + OBJECT_4 /* Build configuration list for PBXProject "spec" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + OBJECT_3 /* release */, + OBJECT_2 /* debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = debug; }; - OBJECT_31 /* Build configuration list for PBXNativeTarget "TestProject" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJECT_29 /* debug */, - OBJECT_30 /* release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = ""; - }; /* End XCConfigurationList section */ }; - rootObject = OBJECT_35 /* Project object */; + rootObject = OBJECT_1 /* Project object */; } diff --git a/Fixtures/TestProject/spec.yml b/Fixtures/TestProject/spec.yml index a480c91f..9f2da192 100644 --- a/Fixtures/TestProject/spec.yml +++ b/Fixtures/TestProject/spec.yml @@ -17,6 +17,9 @@ targets: - TestProject buildSettings: INFOPLIST_FILE: TestProject/Info.plist + dependencies: + - name: MyFramework + type: target MyFramework: type: framework platform: iOS diff --git a/Sources/XcodeGen/main.swift b/Sources/XcodeGen/main.swift index 9fb08773..8bd9b58e 100644 --- a/Sources/XcodeGen/main.swift +++ b/Sources/XcodeGen/main.swift @@ -26,6 +26,7 @@ func generate(spec: String) { spec = specLintingResults.spec if !specLintingResults.errors.isEmpty { print("Spec errors: \n\t- \(specLintingResults.errors.map{$0.description}.joined(separator: "\n\t- "))") + return } if !specLintingResults.appliedFixits.isEmpty { print("Applied spec fixits:\n\t- \(specLintingResults.appliedFixits.map{$0.description}.joined(separator: "\n\t- "))") diff --git a/Sources/XcodeGenKit/ProjectGenerator.swift b/Sources/XcodeGenKit/ProjectGenerator.swift index 2d628137..6c41a363 100644 --- a/Sources/XcodeGenKit/ProjectGenerator.swift +++ b/Sources/XcodeGenKit/ProjectGenerator.swift @@ -21,7 +21,13 @@ public class ProjectGenerator { var groups: [PBXGroup] = [] var fileReferences: [PBXFileReference] = [] var groupsByPath: [String: String] = [:] + + var targetNativeReferences: [String: String] = [:] + var targetBuildFileReferences: [String: String] = [:] + var targetFileReferences: [String: String] = [:] + var ids = 0 + var projectReference: String var buildSettingGroups: [String: BuildSettings] = [:] @@ -57,6 +63,8 @@ public class ProjectGenerator { public init(spec: Spec, path: Path) { self.spec = spec self.path = path + projectReference = "" + projectReference = id() } func id() -> String { @@ -85,7 +93,18 @@ public class ProjectGenerator { var topLevelGroups: [PBXGroup] = [] - var targets: [String] = [] + for target in spec.targets { + targetNativeReferences[target.name] = id() + + let fileReference = PBXFileReference(reference: id(), sourceTree: .buildProductsDir, explicitFileType: target.type.fileExtension, path: target.filename, includeInIndex: 0) + objects.append(.pbxFileReference(fileReference)) + targetFileReferences[target.name] = fileReference.reference + + let buildFile = PBXBuildFile(reference: id(), fileRef: fileReference.reference) + objects.append(.pbxBuildFile(buildFile)) + targetBuildFileReferences[target.name] = buildFile.reference + } + for target in spec.targets { let source = spec.path.parent() + target.sources.first! @@ -98,9 +117,6 @@ public class ProjectGenerator { let buildFiles = fileReferences.map { PBXBuildFile(reference: id(), fileRef: $0.reference) } objects += buildFiles.map { .pbxBuildFile($0) } - let buildPhase = PBXSourcesBuildPhase(reference: id(), files: buildFiles.referenceSet) - let buildPhases = [buildPhase] - objects += buildPhases.map { .pbxSourcesBuildPhase($0) } let configs: [XCBuildConfiguration] = try spec.configs.map { config in let buildSettings = try getTargetBuildSettings(config: config, target: target) @@ -110,23 +126,71 @@ public class ProjectGenerator { let buildConfigList = XCConfigurationList(reference: id(), buildConfigurations: configs.referenceSet, defaultConfigurationName: "") objects.append(.xcConfigurationList(buildConfigList)) + var dependancies: [String] = [] + var frameworkFiles: [String] = [] + var copyFiles: [String] = [] + for dependancy in target.dependencies { + switch dependancy.type { + case .target: + let targetProxy = PBXContainerItemProxy(reference: id(), containerPortal: projectReference, remoteGlobalIDString: targetNativeReferences[dependancy.name]!, proxyType: .nativeTarget, remoteInfo: dependancy.name) + let targetDependancy = PBXTargetDependency(reference: id(), target: targetNativeReferences[dependancy.name]!, targetProxy: targetProxy.reference ) - let productReference = PBXFileReference(reference: id(), sourceTree: .buildProductsDir, path: target.name, includeInIndex: 0) - objects.append(.pbxFileReference(productReference)) + objects.append(.pbxContainerItemProxy(targetProxy)) + objects.append(.pbxTargetDependency(targetDependancy)) + dependancies.append(targetDependancy.reference) - let nativeTarget = PBXNativeTarget(reference: id(), buildConfigurationList: buildConfigList.reference, buildPhases: buildPhases.referenceList, buildRules: [], dependencies: [], name: target.name, productReference: productReference.reference, productType: target.type) + let dependencyBuildFile = targetBuildFileReferences[dependancy.name]! + frameworkFiles.append(dependencyBuildFile) + copyFiles.append(dependencyBuildFile) + case .system: + //TODO: handle system frameworks + break + } + } + + let fileReference = targetFileReferences[target.name]! + if target.type == .framework { + let buildFile = PBXBuildFile(reference: targetBuildFileReferences[target.name]!, fileRef: fileReference) + objects.append(.pbxBuildFile(buildFile)) + } + + var buildPhases: [String] = [] + + let buildPhase = PBXSourcesBuildPhase(reference: id(), files: buildFiles.referenceSet) + objects.append(.pbxSourcesBuildPhase(buildPhase)) + buildPhases.append(buildPhase.reference) + + let frameworkPhase = PBXFrameworksBuildPhase(reference: id(), files: Set(frameworkFiles), runOnlyForDeploymentPostprocessing: 0) + objects.append(.pbxFrameworksBuildPhase(frameworkPhase)) + buildPhases.append(frameworkPhase.reference) + + let copyPhase = PBXCopyFilesBuildPhase(reference: id(), dstPath: "", dstSubfolderSpec: .frameworks, files: Set(copyFiles)) + objects.append(.pbxCopyFilesBuildPhase(copyPhase)) + buildPhases.append(copyPhase.reference) + + let nativeTarget = PBXNativeTarget( + reference: targetNativeReferences[target.name]!, + buildConfigurationList: buildConfigList.reference, + buildPhases: buildPhases, + buildRules: [], + dependencies: dependancies, + name: target.name, + productReference: fileReference, + productType: target.type) objects.append(.pbxNativeTarget(nativeTarget)) - - targets.append(nativeTarget.reference) } + let productGroup = PBXGroup(reference: id(), children: Set(targetFileReferences.values), sourceTree: .group, name: "Products") + objects.append(.pbxGroup(productGroup)) + topLevelGroups.append(productGroup) + let mainGroup = PBXGroup(reference: id(), children: topLevelGroups.referenceSet, sourceTree: .group) objects.append(.pbxGroup(mainGroup)) - let pbxProjectRoot = PBXProject(reference: id(), buildConfigurationList: buildConfigList.reference, compatibilityVersion: "Xcode 3.2", mainGroup: mainGroup.reference, targets: targets) + let pbxProjectRoot = PBXProject(reference: projectReference, buildConfigurationList: buildConfigList.reference, compatibilityVersion: "Xcode 3.2", mainGroup: mainGroup.reference, targets: Array(targetNativeReferences.values)) objects.append(.pbxProject(pbxProjectRoot)) - return PBXProj(path: path + "project.pbxproj", name: path.lastComponentWithoutExtension, archiveVersion: 1, objectVersion: 46, rootObject: pbxProjectRoot.reference, objects: objects) + return PBXProj(path: path + "project.pbxproj", name: path.lastComponentWithoutExtension, archiveVersion: 1, objectVersion: 46, rootObject: projectReference, objects: objects) } func getTargetBuildSettings(config: Config, target: Target) throws -> BuildSettings { diff --git a/Sources/XcodeGenKit/Spec/Target.swift b/Sources/XcodeGenKit/Spec/Target.swift index f5d59d41..44438153 100644 --- a/Sources/XcodeGenKit/Spec/Target.swift +++ b/Sources/XcodeGenKit/Spec/Target.swift @@ -17,10 +17,18 @@ public struct Target { public var localizedSource: String? public var sources: [String] public var sourceExludes: [String] - public var dependancies: [Dependancy] + public var dependencies: [Dependency] public var prebuildScripts: [String] public var postbuildScripts: [String] public var buildSettings: TargetBuildSettings? + + public var filename: String { + var name = self.name + if let fileExtension = type.fileExtension { + name += ".\(fileExtension)" + } + return name + } } extension Target: NamedJSONDictionaryConvertible { @@ -41,13 +49,13 @@ extension Target: NamedJSONDictionaryConvertible { buildSettings = jsonDictionary.json(atKeyPath: "buildSettings") sources = jsonDictionary.json(atKeyPath: "sources") ?? [] sourceExludes = jsonDictionary.json(atKeyPath: "sourceExludes") ?? [] - dependancies = jsonDictionary.json(atKeyPath: "dependancies") ?? [] + dependencies = jsonDictionary.json(atKeyPath: "dependencies") ?? [] prebuildScripts = jsonDictionary.json(atKeyPath: "prebuildScripts") ?? [] postbuildScripts = jsonDictionary.json(atKeyPath: "postbuildScripts") ?? [] } } -public struct Dependancy { +public struct Dependency { public var name: String public var type: DependancyType @@ -58,7 +66,7 @@ public struct Dependancy { } } -extension Dependancy: JSONObjectConvertible { +extension Dependency: JSONObjectConvertible { public init(jsonDictionary: JSONDictionary) throws { name = try jsonDictionary.json(atKeyPath: "name") diff --git a/Sources/XcodeGenKit/SpecLinter.swift b/Sources/XcodeGenKit/SpecLinter.swift index 4b496221..432f2119 100644 --- a/Sources/XcodeGenKit/SpecLinter.swift +++ b/Sources/XcodeGenKit/SpecLinter.swift @@ -20,16 +20,24 @@ public struct SpecLinter { fixits.append(.createdConfigs) } + for target in spec.targets { + for dependency in target.dependencies { + if dependency.type == .target && !spec.targets.contains(where: { $0.name == dependency.name}) { + errors.append(.invalidTargetDependency(dependency.name)) + } + } + } + return (spec, fixits, errors) } } public enum SpecLinterError: CustomStringConvertible { - case invalidDependancy(String) + case invalidTargetDependency(String) public var description: String { switch self { - case let .invalidDependancy(dependancy): return "Invalid dependancy \(dependancy)" + case let .invalidTargetDependency(dependency): return "Invalid target dependency \(dependency)" } } }