Merge pull request #306 from yonaskolb/build_rule

Add build rules
This commit is contained in:
Yonas Kolb 2018-05-24 16:22:06 +10:00 committed by GitHub
commit 701df1c915
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 183 additions and 1 deletions

View File

@ -19,6 +19,7 @@ Required properties are marked with checkbox. Some of the YAML examples don't sh
- [Config Files](#config-files)
- [Settings](#settings)
- [Build Script](#build-script)
- [Build Rule](#build-rule)
- [Dependency](#dependency)
- [Target Scheme](#target-scheme)
- [Legacy Target](#legacy-target)
@ -160,9 +161,10 @@ Settings are merged in the following order: groups, base, configs.
- [ ] **settings**: **[Settings](#settings)** - Target specific build settings. Default platform and product type settings will be applied first before any custom settings defined here. Other context dependant settings will be set automatically as well:
- `INFOPLIST_FILE`: If it doesn't exist your sources will be searched for `Info.plist` files and the first one found will be used for this setting
- `FRAMEWORK_SEARCH_PATHS`: If carthage dependencies are used, the platform build path will be added to this setting
- [ ] **dependencies**: **[[Dependency](#dependency)]** - Dependencies for the target
- [ ] **prebuildScripts**: **[[Build Script](#build-script)]** - Build scripts that run *before* any other build phases
- [ ] **postbuildScripts**: **[[Build Script](#build-script)]** - Build scripts that run *after* any other build phases
- [ ] **dependencies**: **[[Dependency](#dependency)]** - Dependencies for the target
- [ ] **buildRules**: **[[Build Rule](#build-rule)]** - Custom build rules
- [ ] **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. Properties that are already set include:
@ -374,6 +376,17 @@ targets:
othercommand
```
### Build Rule
- [ ] **filePattern**: **String** - A glob pattern for the files that will have the build rule run on them. This or `fileType` must be defined
- [ ] **fileType**: **String** - A file type determined by Xcode. The available types can be seen by hovering your mouse of the `Process` dropdown in the Xcode interface. For example `sourcecode.swift` or `file.xib`. This or `filePattern` must be defined.
- [ ] **script**: **String** - The script that will be run on each file. This or `compilerSpec` must be defined.
- [ ] **compilerSpec**: **String**: A reference to a built in apple tool to run on each file. This is for advanced use and the the values for this must be checked. This or `script` must be defined.
- [ ] **name**: **String** - The name of a build rule. Defaults to `Build Rule`
- [ ] **outputFiles**: **[String]** - The list of output files
- [ ] **outputFilesCompilerFlags**: **[String]** - The list of compiler flags to apply to the output files
### Target Scheme
This is a convenience used to automatically generate schemes for a target based on different configs or included tests. If you want more control check out the top level [Scheme](#scheme).

View File

@ -0,0 +1,82 @@
import Foundation
import JSONUtilities
public struct BuildRule: Equatable {
public static let scriptCompilerSpec = "com.apple.compilers.proxy.script"
public static let filePatternFileType = "pattern.proxy"
public enum FileType: Equatable {
case type(String)
case pattern(String)
public var fileType: String {
switch self {
case .type(let fileType): return fileType
case .pattern: return BuildRule.filePatternFileType
}
}
public var pattern: String? {
switch self {
case .type: return nil
case .pattern(let pattern): return pattern
}
}
}
public enum Action: Equatable {
case compilerSpec(String)
case script(String)
public var compilerSpec: String {
switch self {
case .compilerSpec(let compilerSpec): return compilerSpec
case .script: return BuildRule.scriptCompilerSpec
}
}
public var script: String? {
switch self {
case .compilerSpec: return nil
case .script(let script): return script
}
}
}
public var fileType: FileType
public var action: Action
public var outputFiles: [String]
public var outputFilesCompilerFlags: [String]
public var name: String?
public init(fileType: FileType, action: Action, name: String? = nil, outputFiles: [String] = [], outputFilesCompilerFlags: [String] = []) {
self.fileType = fileType
self.action = action
self.name = name
self.outputFiles = outputFiles
self.outputFilesCompilerFlags = outputFilesCompilerFlags
}
}
extension BuildRule: JSONObjectConvertible {
public init(jsonDictionary: JSONDictionary) throws {
if let fileType: String = jsonDictionary.json(atKeyPath: "fileType") {
self.fileType = .type(fileType)
} else {
self.fileType = .pattern(try jsonDictionary.json(atKeyPath: "filePattern"))
}
if let compilerSpec: String = jsonDictionary.json(atKeyPath: "compilerSpec") {
self.action = .compilerSpec(compilerSpec)
} else {
self.action = .script(try jsonDictionary.json(atKeyPath: "script"))
}
outputFiles = jsonDictionary.json(atKeyPath: "outputFiles") ?? []
outputFilesCompilerFlags = jsonDictionary.json(atKeyPath: "outputFilesCompilerFlags") ?? []
name = jsonDictionary.json(atKeyPath: "name")
}
}

View File

@ -30,6 +30,7 @@ public struct Target {
public var dependencies: [Dependency]
public var prebuildScripts: [BuildScript]
public var postbuildScripts: [BuildScript]
public var buildRules: [BuildRule]
public var configFiles: [String: String]
public var scheme: TargetScheme?
public var legacy: LegacyTarget?
@ -60,6 +61,7 @@ public struct Target {
dependencies: [Dependency] = [],
prebuildScripts: [BuildScript] = [],
postbuildScripts: [BuildScript] = [],
buildRules: [BuildRule] = [],
scheme: TargetScheme? = nil,
legacy: LegacyTarget? = nil,
attributes: [String: Any] = [:]
@ -74,6 +76,7 @@ public struct Target {
self.dependencies = dependencies
self.prebuildScripts = prebuildScripts
self.postbuildScripts = postbuildScripts
self.buildRules = buildRules
self.scheme = scheme
self.legacy = legacy
self.attributes = attributes
@ -168,6 +171,7 @@ extension Target: Equatable {
lhs.dependencies == rhs.dependencies &&
lhs.prebuildScripts == rhs.prebuildScripts &&
lhs.postbuildScripts == rhs.postbuildScripts &&
lhs.buildRules == rhs.buildRules &&
lhs.scheme == rhs.scheme &&
lhs.legacy == rhs.legacy &&
NSDictionary(dictionary: lhs.attributes).isEqual(to: rhs.attributes)
@ -275,6 +279,7 @@ extension Target: NamedJSONDictionaryConvertible {
}
prebuildScripts = jsonDictionary.json(atKeyPath: "prebuildScripts") ?? []
postbuildScripts = jsonDictionary.json(atKeyPath: "postbuildScripts") ?? []
buildRules = jsonDictionary.json(atKeyPath: "buildRules") ?? []
scheme = jsonDictionary.json(atKeyPath: "scheme")
legacy = jsonDictionary.json(atKeyPath: "legacy")
attributes = jsonDictionary.json(atKeyPath: "attributes") ?? [:]

View File

@ -643,6 +643,20 @@ public class PBXProjGenerator {
buildPhases.append(carthageScript.reference)
}
let buildRules = target.buildRules.map { buildRule in
createObject(id: "\(target.name)-\(buildRule.action)-\(buildRule.fileType)",
PBXBuildRule(
compilerSpec: buildRule.action.compilerSpec,
fileType: buildRule.fileType.fileType,
isEditable: true,
filePatterns: buildRule.fileType.pattern,
name: buildRule.name ?? "Build Rule",
outputFiles: buildRule.outputFiles,
outputFilesCompilerFlags: buildRule.outputFilesCompilerFlags,
script: buildRule.action.script
)).reference
}
try target.postbuildScripts.forEach(generateBuildScript)
let targetObject = targetObjects[target.name]!.object
@ -652,6 +666,7 @@ public class PBXProjGenerator {
targetObject.buildPhases = buildPhases
targetObject.dependencies = dependencies
targetObject.productName = target.name
targetObject.buildRules = buildRules
targetObject.productReference = fileReference
if !target.isLegacy {
targetObject.productType = target.type

View File

@ -63,6 +63,37 @@
BF_940936137577 = {isa = PBXBuildFile; fileRef = FR_123503999387 /* App_iOS_UITests.xctest */; };
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
BR_808703807095 /* PBXBuildRule */ = {
isa = PBXBuildRule;
compilerSpec = "com.apple.build-tasks.copy-plist-file";
filePatterns = "*.plist";
fileType = pattern.proxy;
isEditable = 1;
name = "Build Rule";
outputFiles = (
);
outputFilesCompilerFlags = (
);
};
BR_855671637991 /* PBXBuildRule */ = {
isa = PBXBuildRule;
compilerSpec = com.apple.compilers.proxy.script;
fileType = sourcecode.swift;
isEditable = 1;
name = "My Rule";
outputFiles = (
file.swift,
file2.swift,
);
outputFilesCompilerFlags = (
"--zee",
"--bee",
);
script = "# comment";
};
/* End PBXBuildRule section */
/* Begin PBXContainerItemProxy section */
CIP_12350399938 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
@ -665,6 +696,8 @@
SSBP_8706434794 /* MyScript */,
);
buildRules = (
BR_855671637991 /* PBXBuildRule */,
BR_808703807095 /* PBXBuildRule */,
);
dependencies = (
TD_354342487294 /* PBXTargetDependency */,

View File

@ -67,6 +67,14 @@ targets:
- name: MyScript
script: |
echo "You ran a script!"
buildRules:
- name: My Rule
fileType: sourcecode.swift
script: "# comment"
outputFiles: [file.swift, file2.swift]
outputFilesCompilerFlags: [--zee, --bee]
- filePattern: "*.plist"
compilerSpec: com.apple.build-tasks.copy-plist-file
App_watchOS:
type: application.watchapp2

View File

@ -364,6 +364,32 @@ func projectLoadingTests() {
try expect(parsedTarget.postbuildScripts) == expectedScripts
}
$0.it("parses build rules") {
var target = validTarget
let buildRules: [[String: Any]] = [
[
"name": "My Rule",
"script": "my script",
"filePattern": "*.swift",
"outputFiles": ["file1", "file2"],
"outputFilesCompilerFlags": ["-a","-b"]
],
[
"compilerSpec": "apple.tool",
"fileType": "sourcecode.swift",
]
]
target["buildRules"] = buildRules
let expectedBuildRules = [
BuildRule(fileType: .pattern("*.swift"), action: .script("my script"), name: "My Rule", outputFiles: ["file1", "file2"], outputFilesCompilerFlags: ["-a","-b"]),
BuildRule(fileType: .type("sourcecode.swift"), action: .compilerSpec("apple.tool")),
]
let parsedTarget = try Target(name: "test", jsonDictionary: target)
try expect(parsedTarget.buildRules) == expectedBuildRules
}
$0.it("parses options") {
let options = SpecOptions(
carthageBuildPath: "../Carthage/Build",