mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2024-08-16 08:10:43 +03:00
Compare commits
5 Commits
e015abb433
...
64c8a5802a
Author | SHA1 | Date | |
---|---|---|---|
|
64c8a5802a | ||
|
f51719ce29 | ||
|
1b0720d139 | ||
|
576739bcb5 | ||
|
f0e1db79e0 |
10
CHANGELOG.md
10
CHANGELOG.md
@ -2,6 +2,16 @@
|
||||
|
||||
## Next Version
|
||||
|
||||
## 2.41.0
|
||||
|
||||
### Added
|
||||
|
||||
- Added `xcodegen cache` command that writes the cache. Useful for `post-commit` git hook integration #1476 @yonaskolb
|
||||
|
||||
### Changed
|
||||
|
||||
- Include folders in file sorting #1466 @jflan-dd
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `supportedDestinations` validation when it contains watchOS for multiplatform apps. #1470 @tatsuky
|
||||
|
10
Docs/FAQ.md
10
Docs/FAQ.md
@ -9,10 +9,14 @@ Absolutely. You will get the most out of XcodeGen by adding your project to your
|
||||
>Note that you can run `xcodegen` as a step in your build process on CI.
|
||||
|
||||
## What happens when I switch branches
|
||||
If files were added or removed in the new checkout you will most likely need to run `xcodegen` again so that your project will reference all your files. Unfortunately this is a manual step at the moment, but in the future this could be automated.
|
||||
If files were added or removed in the new checkout you will most likely need to run `xcodegen` again so that your project will reference all your files.
|
||||
|
||||
For now you can always add xcodegen as a git `post-checkout` hook.
|
||||
It's recommended to use `--use-cache` so that the project is not needlessly generated.
|
||||
It's recommended to set up some [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) to automate the process:
|
||||
- run `xcodegen generate --use-cache` on the following hooks. This will make sure the project is up to date when checking out, merging and rebasing
|
||||
- `post-checkout`
|
||||
- `post-rewrite`
|
||||
- `post-merge`
|
||||
- run `xcodegen cache` on `pre-commit`. This will make sure that when switching branches the cache will be updated in case you made local changes, or are ammending a commit that added a new file.
|
||||
|
||||
## Can I use CocoaPods
|
||||
Yes, you will just need to run `pod install` after the project is generated to integrate Cocoapods changes.
|
||||
|
53
Docs/Recipes/ios-alternate-app-icons.md
Normal file
53
Docs/Recipes/ios-alternate-app-icons.md
Normal file
@ -0,0 +1,53 @@
|
||||
# (iOS) Alternate app icons
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
Adds alternate app icons to include in the built product.
|
||||
|
||||
## File structure
|
||||
|
||||
```diff
|
||||
.
|
||||
├── MyApp
|
||||
│ ├── AppDelegate.swift
|
||||
│ ├── Assets.xcassets
|
||||
│ │ ├── AppIcon.appiconset
|
||||
│ │ │ ├── AppIcon.png
|
||||
| | | └── Contents.json
|
||||
+│ │ ├── AppIcon2.appiconset
|
||||
+│ │ │ ├── AppIcon.png
|
||||
+| | | └── Contents.json
|
||||
+│ │ ├── AppIcon3.appiconset
|
||||
+│ │ │ ├── AppIcon.png
|
||||
+| | | └── Contents.json
|
||||
│ │ └── Contents.json
|
||||
│ ├── LaunchScreen.storyboard
|
||||
│ └── RootViewController.swift
|
||||
└── project.yml
|
||||
```
|
||||
|
||||
## project.yml
|
||||
|
||||
```diff
|
||||
name: MyApp
|
||||
targets:
|
||||
MyApp:
|
||||
type: application
|
||||
platform: iOS
|
||||
deploymentTarget: 12.0
|
||||
settings:
|
||||
TARGETED_DEVICE_FAMILY: 1
|
||||
MARKETING_VERSION: 1.0
|
||||
CURRENT_PROJECT_VERSION: 1
|
||||
DEVELOPMENT_TEAM: MYTEAMID
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.mycompany.myapp
|
||||
GENERATE_INFOPLIST_FILE: YES
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents: YES
|
||||
INFOPLIST_KEY_UILaunchStoryboardName: LaunchScreen.storyboard
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait
|
||||
+ ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS: YES
|
||||
+ ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES: AppIcon2 AppIcon3
|
||||
sources:
|
||||
- MyApp
|
||||
```
|
72
Docs/Recipes/ios-environments.md
Normal file
72
Docs/Recipes/ios-environments.md
Normal file
@ -0,0 +1,72 @@
|
||||
# (iOS) Environments
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
Best way to setup Development, Testing and Production environments.
|
||||
|
||||
## File structure
|
||||
|
||||
```diff
|
||||
.
|
||||
├── MyApp
|
||||
│ ├── AppDelegate.swift
|
||||
│ ├── Assets.xcassets
|
||||
│ │ ├── AppIcon.appiconset
|
||||
│ │ │ ├── AppIcon.png
|
||||
| | | └── Contents.json
|
||||
│ │ └── Contents.json
|
||||
│ ├── LaunchScreen.storyboard
|
||||
│ └── RootViewController.swift
|
||||
└── project.yml
|
||||
```
|
||||
|
||||
## project.yml
|
||||
|
||||
```diff
|
||||
name: MyApp
|
||||
+configs:
|
||||
+ Dev Debug: debug
|
||||
+ Test Debug: debug
|
||||
+ Prod Debug: debug
|
||||
+ Dev Release: release
|
||||
+ Test Release: release
|
||||
+ Prod Release: release
|
||||
+settings:
|
||||
+ configs:
|
||||
+ Dev Debug:
|
||||
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS: DEBUG DEV
|
||||
+ Test Debug:
|
||||
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS: DEBUG TEST
|
||||
+ Prod Debug:
|
||||
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS: DEBUG PROD
|
||||
+ Dev Release:
|
||||
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS: DEV
|
||||
+ Test Release:
|
||||
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS: TEST
|
||||
+ Prod Release:
|
||||
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS: PROD
|
||||
targets:
|
||||
MyApp:
|
||||
type: application
|
||||
platform: iOS
|
||||
deploymentTarget: 12.0
|
||||
settings:
|
||||
TARGETED_DEVICE_FAMILY: 1
|
||||
MARKETING_VERSION: 1.0
|
||||
CURRENT_PROJECT_VERSION: 1
|
||||
DEVELOPMENT_TEAM: MYTEAMID
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.mycompany.myapp
|
||||
GENERATE_INFOPLIST_FILE: YES
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents: YES
|
||||
INFOPLIST_KEY_UILaunchStoryboardName: LaunchScreen.storyboard
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait
|
||||
sources:
|
||||
- MyApp
|
||||
+ scheme:
|
||||
+ configVariants:
|
||||
+ - Dev
|
||||
+ - Test
|
||||
+ - Prod
|
||||
```
|
||||
|
90
Docs/Recipes/ios-playground.md
Normal file
90
Docs/Recipes/ios-playground.md
Normal file
@ -0,0 +1,90 @@
|
||||
# (iOS) Playground
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
An alternative to XCode Playground.
|
||||
|
||||
Example of Source.swift:
|
||||
|
||||
```swift
|
||||
import UIKit
|
||||
|
||||
@main
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
var greeting = "Hello, playground"
|
||||
print(greeting)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Another example with UI:
|
||||
|
||||
```swift
|
||||
import UIKit
|
||||
|
||||
@main
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
let window = UIWindow()
|
||||
self.window = window
|
||||
|
||||
let rootViewController = RootViewController(nibName: nil, bundle: nil)
|
||||
window.rootViewController = rootViewController
|
||||
window.makeKeyAndVisible()
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class RootViewController: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## File structure
|
||||
|
||||
```diff
|
||||
.
|
||||
├── Source.swift
|
||||
└── project.yml
|
||||
```
|
||||
|
||||
## project.yml
|
||||
|
||||
```diff
|
||||
name: MyApp
|
||||
targets:
|
||||
MyApp:
|
||||
type: application
|
||||
platform: iOS
|
||||
deploymentTarget: 12.0
|
||||
settings:
|
||||
TARGETED_DEVICE_FAMILY: 1
|
||||
MARKETING_VERSION: 1.0
|
||||
CURRENT_PROJECT_VERSION: 1
|
||||
DEVELOPMENT_TEAM: MYTEAMID
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.mycompany.myapp
|
||||
GENERATE_INFOPLIST_FILE: YES
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents: YES
|
||||
- INFOPLIST_KEY_UILaunchStoryboardName: LaunchScreen.storyboard
|
||||
+ INFOPLIST_KEY_UILaunchScreen_Generation: YES
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait
|
||||
sources:
|
||||
- Source.swift
|
||||
```
|
58
Docs/Recipes/ios-ui-testing-bundle.md
Normal file
58
Docs/Recipes/ios-ui-testing-bundle.md
Normal file
@ -0,0 +1,58 @@
|
||||
# (iOS) UI Testing Bundle
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
Adds a user interface testing bundle that uses the XCTest framework.
|
||||
|
||||
## File structure
|
||||
|
||||
```diff
|
||||
.
|
||||
├── MyApp
|
||||
│ ├── AppDelegate.swift
|
||||
│ ├── Assets.xcassets
|
||||
│ │ ├── AppIcon.appiconset
|
||||
│ │ │ ├── AppIcon.png
|
||||
| | | └── Contents.json
|
||||
│ │ └── Contents.json
|
||||
│ ├── LaunchScreen.storyboard
|
||||
│ └── RootViewController.swift
|
||||
+├── MyAppUITests
|
||||
+│ └── SomeUITests.swift
|
||||
└── project.yml
|
||||
```
|
||||
|
||||
## project.yml
|
||||
|
||||
```diff
|
||||
name: MyApp
|
||||
targets:
|
||||
MyApp:
|
||||
type: application
|
||||
platform: iOS
|
||||
deploymentTarget: 12.0
|
||||
settings:
|
||||
TARGETED_DEVICE_FAMILY: 1
|
||||
MARKETING_VERSION: 1.0
|
||||
CURRENT_PROJECT_VERSION: 1
|
||||
DEVELOPMENT_TEAM: MYTEAMID
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.mycompany.myapp
|
||||
GENERATE_INFOPLIST_FILE: YES
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents: YES
|
||||
INFOPLIST_KEY_UILaunchStoryboardName: LaunchScreen.storyboard
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait
|
||||
sources:
|
||||
- MyApp
|
||||
+ MyAppUITests:
|
||||
+ type: bundle.ui-testing
|
||||
+ platform: iOS
|
||||
+ settings:
|
||||
+ DEVELOPMENT_TEAM: MYTEAMID
|
||||
+ PRODUCT_BUNDLE_IDENTIFIER: com.company.myappuitests
|
||||
+ GENERATE_INFOPLIST_FILE: YES
|
||||
+ sources:
|
||||
+ - MyAppUITests
|
||||
+ dependencies:
|
||||
+ - target: MyApp
|
||||
```
|
58
Docs/Recipes/ios-unit-testing-bundle.md
Normal file
58
Docs/Recipes/ios-unit-testing-bundle.md
Normal file
@ -0,0 +1,58 @@
|
||||
# (iOS) Unit Testing Bundle
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
Adds a unit test bundle that uses the XCTest framework.
|
||||
|
||||
## File structure
|
||||
|
||||
```diff
|
||||
.
|
||||
├── MyApp
|
||||
│ ├── AppDelegate.swift
|
||||
│ ├── Assets.xcassets
|
||||
│ │ ├── AppIcon.appiconset
|
||||
│ │ │ ├── AppIcon.png
|
||||
| | | └── Contents.json
|
||||
│ │ └── Contents.json
|
||||
│ ├── LaunchScreen.storyboard
|
||||
│ └── RootViewController.swift
|
||||
+├── MyAppTests
|
||||
+│ └── SomeTests.swift
|
||||
└── project.yml
|
||||
```
|
||||
|
||||
## project.yml
|
||||
|
||||
```diff
|
||||
name: MyApp
|
||||
targets:
|
||||
MyApp:
|
||||
type: application
|
||||
platform: iOS
|
||||
deploymentTarget: 12.0
|
||||
settings:
|
||||
TARGETED_DEVICE_FAMILY: 1
|
||||
MARKETING_VERSION: 1.0
|
||||
CURRENT_PROJECT_VERSION: 1
|
||||
DEVELOPMENT_TEAM: MYTEAMID
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.mycompany.myapp
|
||||
GENERATE_INFOPLIST_FILE: YES
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents: YES
|
||||
INFOPLIST_KEY_UILaunchStoryboardName: LaunchScreen.storyboard
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations: UIInterfaceOrientationPortrait
|
||||
sources:
|
||||
- MyApp
|
||||
+ MyAppTests:
|
||||
+ type: bundle.unit-test
|
||||
+ platform: iOS
|
||||
+ settings:
|
||||
+ DEVELOPMENT_TEAM: MYTEAMID
|
||||
+ PRODUCT_BUNDLE_IDENTIFIER: com.company.myapptests
|
||||
+ GENERATE_INFOPLIST_FILE: YES
|
||||
+ sources:
|
||||
+ - MyAppTests
|
||||
+ dependencies:
|
||||
+ - target: MyApp
|
||||
```
|
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
||||
TOOL_NAME = XcodeGen
|
||||
export EXECUTABLE_NAME = xcodegen
|
||||
VERSION = 2.40.1
|
||||
VERSION = 2.41.0
|
||||
|
||||
PREFIX = /usr/local
|
||||
INSTALL_PATH = $(PREFIX)/bin/$(EXECUTABLE_NAME)
|
||||
|
@ -113,7 +113,7 @@ swift run xcodegen
|
||||
Add the following to your Package.swift file's dependencies:
|
||||
|
||||
```swift
|
||||
.package(url: "https://github.com/yonaskolb/XcodeGen.git", from: "2.40.1"),
|
||||
.package(url: "https://github.com/yonaskolb/XcodeGen.git", from: "2.41.0"),
|
||||
```
|
||||
|
||||
And then import wherever needed: `import XcodeGenKit`
|
||||
|
@ -3,6 +3,6 @@ import ProjectSpec
|
||||
import XcodeGenCLI
|
||||
import Version
|
||||
|
||||
let version = Version("2.40.1")
|
||||
let version = Version("2.41.0")
|
||||
let cli = XcodeGenCLI(version: version)
|
||||
cli.execute()
|
||||
|
44
Sources/XcodeGenCLI/Commands/CacheCommand.swift
Normal file
44
Sources/XcodeGenCLI/Commands/CacheCommand.swift
Normal file
@ -0,0 +1,44 @@
|
||||
import Foundation
|
||||
import PathKit
|
||||
import ProjectSpec
|
||||
import SwiftCLI
|
||||
import XcodeGenKit
|
||||
import XcodeProj
|
||||
import Version
|
||||
|
||||
class CacheCommand: ProjectCommand {
|
||||
|
||||
@Key("--cache-path", description: "Where the cache file will be loaded from and save to. Defaults to ~/.xcodegen/cache/{SPEC_PATH_HASH}")
|
||||
var cacheFilePath: Path?
|
||||
|
||||
init(version: Version) {
|
||||
super.init(version: version,
|
||||
name: "cache",
|
||||
shortDescription: "Write the project cache")
|
||||
}
|
||||
|
||||
override func execute(specLoader: SpecLoader, projectSpecPath: Path, project: Project) throws {
|
||||
|
||||
let cacheFilePath = self.cacheFilePath ?? Path("~/.xcodegen/cache/\(projectSpecPath.absolute().string.md5)").absolute()
|
||||
|
||||
var cacheFile: CacheFile?
|
||||
|
||||
// generate cache
|
||||
do {
|
||||
cacheFile = try specLoader.generateCacheFile()
|
||||
} catch {
|
||||
throw GenerationError.projectSpecParsingError(error)
|
||||
}
|
||||
|
||||
// write cache
|
||||
if let cacheFile = cacheFile {
|
||||
do {
|
||||
try cacheFilePath.parent().mkpath()
|
||||
try cacheFilePath.write(cacheFile.string)
|
||||
success("Wrote cache to \(cacheFilePath)")
|
||||
} catch {
|
||||
info("Failed to write cache: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ class DumpCommand: ProjectCommand {
|
||||
try file.parent().mkpath()
|
||||
try file.write(output)
|
||||
} else {
|
||||
stdout.print(output)
|
||||
success(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,6 @@ import Version
|
||||
|
||||
class GenerateCommand: ProjectCommand {
|
||||
|
||||
@Flag("-q", "--quiet", description: "Suppress all informational and success output")
|
||||
var quiet: Bool
|
||||
|
||||
@Flag("-c", "--use-cache", description: "Use a cache for the xcodegen spec. This will prevent unnecessarily generating the project if nothing has changed")
|
||||
var useCache: Bool
|
||||
|
||||
@ -46,7 +43,7 @@ class GenerateCommand: ProjectCommand {
|
||||
Path("~/.xcodegen/cache/\(projectSpecPath.absolute().string.md5)").absolute()
|
||||
var cacheFile: CacheFile?
|
||||
|
||||
// read cache
|
||||
// generate cache
|
||||
if useCache || self.cacheFilePath != nil {
|
||||
do {
|
||||
cacheFile = try specLoader.generateCacheFile()
|
||||
@ -138,22 +135,4 @@ class GenerateCommand: ProjectCommand {
|
||||
try Task.run(bash: command, directory: projectDirectory.absolute().string)
|
||||
}
|
||||
}
|
||||
|
||||
func info(_ string: String) {
|
||||
if !quiet {
|
||||
stdout.print(string)
|
||||
}
|
||||
}
|
||||
|
||||
func warning(_ string: String) {
|
||||
if !quiet {
|
||||
stdout.print(string.yellow)
|
||||
}
|
||||
}
|
||||
|
||||
func success(_ string: String) {
|
||||
if !quiet {
|
||||
stdout.print(string.green)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,9 @@ class ProjectCommand: Command {
|
||||
let name: String
|
||||
let shortDescription: String
|
||||
|
||||
@Flag("-q", "--quiet", description: "Suppress all informational and success output")
|
||||
var quiet: Bool
|
||||
|
||||
@Key("-s", "--spec", description: "The path to the project spec file. Defaults to project.yml. (It is also possible to link to multiple spec files by comma separating them. Note that all other flags will be the same.)")
|
||||
var spec: String?
|
||||
|
||||
@ -58,4 +61,22 @@ class ProjectCommand: Command {
|
||||
}
|
||||
|
||||
func execute(specLoader: SpecLoader, projectSpecPath: Path, project: Project) throws {}
|
||||
|
||||
func info(_ string: String) {
|
||||
if !quiet {
|
||||
stdout.print(string)
|
||||
}
|
||||
}
|
||||
|
||||
func warning(_ string: String) {
|
||||
if !quiet {
|
||||
stdout.print(string.yellow)
|
||||
}
|
||||
}
|
||||
|
||||
func success(_ string: String) {
|
||||
if !quiet {
|
||||
stdout.print(string.green)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public class XcodeGenCLI {
|
||||
description: "Generates Xcode projects",
|
||||
commands: [
|
||||
generateCommand,
|
||||
CacheCommand(version: version),
|
||||
DumpCommand(version: version),
|
||||
]
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user