mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2024-12-11 07:16:40 +03:00
Merge master into lockfile
This commit is contained in:
commit
f061c03e6a
19
CHANGELOG.md
19
CHANGELOG.md
@ -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
|
||||
|
||||
|
@ -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`
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
};
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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") {
|
||||
|
Loading…
Reference in New Issue
Block a user