Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace $target_name in target templates #504

Merged
merged 2 commits into from
Jan 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added ability to generate empty directories via `options.generateEmptyDirectories` [#480](https://github.com/yonaskolb/XcodeGen/pull/480) @Beniamiiin
- Added support for the `instrumentsPackage` product type [#482](https://github.com/yonaskolb/XcodeGen/pull/482) @ksulliva
- Added support for `inputFileLists` and `outputFileLists` within project build scripts [#500](https://github.com/yonaskolb/XcodeGen/pull/500) @lukewakeford
- Added support for a `$target_name` replacement string within target templates [#504](https://github.com/yonaskolb/XcodeGen/pull/504) @yonaskolb

#### Changed
- **BREAKING**: All the paths within `include` files are now relative to that file and not the root spec. This can be disabled with a `relativePaths: false` on the include. See the [documentation](https://github.com/yonaskolb/XcodeGen/blob/master/Docs/ProjectSpec.md#include) for more details [#489](https://github.com/yonaskolb/XcodeGen/pull/489) @ellneal
Expand Down
26 changes: 24 additions & 2 deletions Docs/ProjectSpec.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Required properties are marked with checkbox. Some of the YAML examples don't sh
- [Target Scheme](#target-scheme)
- [Legacy Target](#legacy-target)
- [Aggregate Target](#aggregate-target)
- [Target Template](#target-template)
- [Scheme](#scheme)

## Project
Expand All @@ -39,7 +40,7 @@ Required properties are marked with checkbox. Some of the YAML examples don't sh
- [ ] **targets**: **[String: [Target](#target)]** - The list of targets in the project mapped by name
- [ ] **fileGroups**: **[String]** - A list of paths to add to the root of the project. These aren't files that will be included in your targets, but that you'd like to include in the project hierachy anyway. For example a folder of xcconfig files that aren't already added by any target sources, or a Readme file.
- [ ] **schemes**: **[Scheme](#scheme)** - A list of schemes by name. This allows more control over what is found in [Target Scheme](#target-scheme)
- [ ] **targetTemplates**: **[String: [Target](#target)]** - a list of targets that can be used as templates for actual targets which reference them via a `template` property. They can be used to extract common target settings. Works great in combination with `include`.
- [ ] **targetTemplates**: **[String: [Target Template](#target-template)]** - a list of targets that can be used as templates for actual targets which reference them via a `template` property. They can be used to extract common target settings. Works great in combination with `include`.

### Include

Expand Down Expand Up @@ -200,7 +201,7 @@ Settings are merged in the following order: groups, base, configs.
- `CFBundleVersion`
- `CFBundlePackageType`
- [ ] **entitlements**: **[Plist](#plist)** - If defined this will generate and write a `.entitlements` file, and use it by setting `CODE_SIGN_ENTITLEMENTS` build setting for every configuration. All properties must be provided
- [ ] **templates**: **[String]** - A list of target templates that will be merged in order
- [ ] **templates**: **[String]** - A list of [Target Templates](#target-template) referenced by name that will be merged with the target in order. Any instances of `$target_name` within these templates will be replaced with the target name.
- [ ] **transitivelyLinkDependencies**: **Bool** - If this is not specified the value from the project set in [Options](#options)`.transitivelyLinkDependencies` will be used.
- [ ] **directlyEmbedCarthageDependencies**: **Bool** - If this is `true` Carthage dependencies will be embedded using an `Embed Frameworks` build phase instead of the `copy-frameworks` script. Defaults to `true` for all targets except iOS/tvOS/watchOS Applications.
- [ ] **requiresObjCLinking**: **Bool** - If this is `true` any targets that link to this target will have `-ObjC` added to their `OTHER_LDFLAGS`. This is required if a static library has any catagories or extensions on Objective-C code. See [this guide](https://pewpewthespells.com/blog/objc_linker_flags.html#objc) for more details. Defaults to `true` if `type` is `library.static`. If you are 100% sure you don't have catagories or extensions on Objective-C code (pure Swift with no use of Foundation/UIKit) you can set this to `false`, otherwise it's best to leave it alone.
Expand Down Expand Up @@ -554,6 +555,27 @@ This is used to override settings or run build scripts in specific targets
- [ ] **scheme**: **[Target Scheme](#target-scheme)** - Generated scheme
- [ ] **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

## Target Template

This is a template that can be referenced from a normal target using the `templates` property. The properties of this template are the same as a [Target](#target)].
Any instances of `$target_name` within each template will be replaced by the final target name which references the template.


```yaml
targets:
MyFramework:
templates:
- Framework
sources:
- SomeSources
targetTemplates:
Framework:
platform: iOS
type: framework
sources:
- $target_name/Sources
```

## Scheme

Schemes allows for more control than the convenience [Target Scheme](#target-scheme) on [Target](#target)
Expand Down
2 changes: 1 addition & 1 deletion Sources/ProjectSpec/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ extension Project {

static func resolveProject(jsonDictionary: JSONDictionary) throws -> JSONDictionary {
var jsonDictionary = jsonDictionary
jsonDictionary = try Target.resolveTargetTemplates(jsonDictionary: jsonDictionary)
jsonDictionary = try Target.resolveMultiplatformTargets(jsonDictionary: jsonDictionary)
jsonDictionary = try Target.resolveTargetTemplates(jsonDictionary: jsonDictionary)
return jsonDictionary
}
}
Expand Down
18 changes: 18 additions & 0 deletions Sources/ProjectSpec/Spec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,22 @@ extension Dictionary where Key == String, Value: Any {
}
return merged
}

func replaceString(_ template: String, with replacement: String) -> JSONDictionary {
var replaced: JSONDictionary = self
for (key, value) in self {
switch value {
case let dictionary as JSONDictionary:
replaced[key] = dictionary.replaceString(template, with: replacement)
case let string as String:
replaced[key] = string.replacingOccurrences(of: template, with: replacement)
case let array as [JSONDictionary]:
replaced[key] = array.map { $0.replaceString(template, with: replacement) }
case let array as [String]:
replaced[key] = array.map { $0.replacingOccurrences(of: template, with: replacement) }
default: break
}
}
return replaced
}
}
22 changes: 2 additions & 20 deletions Sources/ProjectSpec/Target.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ extension Target {
}
}
target = target.merged(onto: mergedDictionary)
target = target.replaceString("$target_name", with: targetName)
}
targetsDictionary[targetName] = target
}
Expand All @@ -163,7 +164,6 @@ extension Target {
return jsonDictionary
}

let platformReplacement = "$platform"
var crossPlatformTargets: [String: JSONDictionary] = [:]

for (targetName, target) in targetsDictionary {
Expand All @@ -173,25 +173,7 @@ extension Target {
for platform in platforms {
var platformTarget = target

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 = platformTarget.replaceString("$platform", with: platform)

platformTarget["platform"] = platform
let platformSuffix = platformTarget["platformSuffix"] as? String ?? "_\(platform)"
Expand Down
2 changes: 2 additions & 0 deletions Tests/XcodeGenKitTests/SpecLoadingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ class SpecLoadingTests: XCTestCase {
"type": "framework",
"platform": "tvOS",
"deploymentTarget": "1.1.0",
"configFiles": ["debug": "Configs/$target_name/debug.xcconfig"]
],
],
])
Expand All @@ -356,6 +357,7 @@ class SpecLoadingTests: XCTestCase {
try expect(target.platform) == .iOS // uses latest value
try expect(target.deploymentTarget) == Version("1.2.0") // keeps value
try expect(target.sources) == ["templateSource", "targetSource"] // merges array in order
try expect(target.configFiles["debug"]) == "Configs/Framework/debug.xcconfig" // replaces $target_name
}

$0.it("parses aggregate targets") {
Expand Down