mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2026-03-18 20:02:25 +00:00
Merge pull request #54 from yonaskolb/target_map
Change targets from list to map
This commit is contained in:
@@ -83,7 +83,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FR7078510801 /* FrameworkFile.swift */,
|
||||
FR1345298502 /* Info.plist */,
|
||||
FR1345298501 /* Info.plist */,
|
||||
FR7740960501 /* MyFramework.h */,
|
||||
);
|
||||
name = MyFramework;
|
||||
@@ -95,7 +95,7 @@
|
||||
children = (
|
||||
FR1332263601 /* AppDelegate.swift */,
|
||||
FR5980633301 /* Assets.xcassets */,
|
||||
FR1345298501 /* Info.plist */,
|
||||
FR1345298502 /* Info.plist */,
|
||||
FR6218091901 /* ViewController.swift */,
|
||||
VG6405436301 /* LaunchScreen.storyboard */,
|
||||
VG1473702401 /* Main.storyboard */,
|
||||
@@ -107,8 +107,8 @@
|
||||
G84487712001 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
G65232631501 /* TestProject */,
|
||||
G29934978701 /* MyFramework */,
|
||||
G65232631501 /* TestProject */,
|
||||
G26536595301 /* TestProjectTests */,
|
||||
G86202385201 /* Products */,
|
||||
);
|
||||
@@ -223,8 +223,8 @@
|
||||
);
|
||||
mainGroup = G84487712001;
|
||||
targets = (
|
||||
NT6523263101 /* TestProject */,
|
||||
NT2993497801 /* MyFramework */,
|
||||
NT6523263101 /* TestProject */,
|
||||
NT2653659501 /* TestProjectTests */,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: GeneratedProject
|
||||
targets:
|
||||
- name: TestProject
|
||||
TestProject:
|
||||
type: application
|
||||
platform: iOS
|
||||
sources: TestProject
|
||||
@@ -23,7 +23,7 @@ targets:
|
||||
else
|
||||
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
|
||||
fi
|
||||
- name: MyFramework
|
||||
MyFramework:
|
||||
type: framework
|
||||
platform: iOS
|
||||
sources: MyFramework
|
||||
@@ -32,7 +32,7 @@ targets:
|
||||
postbuildScripts:
|
||||
- name: Swiftlint
|
||||
path: scripts/swiftlint.sh
|
||||
- name: TestProjectTests
|
||||
TestProjectTests:
|
||||
type: bundle.unit-test
|
||||
platform: iOS
|
||||
sources: TestProjectTests
|
||||
|
||||
@@ -7,6 +7,10 @@ settingGroups:
|
||||
new:
|
||||
MY_SETTING: VALUE
|
||||
targets:
|
||||
- name: NewTarget
|
||||
NewTarget:
|
||||
type: application
|
||||
platform: iOS
|
||||
IncludedTarget:
|
||||
name: IncludedTargetNew
|
||||
platform: tvOS
|
||||
sources: Target
|
||||
|
||||
@@ -4,6 +4,6 @@ settingGroups:
|
||||
MY_SETTING1: VALUE1
|
||||
MY_SETTING2: VALUE2
|
||||
targets:
|
||||
- name: IncludedTarget
|
||||
IncludedTarget:
|
||||
type: application
|
||||
platform: iOS
|
||||
|
||||
@@ -68,7 +68,7 @@ configs:
|
||||
config1: debug
|
||||
config2: release
|
||||
targets:
|
||||
- name: Target
|
||||
Target:
|
||||
type: application
|
||||
platform: iOS
|
||||
settings:
|
||||
|
||||
@@ -38,7 +38,7 @@ Given a very simple project spec file like this:
|
||||
```yaml
|
||||
name: My Project
|
||||
targets:
|
||||
- name: MyApp
|
||||
MyApp:
|
||||
type: application
|
||||
platform: iOS
|
||||
sources: MyApp
|
||||
@@ -46,7 +46,7 @@ targets:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.myapp
|
||||
dependencies:
|
||||
- target: MyFramework
|
||||
- name: MyFramework
|
||||
MyFramework:
|
||||
type: framework
|
||||
platform: iOS
|
||||
sources: MyFramework
|
||||
|
||||
@@ -74,12 +74,13 @@ extension ProjectSpec.Options: Equatable {
|
||||
extension ProjectSpec: JSONObjectConvertible {
|
||||
|
||||
public init(jsonDictionary: JSONDictionary) throws {
|
||||
let jsonDictionary = try ProjectSpec.filterJSON(jsonDictionary: jsonDictionary)
|
||||
name = try jsonDictionary.json(atKeyPath: "name")
|
||||
settings = jsonDictionary.json(atKeyPath: "settings") ?? .empty
|
||||
settingGroups = jsonDictionary.json(atKeyPath: "settingGroups") ?? jsonDictionary.json(atKeyPath: "settingPresets") ?? [:]
|
||||
let configs: [String: String] = jsonDictionary.json(atKeyPath: "configs") ?? [:]
|
||||
self.configs = configs.map { Config(name: $0, type: ConfigType(rawValue: $1)) }
|
||||
targets = try Target.decodeTargets(jsonDictionary: jsonDictionary)
|
||||
targets = try jsonDictionary.json(atKeyPath: "targets").sorted { $0.name < $1.name }
|
||||
schemes = try jsonDictionary.json(atKeyPath: "schemes")
|
||||
attributes = jsonDictionary.json(atKeyPath: "attributes") ?? [:]
|
||||
if jsonDictionary["options"] != nil {
|
||||
@@ -88,6 +89,10 @@ extension ProjectSpec: JSONObjectConvertible {
|
||||
options = Options()
|
||||
}
|
||||
}
|
||||
|
||||
static func filterJSON(jsonDictionary: JSONDictionary) throws -> JSONDictionary {
|
||||
return try Target.generateCrossPlaformTargets(jsonDictionary: jsonDictionary)
|
||||
}
|
||||
}
|
||||
|
||||
extension ProjectSpec.Options: JSONObjectConvertible {
|
||||
|
||||
@@ -48,22 +48,20 @@ public struct Target {
|
||||
|
||||
extension Target {
|
||||
|
||||
static func decodeTargets(jsonDictionary: JSONDictionary) throws -> [Target] {
|
||||
guard jsonDictionary["targets"] != nil else {
|
||||
return []
|
||||
static func generateCrossPlaformTargets(jsonDictionary: JSONDictionary) throws -> JSONDictionary {
|
||||
guard let targetsDictionary: [String: JSONDictionary] = jsonDictionary["targets"] as? [String: JSONDictionary] else {
|
||||
return jsonDictionary
|
||||
}
|
||||
let array: [JSONDictionary] = try jsonDictionary.json(atKeyPath: "targets", invalidItemBehaviour: .fail)
|
||||
|
||||
var targets: [JSONDictionary] = []
|
||||
|
||||
let platformReplacement = "$platform"
|
||||
var crossPlatformTargets: [String: JSONDictionary] = [:]
|
||||
|
||||
for json in array {
|
||||
for (targetName, target) in targetsDictionary {
|
||||
|
||||
if let platforms = json["platform"] as? [String] {
|
||||
if let platforms = target["platform"] as? [String] {
|
||||
|
||||
for platform in platforms {
|
||||
var platformTarget = json
|
||||
var platformTarget = target
|
||||
|
||||
func replacePlatform(_ dictionary: JSONDictionary) -> JSONDictionary {
|
||||
var replaced = dictionary
|
||||
@@ -88,31 +86,30 @@ extension Target {
|
||||
platformTarget["platform"] = platform
|
||||
let platformSuffix = platformTarget["platformSuffix"] as? String ?? "_\(platform)"
|
||||
let platformPrefix = platformTarget["platformPrefix"] as? String ?? ""
|
||||
let name = platformTarget["name"] as? String ?? ""
|
||||
platformTarget["name"] = platformPrefix + name + platformSuffix
|
||||
let newTargetName = platformPrefix + targetName + platformSuffix
|
||||
|
||||
var settings = platformTarget["settings"] as? JSONDictionary ?? [:]
|
||||
if settings["configs"] != nil || settings["groups"] != nil || settings["base"] != nil {
|
||||
var base = settings["base"] as? JSONDictionary ?? [:]
|
||||
if base["PRODUCT_NAME"] == nil {
|
||||
base["PRODUCT_NAME"] = name
|
||||
base["PRODUCT_NAME"] = targetName
|
||||
}
|
||||
settings["base"] = base
|
||||
} else {
|
||||
if settings["PRODUCT_NAME"] == nil {
|
||||
settings["PRODUCT_NAME"] = name
|
||||
settings["PRODUCT_NAME"] = targetName
|
||||
}
|
||||
}
|
||||
platformTarget["settings"] = settings
|
||||
|
||||
targets.append(platformTarget)
|
||||
crossPlatformTargets[newTargetName] = platformTarget
|
||||
}
|
||||
} else {
|
||||
targets.append(json)
|
||||
crossPlatformTargets[targetName] = target
|
||||
}
|
||||
}
|
||||
|
||||
return try targets.map { try Target(jsonDictionary: $0) }
|
||||
var merged = jsonDictionary
|
||||
merged["targets"] = crossPlatformTargets
|
||||
return merged
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,10 +156,10 @@ extension TargetScheme: JSONObjectConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
extension Target: JSONObjectConvertible {
|
||||
extension Target: NamedJSONDictionaryConvertible {
|
||||
|
||||
public init(jsonDictionary: JSONDictionary) throws {
|
||||
name = try jsonDictionary.json(atKeyPath: "name")
|
||||
public init(name: String, jsonDictionary: JSONDictionary) throws {
|
||||
self.name = jsonDictionary.json(atKeyPath: "name") ?? name
|
||||
let typeString: String = try jsonDictionary.json(atKeyPath: "type")
|
||||
if let type = PBXProductType(string: typeString) {
|
||||
self.type = type
|
||||
|
||||
@@ -23,11 +23,11 @@ func specLoadingTests() {
|
||||
|
||||
func expectTargetError(_ target: [String: Any], _ expectedError: ProjectSpecError) throws {
|
||||
try expectError(expectedError) {
|
||||
_ = try Target(jsonDictionary: target)
|
||||
_ = try Target(name: "test", jsonDictionary: target)
|
||||
}
|
||||
}
|
||||
|
||||
let validTarget: [String: Any] = ["name": "test", "type": "application", "platform": "iOS"]
|
||||
let validTarget: [String: Any] = ["type": "application", "platform": "iOS"]
|
||||
let invalid = "invalid"
|
||||
|
||||
describe("Spec Loader") {
|
||||
@@ -41,7 +41,7 @@ func specLoadingTests() {
|
||||
"new": Settings(dictionary: ["MY_SETTING": "VALUE"]),
|
||||
]
|
||||
try expect(spec.targets) == [
|
||||
Target(name: "IncludedTarget", type: .application, platform: .iOS),
|
||||
Target(name: "IncludedTargetNew", type: .application, platform: .tvOS, sources: ["Target"]),
|
||||
Target(name: "NewTarget", type: .application, platform: .iOS),
|
||||
]
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func specLoadingTests() {
|
||||
["carthage": "name"],
|
||||
["framework": "path"],
|
||||
]
|
||||
let target = try Target(jsonDictionary: targetDictionary)
|
||||
let target = try Target(name: "test", jsonDictionary: targetDictionary)
|
||||
try expect(target.dependencies.count) == 3
|
||||
try expect(target.dependencies[0]) == Dependency(type: .target, reference: "name", embed: false)
|
||||
try expect(target.dependencies[1]) == Dependency(type: .carthage, reference: "name")
|
||||
@@ -83,14 +83,13 @@ func specLoadingTests() {
|
||||
|
||||
$0.it("parsed cross platform targets") {
|
||||
let targetDictionary: [String: Any] = [
|
||||
"name": "Framework",
|
||||
"platform": ["iOS", "tvOS"],
|
||||
"type": "framework",
|
||||
"sources": ["Framework", "Framework $platform"],
|
||||
"settings": ["SETTING": "value_$platform"],
|
||||
]
|
||||
|
||||
let spec = try getProjectSpec(["targets": [targetDictionary]])
|
||||
let spec = 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)
|
||||
|
||||
@@ -167,7 +166,7 @@ func specLoadingTests() {
|
||||
BuildScript(script: .script("shell script\ndo thing"), name: "myscript", inputFiles: ["file", "file2"], outputFiles: ["file", "file2"], shell: "bin/customshell", runOnlyWhenInstalling: true),
|
||||
]
|
||||
|
||||
let parsedTarget = try Target(jsonDictionary: target)
|
||||
let parsedTarget = try Target(name: "test", jsonDictionary: target)
|
||||
try expect(parsedTarget.prebuildScripts) == expectedScripts
|
||||
try expect(parsedTarget.postbuildScripts) == expectedScripts
|
||||
}
|
||||
|
||||
+25
-23
@@ -25,13 +25,13 @@ Required properties are marked 🔵 and optional properties with ⚪️.
|
||||
## Project
|
||||
|
||||
- 🔵 **name**: `String` - Name of the generated project
|
||||
- ⚪️ **include**: `[String]` - The paths to other specs. They will be merged in order and then the current spec will be merged on top
|
||||
- ⚪️ **include**: `[String]` - The paths to other specs. They will be merged in order and then the current spec will be merged on top. Target names can be changed by adding a `name` property
|
||||
- ⚪️ **options**: [Options](#options) - Various options to override default behaviour
|
||||
- ⚪️ **attributes**: `map` - The PBXProject attributes. This is for advanced use. Defaults to ``{"LastUpgradeCheck": "0830"}``
|
||||
- ⚪️ **configs**: [Configs](#configs) - Project build configurations. Defaults to `Debug` and `Release` configs
|
||||
- ⚪️ **settings**: [Settings](#settings) - Project specific settings. Default base and config type settings will be applied first before any settings defined here
|
||||
- ⚪️ **settingGroups**: [Setting Groups](#setting-groups) - Setting groups mapped by name
|
||||
- ⚪️ **targets**: [[Target](#target)] - The list of targets in the project
|
||||
- ⚪️ **targets**: [String: [Target](#target)] - The list of targets in the project mapped by name
|
||||
|
||||
### Options
|
||||
- ⚪️ **carthageBuildPath**: `String` - The path to the carthage build directory. Defaults to `Carthage/Build`. This is used when specifying target carthage dependencies
|
||||
@@ -94,7 +94,6 @@ Settings are merged in the following order: groups, base, configs.
|
||||
|
||||
## Target
|
||||
|
||||
- 🔵 **name**: `String` - Name of the target
|
||||
- 🔵 **type**: [Product Type](#product-type) - Product type of the target
|
||||
- 🔵 **platform**: [Platform](#platform) - Platform of the target
|
||||
- ⚪️ **sources**: [Sources](#sources) - Source directories of the target
|
||||
@@ -146,18 +145,19 @@ The generated targets by default will have a suffix of `_$platform` applied, you
|
||||
|
||||
If no `PRODUCT_NAME` build setting is specified for a target, this will be set to the target name, so that this target can be imported under a single name.
|
||||
|
||||
```
|
||||
name: MyFramework
|
||||
sources: MyFramework
|
||||
platform: [iOS, tvOS]
|
||||
type: framework
|
||||
settings:
|
||||
base:
|
||||
INFOPLIST_FILE: MyApp/Info.plist
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.myapp
|
||||
MY_SETTING: platform $platform
|
||||
groups:
|
||||
- $platform
|
||||
```yaml
|
||||
targets:
|
||||
MyFramework:
|
||||
sources: MyFramework
|
||||
platform: [iOS, tvOS]
|
||||
type: framework
|
||||
settings:
|
||||
base:
|
||||
INFOPLIST_FILE: MyApp/Info.plist
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.myapp
|
||||
MY_SETTING: platform $platform
|
||||
groups:
|
||||
- $platform
|
||||
```
|
||||
The above will generate 2 targets named `MyFramework_iOS` and `MyFramework_tvOS`, with all the relevant platform build settings. They will both have a `PRODUCT_NAME` of `MyFramework`
|
||||
|
||||
@@ -166,9 +166,9 @@ Specifies the source directories for a target. This can either be a single path
|
||||
|
||||
```yaml
|
||||
targets:
|
||||
- name: MyTarget
|
||||
MyTarget
|
||||
sources: MyTargetSource
|
||||
- name: MyOtherTarget
|
||||
MyOtherTarget
|
||||
sources:
|
||||
- MyOtherTargetSource1
|
||||
- MyOtherTargetSource2
|
||||
@@ -201,12 +201,13 @@ If any applications contain carthage dependencies within itself or any dependent
|
||||
|
||||
```yaml
|
||||
targets:
|
||||
- name: MyTarget
|
||||
MyTarget:
|
||||
dependencies:
|
||||
- target: MyFramework
|
||||
- framework: path/to/framework.framework
|
||||
- carthage: Result
|
||||
- name: MyFramework
|
||||
MyFramework:
|
||||
type: framework
|
||||
```
|
||||
|
||||
### Config Files
|
||||
@@ -214,7 +215,7 @@ Specifies `.xcconfig` files for each configuration.
|
||||
|
||||
```yaml
|
||||
targets:
|
||||
- name: MyTarget
|
||||
MyTarget:
|
||||
configFiles:
|
||||
Debug: config_files/debug.xcconfig
|
||||
Release: config_files/release.xcconfig
|
||||
@@ -237,7 +238,7 @@ A multiline script can be written using the various YAML multiline methods, for
|
||||
|
||||
```yaml
|
||||
targets:
|
||||
- name: MyTarget
|
||||
MyTarget:
|
||||
prebuildScripts:
|
||||
- path: myscripts/my_script.sh
|
||||
name: My Script
|
||||
@@ -279,7 +280,7 @@ configs:
|
||||
Staging Release: release
|
||||
Production Release: release
|
||||
targets
|
||||
- name: MyApp
|
||||
MyApp:
|
||||
scheme:
|
||||
testTargets:
|
||||
- MyUnitTests
|
||||
@@ -287,5 +288,6 @@ targets
|
||||
- Test
|
||||
- Staging
|
||||
- Production
|
||||
- name: MyUnitTests
|
||||
MyUnitTests:
|
||||
sources: Tests
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user