mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2026-03-18 20:02:25 +00:00
Merge branch 'master' into disable_main_thread_checker
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
name: CI
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
swift_5:
|
||||
runs-on: macos-latest
|
||||
name: Swift 5.0
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Info
|
||||
run: swift --version; swift package --version
|
||||
- name: Resolve
|
||||
run: swift package resolve
|
||||
- name: Build
|
||||
run: swift build
|
||||
- name: Test
|
||||
run: swift test
|
||||
- name: Gen fixtures
|
||||
run: scripts/gen-fixtures.sh
|
||||
- name: Check fixtures
|
||||
run: scripts/diff-fixtures.sh
|
||||
- name: Build fixtures
|
||||
run: scripts/build-fixtures.sh
|
||||
- name: Build release
|
||||
run: make build
|
||||
# swift_5.1:
|
||||
# runs-on: macos-latest
|
||||
# name: Swift 5.1
|
||||
# steps:
|
||||
# - uses: actions/checkout@master
|
||||
# - name: Xcode version
|
||||
# run: sudo xcode-select -s /Applications/Xcode_11_beta.app
|
||||
# - name: Info
|
||||
# run: swift --version; swift package --version
|
||||
# - name: Resolve
|
||||
# run: swift package resolve
|
||||
# - name: Build
|
||||
# run: swift build
|
||||
# - name: Test
|
||||
# run: swift test
|
||||
# - name: Gen fixtures
|
||||
# run: scripts/gen-fixtures.sh
|
||||
# - name: Check fixtures
|
||||
# run: scripts/diff-fixtures.sh
|
||||
# - name: Build fixtures
|
||||
# run: scripts/build-fixtures.sh
|
||||
# - name: Build release
|
||||
# run: make build
|
||||
|
||||
+7
-1
@@ -3,9 +3,15 @@
|
||||
## Next Version
|
||||
|
||||
#### Added
|
||||
|
||||
- Added ability to disable main thread checker on Run and Test schemes and TargetSchemes [#601](https://github.com/yonaskolb/XcodeGen/pull/601) @wag-miles
|
||||
|
||||
#### Fixed
|
||||
- Fixed included specs that were referenced multiple times from duplicating content [#599](https://github.com/yonaskolb/XcodeGen/pull/599) @haritowa
|
||||
- Fixed `.orig` files being added to the project [#627](https://github.com/yonaskolb/XcodeGen/pull/627) @keith
|
||||
|
||||
#### Changed
|
||||
- Allow linking of dependencies into static libraries when `link` is set to true [#635](https://github.com/yonaskolb/XcodeGen/pull/635) @kateinoigakukun
|
||||
|
||||
## 2.6.0
|
||||
|
||||
#### Added
|
||||
|
||||
+17
@@ -1,6 +1,7 @@
|
||||
# Frequently asked questions
|
||||
- [Can I still check in my project](#can-i-still-check-in-my-project)
|
||||
- [Can I use CocoaPods](#can-i-use-cocoapods)
|
||||
- [Can I use Crashlytics](#can-i-use-crashlytics)
|
||||
- [How do I setup code signing](#how-do-i-setup-code-signing)
|
||||
|
||||
## Can I still check in my project
|
||||
@@ -15,6 +16,22 @@ For now you can always add xcodegen as a git `post-checkout` hook.
|
||||
## Can I use CocoaPods
|
||||
Yes, simply generate your project and then run `pod install` which will integrate with your project and create a workspace.
|
||||
|
||||
## Can I use Crashlytics
|
||||
Yes, but you need to use a little trick when using CocoaPods. Add this script in your `Podfile`:
|
||||
|
||||
```ruby:Podfile
|
||||
// Your dependencies
|
||||
pod 'Fabric'
|
||||
pod 'Crashlytics'
|
||||
|
||||
script_phase :name => 'Run Fabric',
|
||||
:script => '"${PODS_ROOT}/Fabric/run"'
|
||||
:input_files => ['$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)']
|
||||
|
||||
```
|
||||
|
||||
This script will be added after `[CP] Embed Pods Frameworks.`
|
||||
|
||||
## How do I setup code signing
|
||||
|
||||
At the moment there are no special options for code signing in XcodeGen, and this must be configured via regular build settings. For code signing to work, you need to tell Xcode which development team to use. This requires setting the `DEVELOPMENT_TEAM` and possibly `CODE_SIGN_STYLE` build settings. See [Configuring build settings](Usage.md#configuring-build-settings) for how to do that
|
||||
|
||||
@@ -81,7 +81,7 @@ mint install yonaskolb/xcodegen
|
||||
```shell
|
||||
git clone https://github.com/yonaskolb/XcodeGen.git
|
||||
cd XcodeGen
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
### Homebrew
|
||||
|
||||
@@ -8,6 +8,8 @@ public struct SpecFile {
|
||||
public let jsonDictionary: JSONDictionary
|
||||
public let subSpecs: [SpecFile]
|
||||
|
||||
private let filename: String
|
||||
|
||||
fileprivate struct Include {
|
||||
let path: Path
|
||||
let relativePaths: Bool
|
||||
@@ -42,11 +44,12 @@ public struct SpecFile {
|
||||
try self.init(filename: path.lastComponent, basePath: path.parent())
|
||||
}
|
||||
|
||||
public init(jsonDictionary: JSONDictionary, basePath: Path = "", relativePath: Path = "", subSpecs: [SpecFile] = []) {
|
||||
public init(filename: String, jsonDictionary: JSONDictionary, basePath: Path = "", relativePath: Path = "", subSpecs: [SpecFile] = []) {
|
||||
self.basePath = basePath
|
||||
self.relativePath = relativePath
|
||||
self.jsonDictionary = jsonDictionary
|
||||
self.subSpecs = subSpecs
|
||||
self.filename = filename
|
||||
}
|
||||
|
||||
fileprivate init(include: Include, basePath: Path, relativePath: Path) throws {
|
||||
@@ -65,7 +68,7 @@ public struct SpecFile {
|
||||
try SpecFile(include: include, basePath: basePath, relativePath: relativePath)
|
||||
}
|
||||
|
||||
self.init(jsonDictionary: jsonDictionary, basePath: basePath, relativePath: relativePath, subSpecs: subSpecs)
|
||||
self.init(filename: filename, jsonDictionary: jsonDictionary, basePath: basePath, relativePath: relativePath, subSpecs: subSpecs)
|
||||
}
|
||||
|
||||
static func loadDictionary(path: Path) throws -> JSONDictionary {
|
||||
@@ -83,17 +86,36 @@ public struct SpecFile {
|
||||
}
|
||||
|
||||
public func resolvedDictionary(variables: [String: String] = [:]) -> JSONDictionary {
|
||||
var resolvedSpec = resolvingPaths().mergedDictionary()
|
||||
let resolvedDictionary = resolvedDictionaryWithUniqueTargets()
|
||||
return substitute(variables: variables, in: resolvedDictionary)
|
||||
}
|
||||
|
||||
private func resolvedDictionaryWithUniqueTargets() -> JSONDictionary {
|
||||
let resolvedSpec = resolvingPaths()
|
||||
|
||||
var value = Set<String>()
|
||||
return resolvedSpec.mergedDictionary(set: &value)
|
||||
}
|
||||
|
||||
private func substitute(variables: [String: String], in mergedDictionary: JSONDictionary) -> JSONDictionary {
|
||||
var resolvedSpec = mergedDictionary
|
||||
|
||||
for (key, value) in variables {
|
||||
resolvedSpec = resolvedSpec.replaceString("${\(key)}", with: value)
|
||||
}
|
||||
|
||||
return resolvedSpec
|
||||
}
|
||||
|
||||
func mergedDictionary() -> JSONDictionary {
|
||||
|
||||
func mergedDictionary(set mergedTargets: inout Set<String>) -> JSONDictionary {
|
||||
let name = (basePath + relativePath + Path(filename)).description
|
||||
|
||||
guard !mergedTargets.contains(name) else { return [:] }
|
||||
mergedTargets.insert(name)
|
||||
|
||||
return jsonDictionary.merged(onto:
|
||||
subSpecs
|
||||
.map { $0.mergedDictionary() }
|
||||
.map { $0.mergedDictionary(set: &mergedTargets) }
|
||||
.reduce([:]) { $1.merged(onto: $0) })
|
||||
}
|
||||
|
||||
@@ -105,6 +127,7 @@ public struct SpecFile {
|
||||
|
||||
let jsonDictionary = Project.pathProperties.resolvingPaths(in: self.jsonDictionary, relativeTo: relativePath)
|
||||
return SpecFile(
|
||||
filename: filename,
|
||||
jsonDictionary: jsonDictionary,
|
||||
relativePath: self.relativePath,
|
||||
subSpecs: subSpecs.map { $0.resolvingPaths(relativeTo: relativePath) }
|
||||
|
||||
@@ -504,9 +504,6 @@ public class PBXProjGenerator {
|
||||
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
|
||||
if dependency.implicit {
|
||||
fileReference = sourceGenerator.getFileReference(
|
||||
@@ -521,7 +518,7 @@ public class PBXProjGenerator {
|
||||
)
|
||||
}
|
||||
|
||||
if dependency.link ?? true {
|
||||
if dependency.link ?? (target.type != .staticLibrary) {
|
||||
let buildFile = addObject(
|
||||
PBXBuildFile(file: fileReference, settings: getDependencyFrameworkSettings(dependency: dependency))
|
||||
)
|
||||
@@ -540,8 +537,6 @@ public class PBXProjGenerator {
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
}
|
||||
case .sdk(let root):
|
||||
// Static libraries can't link or embed dynamic frameworks
|
||||
guard target.type != .staticLibrary else { break }
|
||||
|
||||
var dependencyPath = Path(dependency.reference)
|
||||
if !dependency.reference.contains("/") {
|
||||
@@ -589,8 +584,6 @@ public class PBXProjGenerator {
|
||||
let allDependencies = findFrameworks
|
||||
? carthageResolver.relatedDependencies(for: dependency, in: target.platform) : [dependency]
|
||||
allDependencies.forEach { dependency in
|
||||
// Static libraries can't link or embed dynamic frameworks
|
||||
guard target.type != .staticLibrary else { return }
|
||||
|
||||
var platformPath = Path(carthageResolver.buildPath(for: target.platform))
|
||||
var frameworkPath = platformPath + dependency.reference
|
||||
@@ -601,7 +594,7 @@ public class PBXProjGenerator {
|
||||
|
||||
self.carthageFrameworksByPlatform[target.platform.carthageName, default: []].insert(fileReference)
|
||||
|
||||
if dependency.link ?? true {
|
||||
if dependency.link ?? (target.type != .staticLibrary) {
|
||||
let buildFile = self.addObject(
|
||||
PBXBuildFile(file: fileReference, settings: getDependencyFrameworkSettings(dependency: dependency))
|
||||
)
|
||||
@@ -613,7 +606,6 @@ public class PBXProjGenerator {
|
||||
}
|
||||
|
||||
for dependency in carthageDependencies {
|
||||
guard target.type != .staticLibrary else { break }
|
||||
|
||||
let embed = dependency.embed ?? target.shouldEmbedCarthageDependencies
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ class SourceGenerator {
|
||||
var defaultExcludedFiles = [
|
||||
".DS_Store",
|
||||
]
|
||||
private let defaultExcludedExtensions = [
|
||||
"orig",
|
||||
]
|
||||
|
||||
private(set) var knownRegions: Set<String> = []
|
||||
|
||||
@@ -317,6 +320,7 @@ class SourceGenerator {
|
||||
/// Checks whether the path is not in any default or TargetSource excludes
|
||||
func isIncludedPath(_ path: Path) -> Bool {
|
||||
return !defaultExcludedFiles.contains(where: { path.lastComponent.contains($0) })
|
||||
&& !(path.extension.map(defaultExcludedExtensions.contains) ?? false)
|
||||
&& !targetSourceExcludePaths.contains(path)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
name: DuplicatedImportRoot
|
||||
fileGroups:
|
||||
- First
|
||||
- Second
|
||||
targetTemplates:
|
||||
IncludedTemplate:
|
||||
type: application
|
||||
platform: iOS
|
||||
sources:
|
||||
- template
|
||||
preBuildScripts:
|
||||
- script: swiftlint
|
||||
name: Swiftlint
|
||||
@@ -0,0 +1,9 @@
|
||||
include:
|
||||
- duplicated_import_transitive.yml
|
||||
- duplicated_import_root.yml
|
||||
- duplicated_import_root.yml
|
||||
name: DuplicatedImportDependent
|
||||
targets:
|
||||
IncludedTarget:
|
||||
templates:
|
||||
- IncludedTemplate
|
||||
@@ -0,0 +1,3 @@
|
||||
include:
|
||||
- duplicated_import_root.yml
|
||||
name: DuplicatedImportTransitive
|
||||
@@ -339,6 +339,8 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
// embed: false
|
||||
// iOSFrameworkZ:
|
||||
// dependencies: []
|
||||
// iOSFrameworkX:
|
||||
// dependencies: []
|
||||
// StaticLibrary:
|
||||
// dependencies:
|
||||
// - target: iOSFrameworkZ
|
||||
@@ -430,18 +432,33 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
expectedLinkedFiles[iosFrameworkZ.name] = Set()
|
||||
expectedEmbeddedFrameworks[iosFrameworkZ.name] = Set()
|
||||
|
||||
let iosFrameworkX = Target(
|
||||
name: "iOSFrameworkX",
|
||||
type: .framework,
|
||||
platform: .iOS,
|
||||
dependencies: []
|
||||
)
|
||||
expectedResourceFiles[iosFrameworkX.name] = Set()
|
||||
expectedLinkedFiles[iosFrameworkX.name] = Set()
|
||||
expectedEmbeddedFrameworks[iosFrameworkX.name] = Set()
|
||||
|
||||
let staticLibrary = Target(
|
||||
name: "StaticLibrary",
|
||||
type: .staticLibrary,
|
||||
platform: .iOS,
|
||||
dependencies: [
|
||||
Dependency(type: .target, reference: iosFrameworkZ.name),
|
||||
Dependency(type: .framework, reference: "FrameworkZ.framework"),
|
||||
Dependency(type: .target, reference: iosFrameworkZ.name, link: true),
|
||||
Dependency(type: .framework, reference: "FrameworkZ.framework", link: true),
|
||||
Dependency(type: .target, reference: iosFrameworkX.name/*, link: false */),
|
||||
Dependency(type: .framework, reference: "FrameworkX.framework"/*, link: false */),
|
||||
Dependency(type: .carthage(findFrameworks: false), reference: "CarthageZ"),
|
||||
]
|
||||
)
|
||||
expectedResourceFiles[staticLibrary.name] = Set()
|
||||
expectedLinkedFiles[staticLibrary.name] = Set([])
|
||||
expectedLinkedFiles[staticLibrary.name] = Set([
|
||||
iosFrameworkZ.filename,
|
||||
"FrameworkZ.framework",
|
||||
])
|
||||
expectedEmbeddedFrameworks[staticLibrary.name] = Set()
|
||||
|
||||
let resourceBundle = Target(
|
||||
@@ -471,7 +488,9 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
expectedLinkedFiles[iosFrameworkA.name] = Set([
|
||||
"FrameworkC.framework",
|
||||
iosFrameworkZ.filename,
|
||||
iosFrameworkX.filename,
|
||||
"FrameworkZ.framework",
|
||||
"FrameworkX.framework",
|
||||
"CarthageZ.framework",
|
||||
"CarthageA.framework",
|
||||
"CarthageB.framework",
|
||||
@@ -496,7 +515,9 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
expectedLinkedFiles[iosFrameworkB.name] = Set([
|
||||
iosFrameworkA.filename,
|
||||
iosFrameworkZ.filename,
|
||||
iosFrameworkX.filename,
|
||||
"FrameworkZ.framework",
|
||||
"FrameworkX.framework",
|
||||
"CarthageZ.framework",
|
||||
"FrameworkC.framework",
|
||||
"FrameworkD.framework",
|
||||
@@ -528,7 +549,9 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
iosFrameworkA.filename,
|
||||
staticLibrary.filename,
|
||||
iosFrameworkZ.filename,
|
||||
iosFrameworkX.filename,
|
||||
"FrameworkZ.framework",
|
||||
"FrameworkX.framework",
|
||||
"CarthageZ.framework",
|
||||
"FrameworkC.framework",
|
||||
iosFrameworkB.filename,
|
||||
@@ -539,7 +562,9 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
expectedEmbeddedFrameworks[appTest.name] = Set([
|
||||
iosFrameworkA.filename,
|
||||
iosFrameworkZ.filename,
|
||||
iosFrameworkX.filename,
|
||||
"FrameworkZ.framework",
|
||||
"FrameworkX.framework",
|
||||
"FrameworkC.framework",
|
||||
iosFrameworkB.filename,
|
||||
"FrameworkD.framework",
|
||||
@@ -572,7 +597,7 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
"NotificationCenter.framework",
|
||||
])
|
||||
|
||||
let targets = [app, iosFrameworkZ, staticLibrary, resourceBundle, iosFrameworkA, iosFrameworkB, appTest, appTestWithoutTransitive, stickerPack]
|
||||
let targets = [app, iosFrameworkZ, iosFrameworkX, staticLibrary, resourceBundle, iosFrameworkA, iosFrameworkB, appTest, appTestWithoutTransitive, stickerPack]
|
||||
|
||||
let project = Project(
|
||||
name: "test",
|
||||
|
||||
@@ -312,6 +312,24 @@ class SourceGeneratorTests: XCTestCase {
|
||||
try test(generateEmptyDirectories: true)
|
||||
}
|
||||
|
||||
$0.it("excludes certain ignored files") {
|
||||
let directories = """
|
||||
Sources:
|
||||
A:
|
||||
- a.swift
|
||||
- .DS_Store
|
||||
- a.swift.orig
|
||||
"""
|
||||
try createDirectories(directories)
|
||||
|
||||
let target = Target(name: "Test", type: .application, platform: .iOS, sources: [TargetSource(path: "Sources")])
|
||||
let project = Project(basePath: directoryPath, name: "Test", targets: [target])
|
||||
let pbxProj = try project.generatePbxProj()
|
||||
try pbxProj.expectFile(paths: ["Sources", "A", "a.swift"])
|
||||
try pbxProj.expectFileMissing(paths: ["Sources", "A", ".DS_Store"])
|
||||
try pbxProj.expectFileMissing(paths: ["Sources", "A", "a.swift.orig"])
|
||||
}
|
||||
|
||||
$0.it("generates file sources") {
|
||||
let directories = """
|
||||
Sources:
|
||||
|
||||
@@ -9,6 +9,21 @@ import Yams
|
||||
|
||||
class SpecLoadingTests: XCTestCase {
|
||||
|
||||
func testSpecLoaderDuplicateImports() {
|
||||
describe {
|
||||
$0.it("merges each file only once") {
|
||||
let path = fixturePath + "duplicated_include/duplicated_import_sut.yml"
|
||||
let project = try loadSpec(path: path)
|
||||
|
||||
try expect(project.fileGroups) == ["First", "Second"]
|
||||
|
||||
let sutTarget = project.targets.first
|
||||
try expect(sutTarget?.sources) == [TargetSource(path: "template")]
|
||||
try expect(sutTarget?.preBuildScripts) == [BuildScript(script: .script("swiftlint"), name: "Swiftlint")]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testSpecLoader() {
|
||||
describe {
|
||||
$0.it("merges includes") {
|
||||
|
||||
Reference in New Issue
Block a user