generate multi platform targets

This commit is contained in:
Yonas Kolb
2017-08-26 16:17:15 +02:00
parent 6f9f194863
commit da4b382f51
4 changed files with 118 additions and 5 deletions
+1 -5
View File
@@ -89,11 +89,7 @@ extension ProjectSpec {
settingPresets = jsonDictionary.json(atKeyPath: "settingPresets") ?? [:]
let configs: [String: String] = jsonDictionary.json(atKeyPath: "configs") ?? [:]
self.configs = configs.map { Config(name: $0, type: ConfigType(rawValue: $1)) }
if jsonDictionary["targets"] == nil {
targets = []
} else {
targets = try jsonDictionary.json(atKeyPath: "targets", invalidItemBehaviour: .fail)
}
self.targets = try Target.decodeTargets(jsonDictionary: jsonDictionary)
schemes = try jsonDictionary.json(atKeyPath: "schemes")
if jsonDictionary["options"] != nil {
options = try jsonDictionary.json(atKeyPath: "options")
+70
View File
@@ -46,6 +46,76 @@ public struct Target {
}
}
extension Target {
static func decodeTargets(jsonDictionary: JSONDictionary) throws -> [Target] {
guard jsonDictionary["targets"] != nil else {
return []
}
let array: [JSONDictionary] = try jsonDictionary.json(atKeyPath: "targets", invalidItemBehaviour: .fail)
var targets: [JSONDictionary] = []
let platformReplacement = "$platform"
for json in array {
if let platforms = json["platform"] as? [String] {
for platform in platforms {
var platformTarget = json
func replacePlatform(_ dictionary: JSONDictionary) -> JSONDictionary {
var replaced = dictionary
for (key, value) in dictionary {
switch value {
case let dictionary as JSONDictionary:
replaced[key] = replacePlatform(dictionary)
case let string as String:
replaced[key] = string.replacingOccurrences(of: platformReplacement, with: platform)
case let array as [JSONDictionary]:
replaced[key] = array.map(replacePlatform)
case let array as [String]:
replaced[key] = array.map { $0.replacingOccurrences(of: platformReplacement, with: platform) }
default: break
}
}
return replaced
}
platformTarget = replacePlatform(platformTarget)
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
var settings = platformTarget["settings"] as? JSONDictionary ?? [:]
if settings["configs"] != nil || settings["presets"] != nil || settings["base"] != nil {
var base = settings["base"] as? JSONDictionary ?? [:]
if base["PRODUCT_NAME"] == nil {
base["PRODUCT_NAME"] = name
}
settings["base"] = base
} else {
if settings["PRODUCT_NAME"] == nil {
settings["PRODUCT_NAME"] = name
}
}
platformTarget["settings"] = settings
targets.append(platformTarget)
}
} else {
targets.append(json)
}
}
return try targets.map { try Target(jsonDictionary: $0) }
}
}
extension Target: Equatable {
public static func ==(lhs: Target, rhs: Target) -> Bool {
@@ -64,6 +64,28 @@ func specLoadingTests() {
try expect(target.dependencies[2]) == .framework("path")
}
$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]])
var target_iOS = Target(name: "Framework_iOS", type: .framework, platform: .iOS)
var target_tvOS = Target(name: "Framework_tvOS", type: .framework, platform: .tvOS)
target_iOS.sources = ["Framework","Framework iOS"]
target_tvOS.sources = ["Framework","Framework tvOS"]
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]
}
$0.it("parses schemes") {
let schemeDictionary: [String: Any] = [
"build": ["targets": [
@@ -138,5 +160,6 @@ func specLoadingTests() {
let parsedSpec = try getProjectSpec(["options": ["carthageBuildPath": "../Carthage/Build"]])
try expect(parsedSpec) == expected
}
}
}
+24
View File
@@ -133,6 +133,30 @@ This will provide default build settings for a certain platform. It can be any o
- macOS
- watchOS
**Multi Platform targets**
You can also specify an array of platforms. This will generate a target for each platform.
If you reference the string `$platform` anywhere within the target spec, that will be replaced with the platform.
The generated targets by default will have a suffix of `_$platform` applied, you can change this by specifying a `platformSuffix` or `platformPrefix`.
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
presets:
- $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`
### Sources
Specifies the source directories for a target. This can either be a single path or a list of paths. Applicable source files, resources, headers, and lproj files will be parsed appropriately