From ebde9de15159f78bf32ef0a04ec842f3d6c36a54 Mon Sep 17 00:00:00 2001 From: Yonas Kolb Date: Tue, 27 Mar 2018 14:21:15 +1100 Subject: [PATCH] Add target.attributes --- Docs/ProjectSpec.md | 1 + Sources/ProjectSpec/Target.swift | 9 +++- Sources/XcodeGenKit/PBXProjGenerator.swift | 44 ++++++++++--------- .../Project.xcodeproj/project.pbxproj | 3 ++ Tests/Fixtures/TestProject/spec.yml | 2 + .../ProjectGeneratorTests.swift | 9 +++- 6 files changed, 44 insertions(+), 24 deletions(-) diff --git a/Docs/ProjectSpec.md b/Docs/ProjectSpec.md index 5c8ca877..2d592917 100644 --- a/Docs/ProjectSpec.md +++ b/Docs/ProjectSpec.md @@ -160,6 +160,7 @@ Settings are merged in the following order: groups, base, configs. - [ ] **dependencies**: **[[Dependency](#dependency)]** - Dependencies for the target - [ ] **scheme**: **[Target Scheme](#target-scheme)** - Generated scheme with tests or config variants - [ ] **legacy**: **[Legacy Target](#legacy-target)** - When present, opt-in to make an Xcode "External Build System" legacy target instead. +- [ ] **attributes**: **[String: Any]** - This sets values in the project `TargetAttributes`. It is merged with `attributes` from the project and anything automatically added by XcodeGen, with any duplicate values being override by values specified here. This is for advanced use only. ### Product Type This will provide default build settings for a certain product type. It can be any of the following: diff --git a/Sources/ProjectSpec/Target.swift b/Sources/ProjectSpec/Target.swift index 233710af..8272021c 100644 --- a/Sources/ProjectSpec/Target.swift +++ b/Sources/ProjectSpec/Target.swift @@ -43,6 +43,7 @@ public struct Target { public var scheme: TargetScheme? public var legacy: LegacyTarget? public var deploymentTarget: Version? + public var attributes: [String: Any] internal var productName: String? public var isLegacy: Bool { @@ -69,7 +70,8 @@ public struct Target { prebuildScripts: [BuildScript] = [], postbuildScripts: [BuildScript] = [], scheme: TargetScheme? = nil, - legacy: LegacyTarget? = nil + legacy: LegacyTarget? = nil, + attributes: [String: Any] = [:] ) { self.name = name self.type = type @@ -83,6 +85,7 @@ public struct Target { self.postbuildScripts = postbuildScripts self.scheme = scheme self.legacy = legacy + self.attributes = attributes } } @@ -175,7 +178,8 @@ extension Target: Equatable { lhs.prebuildScripts == rhs.prebuildScripts && lhs.postbuildScripts == rhs.postbuildScripts && lhs.scheme == rhs.scheme && - lhs.legacy == rhs.legacy + lhs.legacy == rhs.legacy && + NSDictionary(dictionary: lhs.attributes).isEqual(to: rhs.attributes) } } @@ -282,5 +286,6 @@ extension Target: NamedJSONDictionaryConvertible { postbuildScripts = jsonDictionary.json(atKeyPath: "postbuildScripts") ?? [] scheme = jsonDictionary.json(atKeyPath: "scheme") legacy = jsonDictionary.json(atKeyPath: "legacy") + attributes = jsonDictionary.json(atKeyPath: "attributes") ?? [:] } } diff --git a/Sources/XcodeGenKit/PBXProjGenerator.swift b/Sources/XcodeGenKit/PBXProjGenerator.swift index 07da280e..fcd802ab 100644 --- a/Sources/XcodeGenKit/PBXProjGenerator.swift +++ b/Sources/XcodeGenKit/PBXProjGenerator.swift @@ -218,35 +218,37 @@ public class PBXProjGenerator { func generateTargetAttributes() -> [String: Any]? { - var targetAttributes: [String: Any] = [:] - - // 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 } - - let configs = buildConfigurationReferences - .flatMap { ref in self.proj.objects.buildConfigurations[ref] } - - return configs - .flatMap { $0.buildSettings["TEST_TARGET_NAME"] as? String } - .first - } + var targetAttributes: [String: [String: Any]] = [:] let uiTestTargets = proj.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 } + + let configs = buildConfigurationReferences + .flatMap { ref in self.proj.objects.buildConfigurations[ref] } + + return configs + .flatMap { $0.buildSettings["TEST_TARGET_NAME"] as? String } + .first + } + guard let name = testTargetName(uiTestTarget.object) else { continue } guard let target = self.proj.objects.targets(named: name).first else { continue } - targetAttributes[uiTestTarget.reference] = ["TestTargetID": target.reference] + targetAttributes[uiTestTarget.reference, default: [:]].merge(["TestTargetID": target.reference]) + } + + for target in spec.targets { + if !target.attributes.isEmpty, let targetObject = targetObjects[target.name] { + targetAttributes[targetObject.reference, default: [:]].merge(target.attributes) + } } - guard !targetAttributes.isEmpty else { return nil } - - return [ - "TargetAttributes": targetAttributes, - ] + return targetAttributes.isEmpty ? nil : ["TargetAttributes": targetAttributes] } func sortGroups(group: ObjectReference) { diff --git a/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj b/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj index 9c586dd0..f461129e 100644 --- a/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj +++ b/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj @@ -678,6 +678,9 @@ NT_123503999387 = { TestTargetID = NT_825232110500; }; + NT_825232110500 = { + ProvisioningStyle = Automatic; + }; }; }; buildConfigurationList = CL_844877120535 /* Build configuration list for PBXProject "Project" */; diff --git a/Tests/Fixtures/TestProject/spec.yml b/Tests/Fixtures/TestProject/spec.yml index 33ee362a..233e0a5c 100644 --- a/Tests/Fixtures/TestProject/spec.yml +++ b/Tests/Fixtures/TestProject/spec.yml @@ -23,6 +23,8 @@ targets: type: application platform: iOS deploymentTarget: 11.2 + attributes: + ProvisioningStyle: Automatic sources: - StandaloneFiles/StandaloneAssets.xcassets - path: App_iOS diff --git a/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift b/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift index a29ae343..91ecd21a 100644 --- a/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift +++ b/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift @@ -208,7 +208,12 @@ func projectGeneratorTests() { } $0.it("generates target attributes") { - + var appTargetWithAttributes = application + appTargetWithAttributes.attributes = ["ProvisioningStyle": "Automatic"] + + var testTargetWithAttributes = uiTest + testTargetWithAttributes.attributes = ["ProvisioningStyle": "Manual"] + var spec = ProjectSpec(basePath: "", name: "test", targets: [appTargetWithAttributes, framework, testTargetWithAttributes]) let pbxProject = try getPbxProj(spec) guard let targetAttributes = pbxProject.objects.projects.referenceValues.first?.attributes["TargetAttributes"] as? [String: [String: Any]] else { @@ -224,6 +229,8 @@ func projectGeneratorTests() { } try expect(targetAttributes[uiTestTarget.reference]?["TestTargetID"] as? String) == appTarget.reference + try expect(targetAttributes[uiTestTarget.reference]?["ProvisioningStyle"] as? String) == "Manual" + try expect(targetAttributes[appTarget.reference]?["ProvisioningStyle"] as? String) == "Automatic" } $0.it("generates platform version") {