yonaskolb / xcodegen Goto Github PK
View Code? Open in Web Editor NEWA Swift command line tool for generating your Xcode project
License: MIT License
A Swift command line tool for generating your Xcode project
License: MIT License
It seems that https://github.com/swift-xcode/xcodeproj supports PBXAggregateTarget (?), but XcodeGen doesn't.
Priority would be low though, I often use the kind of target in framework projects to invoke archive script.
I often use auto-increment build number script and some scripts that should invoked only when archiving.
Examples:
http://crunchybagel.com/auto-incrementing-build-numbers-in-xcode/
https://gist.github.com/sekati/3172554
https://github.com/realm/realm-cocoa/blob/master/scripts/strip-frameworks.sh
Those kind of scripts should run only when archiving (well, just personally I guess so). So I believe 'Run script only when installing' option would be nice...
This is just a question about include
feature.
How is it different from simply using xcconfig's #include
and Xcode's $(inherited)
?
This results in projects that don't have default build settings applied for config type, platform or product type
Ability to support spec includes. This would allow you to seperate the spec into multiple files, to for example seperate all the setting presets for sharing amongst multiple specs
Generation fails unless App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
is present.
workaround:
$ mkdir LGTM.xcodeproj/project.xcworkspace
$ :> LGTM.xcodeproj/project.xcworkspace/contents.xcworkspacedata
$ xcodegen
📋 Loaded spec:
Name: LGTM
Targets:
🖥 application: LGTM
📱 framework: LGTMKit_iOS
🖥 framework: LGTMKit_macOS
📱 application: LGTM_iOS
⚙️ Generated project
💾 Saved project to LGTM.xcodeproj
I have Xcode 9 GM installed, and have ensured that I am using them from the command-line. When I do the following homebrew commands:
brew update
brew tap yonaskolb/XcodeGen https://github.com/yonaskolb/XcodeGen.git
brew install XcodeGen
then I am getting the following errors both on my local laptop and our CI servers:
Updated 2 taps (caskroom/cask, homebrew/core).
==> New Formulae
azure-cli@1
json-table
==> Updated Formulae
akamai
angular-cli
apache-opennlp
axel
azure-cli
bandcamp-dl
...
webpack
wpscan
xorriso
xtensor
you-get
youtube-dl
==> Deleted Formulae
kes
==> Tapping yonaskolb/xcodegen
Cloning into '/usr/local/Homebrew/Library/Taps/yonaskolb/homebrew-xcodegen'...
Tapped 1 formula (99 files, 2.7MB)
==> Installing xcodegen from yonaskolb/xcodegen
==> Downloading https://github.com/yonaskolb/XcodeGen/archive/0.6.1.tar.gz
==> Downloading from https://codeload.github.com/yonaskolb/XcodeGen/tar.gz/0.6.1
==> Building XcodeGen
==> swift build -c release -Xlinker -rpath -Xlinker @executable_path -Xswiftc -static-stdlib
Last 15 lines from /Users/builduser/Library/Logs/Homebrew/xcodegen/01.swift:
2017-09-18 18:59:50 +0000
swift build -c release -Xlinker -rpath -Xlinker @executable_path -Xswiftc -static-stdlib
error: manifest parse error(s):
sandbox-exec: sandbox_apply_container: Operation not permitted
If reporting this issue please do so to (not Homebrew/brew or Homebrew/core):
yonaskolb/xcodegen
/usr/local/Homebrew/Library/Homebrew/utils/github.rb:226:in `raise_api_error': curl failed! curl: (22) The requested URL returned error: 422 Unprocessable Entity (GitHub::Error)
curl: (3) <url> malformed
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:184:in `open'
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:284:in `search'
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:231:in `search_issues'
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:244:in `issues_for_formula'
from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:369:in `fetch_issues'
from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:365:in `issues'
from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:419:in `dump'
from /usr/local/Homebrew/Library/Homebrew/brew.rb:133:in `rescue in <main>'
from /usr/local/Homebrew/Library/Homebrew/brew.rb:26:in `<main>'
Generate pre and post build run script build phases
Using the instructions from the README I currently get this:
brew install xcodegen
==> Installing xcodegen from yonaskolb/xcodegen
==> Downloading https://github.com/yonaskolb/XcodeGen/archive/0.6.1.tar.gz
Already downloaded: /Users/dbeard/Library/Caches/Homebrew/xcodegen-0.6.1.tar.gz
==> Building XcodeGen
==> swift build -c release -Xlinker -rpath -Xlinker @executable_path -Xswiftc -static-stdlib
Last 15 lines from /Users/dbeard/Library/Logs/Homebrew/xcodegen/01.swift:
2017-09-13 12:02:33 -0700
swift build -c release -Xlinker -rpath -Xlinker @executable_path -Xswiftc -static-stdlib
error: manifest parse error(s):
sandbox-exec: sandbox_apply_container: Operation not permitted
If reporting this issue please do so to (not Homebrew/brew or Homebrew/core):
yonaskolb/xcodegen
/usr/local/Homebrew/Library/Homebrew/utils/github.rb:226:in `raise_api_error': curl failed! (GitHub::Error)
curl: (22) The requested URL returned error: 422 Unprocessable Entity
curl: (3) <url> malformed
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:184:in `open'
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:284:in `search'
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:231:in `search_issues'
from /usr/local/Homebrew/Library/Homebrew/utils/github.rb:244:in `issues_for_formula'
from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:369:in `fetch_issues'
from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:365:in `issues'
from /usr/local/Homebrew/Library/Homebrew/exceptions.rb:419:in `dump'
from /usr/local/Homebrew/Library/Homebrew/brew.rb:133:in `rescue in <main>'
from /usr/local/Homebrew/Library/Homebrew/brew.rb:26:in `<main>'
If multiple targets have share the same source folder
Currently if I generate a project that has a xcconfig set for the configuration, and also includes the directory the xcconfig file lives in in the sources
of a target, the project ends up in a broken state:
This is the configuration for this case:
name: Project
configs:
Debug: debug
configFiles:
Debug: xcconfigs/debug.xcconfig
targets:
Project:
type: application
platform: iOS
sources: xcconfigs
Sample project (with the generated project) as an example: XcodeGenTest.zip
This lets the Carthage folder reside in other places than the project root
Add the ability to add a TestTargetID
in project attributes
You can already set the TEST_TARGET_NAME
build setting but that doesn't change the "Host application" in the Xcode UI
example xcodegen.yml
:
name: FooBar
targets:
- name: FooBar
type: application
platform: iOS
sources:
- Sources
postbuildScripts:
- path: Scripts/strip-frameworks.sh
name: Strip Unused Architectures from Frameworks
runOnlyWhenInstalling: true
Xcode now says Project *.xcodeproj cannot be opened because the project file cannot be parsed.
. Script used above is: https://raw.githubusercontent.com/realm/realm-cocoa/master/scripts/strip-frameworks.sh
Although in the example I'm specifying path of the script, writing the script as string in yamls causes the same problem naturally.
Now, here is the concerned excerpt from generated project:
/* Begin PBXShellScriptBuildPhase section */
SSBP35707201 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Strip Unused Architectures from Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
shellScript = "################################################################################\n#\n# Copyright 2015 Realm Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n################################################################################\n\n# This script strips all non-valid architectures from dynamic libraries in\n# the application's `Frameworks` directory.\n#\n# The following environment variables are required:\n#\n# BUILT_PRODUCTS_DIR\n# FRAMEWORKS_FOLDER_PATH\n# VALID_ARCHS\n# EXPANDED_CODE_SIGN_IDENTITY\n\n\n# Signs a framework with the provided identity\ncode_sign() {\n # Use the current code_sign_identitiy\n echo \"Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}\"\n echo \"/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1\"\n /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"\n}\n\n# Set working directory to product’s embedded frameworks \ncd \"${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}\"\n\nif [ \"$ACTION\" = \"install\" ]; then\n echo \"Copy .bcsymbolmap files to .xcarchive\"\n find . -name '*.bcsymbolmap' -type f -exec mv {} \"${CONFIGURATION_BUILD_DIR}\" \;\nelse\n # Delete *.bcsymbolmap files from framework bundle unless archiving\n find . -name '*.bcsymbolmap' -type f -exec rm -rf \"{}\" +\;\nfi\n\necho \"Stripping frameworks\"\n\nfor file in $(find . -type f -perm +111); do\n # Skip non-dynamic libraries\n if ! [[ \"$(file \"$file\")\" == *\"dynamically linked shared library\"* ]]; then\n continue\n fi\n # Get architectures for current file\n archs=\"$(lipo -info \"${file}\" | rev | cut -d ':' -f1 | rev)\"\n stripped=\""\n for arch in $archs; do\n if ! [[ \"${VALID_ARCHS}\" == *\"$arch\"* ]]; then\n # Strip non-valid architectures in-place\n lipo -remove \"$arch\" -output \"$file\" \"$file\" || exit 1\n stripped=\"$stripped $arch\"\n fi\n done\n if [[ \"$stripped\" != \"" ]]; then\n echo \"Stripped $file of architectures:$stripped\"\n if [ \"${CODE_SIGNING_REQUIRED}\" == \"YES\" ]; then\n code_sign \"${file}\"\n fi\n fi\ndone\n";
};
/* End PBXShellScriptBuildPhase section */
I am working on a a Swift project and I need to be able to generate a Playground inserting my own file into it to get some autocomplete
Auto apply xcconfig configurations like this.
I notice documentations do mention about xcconfig but looks like it's not working as expected.
configFiles
does not affect anything. (Bug? or maybe my spec is wrong)So this is my proposal.
baseConfiguration
for PBXProjconfigFiles
with baseConfigurations
for consistency.configs
to configurations
since it looks like xcconfig
and is misleading.name: MyProject
configurations:
Debug:
baseConfiguration: configs/Debug.xcconfig
OTA:
baseConfiguration: configs/OTA.xcconfig
Release:
baseConfiguration: configs/Release.xcconfig
targets:
MyApp:
type: application
platform: iOS
sources: Sources/MyApp
settings:
PRODUCT_BUNDLE_IDENTIFIER: jp.toshi0383.hello
baseConfigurations:
Debug: configs/MyApp-Debug.xcconfig
OTA: configs/MyApp-OTA.xcconfig
Release: configs/MyApp-Release.xcconfig
If you guys feel happy with this outline, I can start working on a PR. 💪
I find it useful to include priority, difficulty and type useful to organize issues. It's also good for welcoming contributors in the project (e.g. they can start with the simple issues to get some context on the project).
This is the setup that I've used for xcodeproj, what do you think @yonaskolb?
lgtm $ xcodegen-debug
📋 Loaded spec:
Name: LGTM
Targets:
🖥 application: LGTM
📱 framework: LGTMKit_iOS
🖥 framework: LGTMKit_macOS
📺 framework: LGTMKit_tvOS
⌚️ framework: LGTMKit_watchOS
📱 application: LGTM_iOS
2 Spec validations errors:
- Target "LGTM" has invalid dependency: "LGTMKit"
- Target "LGTM_iOS" has invalid dependency: "LGTMKit"
How could I generate an empty(buildSettings = { };
) framework target?
I don't want each target for every platform.
Should be able to generate a spec from an existing project for easy migration
With spec like this,
targets:
LGTM:
platform: macOS
type: application
sources: LGTM
dependencies:
- target: LGTMKit_macOS
LGTMKit:
type: framework
platform: [iOS, macOS]
sources: LGTMKit
dependencies:
- carthage: APIKit
Related: #82
Currently, if you have more than one configs xcodegen
would make schemes Shared
.
If there is an option to make a scheme Shared
checked on, it would be great.
Using XcodeGen 0.3.0 and Xcode 8.3.3.
If one of files name contains "@", xcodegen generates non-parsable project by Xcode, somehow.
So it cannot deal with retina filenames such as [email protected]
, [email protected]
.
Adding those kind of assets to *.xcassets wouldn't really solve this problem as I intend not to use it, since using xcassets forces UIImage to be cached.
example:
name: FooBar
targets:
- name: FooBar
type: application
platform: iOS
sources:
- Assets
If "Assets" directory or its subdirectory contains a file that has "@" in its name, Xcode cannot parse generated project.
The other tool, struct
, can correctly generates a project in the same situation, just fwiw.
This is by specifying multiple platforms for a target in the spec, which would generate multiple targets, each with a different platform
The readme should contain a proper documentation. 👍
Is there any difference from using xcconfig?
What are pros/cons ?
Related: #64 (comment)
Hello,
Thanks for your this great solution that I really wanted.
Today I tried to generate my project using XcodeGen.
I faced the problem that Xcode shows the message This app was unable to be installed
after build the project for the simulator.
I reproduced it on TestProject in this repository.
xcodegen --spec spec.yml
GeneratedProject.xcodeproj
It can be fixed by removing frameworks from Copy Files in Build Phases or remove the line https://github.com/yonaskolb/XcodeGen/blob/master/Sources/XcodeGenKit/PBXProjGenerator.swift#L236
I don't know this is correct way to fix it. But do frameworks need to be copied when these add as Embedded Framework?
It would be nice if there were a way to clear the default settings XcodeGen provides. This is useful if you define all your settings in xcconfig files, so when you generate the project, you don't want its default settings to shadow yours. I almost expected it to with this configuration:
name: Project
settings:
base: []
targets:
Project:
type: application
platform: iOS
But I understand these base
settings are just additive to the project. In the meantime I might use xcodeproj to wipe these settings out after project generation.
If a storyboard localized for some language, it should be grouped into one variant group.
XcodeGen generates references same level.
expectation
VG1473702401 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
FR3676338402 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
VG2365450901 /* Main.strings */ = {
isa = PBXVariantGroup;
children = (
FR7070045401 /* en */,
);
name = Main.strings;
sourceTree = "<group>";
};
should be
VG1473702401 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
FR3676338402 /* Base */,
FR7070045401 /* en */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
This would add a command that would print out the specific settings that would be applied to a target for a specific config. This would combine
To begin with this wouldn't include settings that are applied by the top most level (the SDK) as we don't have easy access to that.
I just had an idea. What do you think about being able to generate simple projects from the command line with XcodeGen. Something like:
xcodegen init -platform iOS -name MyTest --no-tests
That would create the xcodegen.yml
file and generate the project from it. How does that sound? @yonaskolb
This would allow to linking to frameworks at a certain path
At the moment targets
is list. That was done to preserve the order of generated targets in the xcode project.
There would be some upsides to making it a map of names to targets however:
include
feature could edit and merge targets by nameThe points are very minor other than the first one which is a real consideration.
Is having the order of targets in the project worth it? Thoughts anyone?
Here is a visual difference
list - Array
targets:
- name: MyTarget
platform: iOS
type: application
- name: MyFramework
platform: iOS
type: framework
map - Dictionary
targets:
MyTarget:
platform: iOS
type: application
MyFramework:
platform: iOS
type: framework
In either case targets
in the ProjectSpec
struct would still be an array, this just affects yaml
This would lint the project after generation with https://github.com/carambalabs/xcodeprojlint to make sure no issues exist
This is for sharing build settings in multiple places
This would allow to linking of system SDK frameworks
Installation can be simplified by using Homebrew. The purpose of this issue is to provide a Homebrew formula that tells Homebrew how to install XcodeGen
This will make the Carthage copy-frameworks
script run only if the output files are missing. As suggested in the Carthage readme
I often use Swift dynamic framework and specify them in xcodegen.yml
like below:
name: Foo
targets:
- name: Bar
type: application
platform: iOS
sources:
- Sources
dependencies:
- framework: Frameworks/Foo.framework
- framework: Frameworks/Bar.framework
XcodeGen correctly handle this and add those frameworks to Linked Frameworks and Libraries
, but it seems we do not have an option to have them as Embedded Binaries
?
I have these Localizable settings under resources/language
directory.
resources/language/
├── Base.lproj
│ └── Localizable.strings
└── ja.lproj
└── Localizable.strings
I want to import them into separated target.
targets:
LGTM:
platform: macOS
type: application
sources:
- LGTM
- resources/language
LGTM_iOS:
platform: iOS
type: application
sources:
- LGTM_iOS
- resources/language
This spec ends-up with the files only added to LGTM
target.
Also on Xcode, both files are displayed as same name, so maybe it's better if we could display the parent directory names for Localizable.strings
.
Although embedding frameworks is working flawlessly, it seems Code Sign on Copy
will be always false
(checked off) even in case specifying it manually by: codeSign: true
.
allow easy carthage dependencies
dependencies:
carthage: Result
An optional file watcher that automatically regenerates the project when file system changes. Should be able to specify watched files with a glob
With this config:
name: Project
targets:
Project:
type: application
platform: iOS
sources:
- Sources/foo.swift
And this file structure:
.
├── Sources
│ └── Foo.swift
└── project.yml
1 directory, 2 files
xcodegen
fails with this error message:
📋 Loaded spec:
Name: Project
Targets:
📱 application: Project
Generation failed: The file “Foo.swift” couldn’t be opened.
Should you be able to reference a path like this absolutely? This is useful for when you have more complex file structures where sources and tests are nearby, meaning you can't reference the entire directory or you'll include test files in the non-test target.
Sample project: XcodeGenTest2.zip
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.