Merge master into lockfile

This commit is contained in:
Yonas Kolb 2018-12-18 20:54:38 +11:00
commit f061c03e6a
10 changed files with 125 additions and 34 deletions

View File

@ -5,13 +5,20 @@
#### Added
- Added `--use-cache` argument to prevent unnecessarily generating the project [#412](https://github.com/yonaskolb/XcodeGen/pull/412) @yonaskolb
#### Fixed
- Fixed XPC Service package type [#435](https://github.com/yonaskolb/XcodeGen/pull/435) @alvarhansen
- Fixed phase ordering for modulemap and static libary header Copy File phases. [402](https://github.com/yonaskolb/XcodeGen/pull/402) @brentleyjones
#### Changed
- Changed spelling of build phases to **preBuildPhase** and **postBuildPhase**. [402](https://github.com/yonaskolb/XcodeGen/pull/402) @brentleyjones
- **BREAKING** Moved generation to a specific subcommand `xcodegen generate`. If not specifying any arguments `xcodegen` will still work [#437](https://github.com/yonaskolb/XcodeGen/pull/437) @yonaskolb
- Changed spelling of build phases to **preBuildPhase** and **postBuildPhase**. The older names are deprecated but still work [402](https://github.com/yonaskolb/XcodeGen/pull/402) @brentleyjones
- Moved generation to a specific subcommand `xcodegen generate`. Simple `xcodegen` will continue to work for now [#437](https://github.com/yonaskolb/XcodeGen/pull/437) @yonaskolb
- If `INFOPLIST_FILE` has been set on a target, then an `info` path won't ovewrite it [#443](https://github.com/yonaskolb/XcodeGen/pull/443) @feischl97
#### Fixed
- Fixed XPC Service package type in generated `Info.plist` [#435](https://github.com/yonaskolb/XcodeGen/pull/435) @alvarhansen
- Fixed phase ordering for modulemap and static libary header Copy File phases. [402](https://github.com/yonaskolb/XcodeGen/pull/402) @brentleyjones
- Fixed intermittent errors when running multiple `xcodegen`s concurrently [#450](https://github.com/yonaskolb/XcodeGen/pull/450) @bryansum
- Fixed `--project` argument not working [#437](https://github.com/yonaskolb/XcodeGen/pull/437) @yonaskolb
- Fixed unit tests not hooking up to host applications properly by default. They now generate a `TEST_HOST` and a `TestTargetID` [#452](https://github.com/yonaskolb/XcodeGen/pull/452) @yonaskolb
- Fixed static libraries not including external frameworks in their search paths [#454](https://github.com/yonaskolb/XcodeGen/pull/454) @brentleyjones
- Add `.intentdefinition` files to sources build phase instead of resources [#442](https://github.com/yonaskolb/XcodeGen/pull/442) @yonaskolb
- Add `mlmodel` files to sources build phase instead of resources [#457](https://github.com/yonaskolb/XcodeGen/pull/457) @dwb357
## 2.0.0

View File

@ -108,7 +108,8 @@ Each config maps to a build type of either `debug` or `release` which will then
```yaml
configs:
Debug: debug
Release: release
Beta: release
AppStore: release
```
If no configs are specified, default `Debug` and `Release` configs will be created automatically.
@ -170,8 +171,10 @@ Settings are merged in the following order: groups, base, configs.
- `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
- `OTHER_LDFLAGS`: See `requiresObjCLinking` below
- `TEST_TARGET_NAME`: for ui tests that target an application
- `TEST_HOST`: for unit tests that target an application
- [ ] **dependencies**: **[[Dependency](#dependency)]** - Dependencies for the target
- [ ] **info**: **[Plist](#plist)** - If defined, this will generate and write an `Info.plist` to the specified path and use it by setting the `INFOPLIST_FILE` build setting for every configuration. The following properties are generated automatically, the rest will have to be provided.
- [ ] **info**: **[Plist](#plist)** - If defined, this will generate and write an `Info.plist` to the specified path and use it by setting the `INFOPLIST_FILE` build setting for every configuration, unless `INFOPLIST_FILE` is already defined in **settings** for this configuration. The following properties are generated automatically, the rest will have to be provided.
- `CFBundleIdentifier`
- `CFBundleInfoDictionaryVersion`
- `CFBundleExecutable`

View File

@ -164,7 +164,9 @@ Inspiration for this tool came from:
- [CocoaPods Xcodeproj](https://github.com/CocoaPods/Xcodeproj)
## Contributions
Pull requests and issues are welcome
Pull requests and issues are always welcome. Please open any issues and PRs for bugs, features, or documentation.
[![](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/images/0)](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/links/0)[![](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/images/1)](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/links/1)[![](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/images/2)](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/links/2)[![](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/images/3)](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/links/3)[![](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/images/4)](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/links/4)[![](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/images/5)](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/links/5)[![](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/images/6)](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/links/6)[![](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/images/7)](https://sourcerer.io/fame/yonaskolb/yonaskolb/XcodeGen/links/7)
## License

View File

@ -10,9 +10,9 @@ class CommandRouter: Router {
}
func parse(commandGroup: CommandGroup, arguments: ArgumentList) throws -> (CommandPath, OptionRegistry) {
if !arguments.hasNext() {
arguments.manipulate { _ in
[defaultCommand.name]
if !arguments.hasNext() || arguments.nextIsOption() {
arguments.manipulate { existing in
[defaultCommand.name] + existing
}
}
return try DefaultRouter().parse(commandGroup: commandGroup, arguments: arguments)

View File

@ -13,7 +13,7 @@ public class FileWriter {
public func writeXcodeProject(_ xcodeProject: XcodeProj, to projectPath: Path? = nil) throws {
let projectPath = project.defaultProjectPath
let tempPath = Path.temporary + "XcodeGen_\(Int(NSTimeIntervalSince1970))"
let tempPath = try Path.processUniqueTemporary() + "XcodeGen"
try? tempPath.delete()
if projectPath.exists {
try projectPath.copy(tempPath)

View File

@ -310,8 +310,8 @@ public class PBXProjGenerator {
var targetAttributes: [PBXTarget: [String: Any]] = [:]
let uiTestTargets = pbxProj.nativeTargets.filter { $0.productType == .uiTestBundle }
for uiTestTarget in uiTestTargets {
let testTargets = pbxProj.nativeTargets.filter { $0.productType == .uiTestBundle || $0.productType == .unitTestBundle }
for testTarget in testTargets {
// look up TEST_TARGET_NAME build setting
func testTargetName(_ target: PBXTarget) -> String? {
@ -322,11 +322,10 @@ public class PBXProjGenerator {
.first
}
guard let name = testTargetName(uiTestTarget) else { continue }
guard let name = testTargetName(testTarget) else { continue }
guard let target = self.pbxProj.targets(named: name).first else { continue }
// FIX: Can't set in xcproj 5.0+
targetAttributes[uiTestTarget, default: [:]].merge(["TestTargetID": target])
targetAttributes[testTarget, default: [:]].merge(["TestTargetID": target])
}
func generateTargetAttributes(_ target: ProjectTarget, pbxTarget: PBXTarget) {
@ -498,6 +497,10 @@ public class PBXProjGenerator {
}
case .framework:
let buildPath = Path(dependency.reference).parent().string.quoted
frameworkBuildPaths.insert(buildPath)
// Static libraries can't link or embed dynamic frameworks
guard target.type != .staticLibrary else { break }
let fileReference: PBXFileElement
@ -529,10 +532,9 @@ public class PBXProjGenerator {
)
copyFrameworksReferences.append(embedFile)
}
let buildPath = Path(dependency.reference).parent().string.quoted
frameworkBuildPaths.insert(buildPath)
case .sdk:
// Static libraries can't link or embed dynamic frameworks
guard target.type != .staticLibrary else { break }
var dependencyPath = Path(dependency.reference)
if !dependency.reference.contains("/") {
@ -570,6 +572,7 @@ public class PBXProjGenerator {
targetFrameworkBuildFiles.append(buildFile)
case .carthage:
// Static libraries can't link or embed dynamic frameworks
guard target.type != .staticLibrary else { break }
var platformPath = Path(getCarthageBuildPath(platform: target.platform))
@ -792,11 +795,11 @@ public class PBXProjGenerator {
buildSettings["CODE_SIGN_ENTITLEMENTS"] = entitlements.path
}
// Set INFOPLIST_FILE
if let info = target.info {
buildSettings["INFOPLIST_FILE"] = info.path
} else if !project.targetHasBuildSetting("INFOPLIST_FILE", target: target, config: config) {
if searchForPlist {
// Set INFOPLIST_FILE if not defined in settings
if !project.targetHasBuildSetting("INFOPLIST_FILE", target: target, config: config) {
if let info = target.info {
buildSettings["INFOPLIST_FILE"] = info.path
} else if searchForPlist {
plistPath = getInfoPlist(target.sources)
searchForPlist = false
}
@ -817,18 +820,31 @@ public class PBXProjGenerator {
}
// automatically set test target name
if target.type == .uiTestBundle,
if target.type == .uiTestBundle || target.type == .unitTestBundle,
!project.targetHasBuildSetting("TEST_TARGET_NAME", target: target, config: config) {
for dependency in target.dependencies {
if dependency.type == .target,
let dependencyTarget = project.getTarget(dependency.reference),
dependencyTarget.type == .application {
dependencyTarget.type.isApp {
buildSettings["TEST_TARGET_NAME"] = dependencyTarget.name
break
}
}
}
// automatically set TEST_HOST
if target.type == .unitTestBundle,
!project.targetHasBuildSetting("TEST_HOST", target: target, config: config) {
for dependency in target.dependencies {
if dependency.type == .target,
let dependencyTarget = project.getTarget(dependency.reference),
dependencyTarget.type.isApp {
buildSettings["TEST_HOST"] = "$(BUILT_PRODUCTS_DIR)/\(dependencyTarget.productName).app/\(dependencyTarget.productName)"
break
}
}
}
// objc linkage
if anyDependencyRequiresObjCLinking {
let otherLinkingFlags = "OTHER_LDFLAGS"

View File

@ -183,8 +183,26 @@ class SourceGenerator {
}
if let fileExtension = path.extension {
switch fileExtension {
case "swift", "m", "mm", "cpp", "c", "cc", "S", "xcdatamodeld", "metal": return .sources
case "h", "hh", "hpp", "ipp", "tpp", "hxx", "def": return .headers
case "swift",
"m",
"mm",
"cpp",
"c",
"cc",
"S",
"xcdatamodeld",
"intentdefinition",
"metal",
"mlmodel":
return .sources
case "h",
"hh",
"hpp",
"ipp",
"tpp",
"hxx",
"def":
return .headers
case "modulemap":
guard targetType == .staticLibrary else { return nil }
return .copyFiles(TargetSource.BuildPhase.CopyFilesSettings(
@ -192,10 +210,18 @@ class SourceGenerator {
subpath: "include/$(PRODUCT_NAME)",
phaseOrder: .preCompile
))
case "framework": return .frameworks
case "xpc": return .copyFiles(.xpcServices)
case "xcconfig", "entitlements", "gpx", "lproj", "apns": return nil
default: return .resources
case "framework":
return .frameworks
case "xpc":
return .copyFiles(.xpcServices)
case "xcconfig",
"entitlements",
"gpx",
"lproj",
"apns":
return nil
default:
return .resources
}
}
return nil

View File

@ -1362,6 +1362,9 @@
AT_D40C01B2BAD29EDEA392714DFB69FE8F = {
CUSTOM = value;
};
NT_193BAF154270D1C21E269EDF2A1BD3F6 = {
TestTargetID = NT_BEB0891E36797FE2214A0A9D516D408D;
};
NT_B91A6EACD6F5192FECA2E95FD531D0CA = {
ProvisioningStyle = Automatic;
};
@ -2829,6 +2832,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-iOS-Tests";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_iOS.app/App_iOS";
TEST_TARGET_NAME = App_iOS;
};
name = "Production Debug";
};
@ -3119,6 +3124,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-iOS-Tests";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_iOS.app/App_iOS";
TEST_TARGET_NAME = App_iOS;
};
name = "Staging Release";
};
@ -3359,6 +3366,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-iOS-Tests";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_iOS.app/App_iOS";
TEST_TARGET_NAME = App_iOS;
};
name = "Test Release";
};
@ -3843,6 +3852,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-iOS-Tests";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_iOS.app/App_iOS";
TEST_TARGET_NAME = App_iOS;
};
name = "Test Debug";
};
@ -4472,6 +4483,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-iOS-Tests";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_iOS.app/App_iOS";
TEST_TARGET_NAME = App_iOS;
};
name = "Production Release";
};
@ -4488,6 +4501,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.project.App-iOS-Tests";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/App_iOS.app/App_iOS";
TEST_TARGET_NAME = App_iOS;
};
name = "Staging Debug";
};

View File

@ -882,6 +882,24 @@ class ProjectGeneratorTests: XCTestCase {
try expect(NSDictionary(dictionary: expectedInfoPlist).isEqual(to: infoPlist)).beTrue()
}
$0.it("info doesn't override info.plist setting") {
let predefinedPlistPath = "Predefined.plist"
// generate plist
let plist = Plist(path: "Info.plist", attributes: ["UISupportedInterfaceOrientations": ["UIInterfaceOrientationPortrait", "UIInterfaceOrientationLandscapeLeft"]])
let tempPath = Path.temporary + "info"
// create project with a predefined plist
let project = Project(basePath: tempPath, name: "", targets: [Target(name: "", type: .application, platform: .iOS, settings: Settings(buildSettings: ["INFOPLIST_FILE": predefinedPlistPath]), info: plist)])
let pbxProject = try project.generatePbxProj()
let writer = FileWriter(project: project)
try writer.writePlists()
guard let targetConfig = pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first else {
throw failure("Couldn't find Target config")
}
// generated plist should not be in buildsettings
try expect(targetConfig.buildSettings["INFOPLIST_FILE"] as? String) == predefinedPlistPath
}
}
}
}

View File

@ -435,7 +435,9 @@ class SourceGeneratorTests: XCTestCase {
- file.123
- file.xcassets
- file.metal
- file.mlmodel
- Info.plist
- Intent.intentdefinition
"""
try createDirectories(directories)
@ -483,6 +485,8 @@ class SourceGeneratorTests: XCTestCase {
try pbxProj.expectFile(paths: ["C", "file.123"], buildPhase: .resources)
try pbxProj.expectFile(paths: ["C", "Info.plist"], buildPhase: .none)
try pbxProj.expectFile(paths: ["C", "file.metal"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["C", "file.mlmodel"], buildPhase: .sources)
try pbxProj.expectFile(paths: ["C", "Intent.intentdefinition"], buildPhase: .sources)
}
$0.it("duplicate TargetSource is included once in sources build phase") {