Open AliSoftware opened 6 years ago
Now that I think about it, I'm not sure if that idea would be self-sufficient.
When we create a new project, both the Xcodeproj (generated by XcodeGen) but also the project files (swift code, copyright header comments, XIBs, Storyboards, …), must be "templatized" and adapted too. And I'm guessing that part isn't XcodeGen's job…
I'm curious to know what people use for such needs, as a solution to replace liftoff
, if XcodeGen isn't the tool for that, btw.
In the meantime I'm working on a tiny ruby script to do that job of create-new-projet-structure-from-a-template, but if there's already some existing tool which handles that for us, I'm interested to know to avoid re-inventing the wheel…
Yeah scaffolding/templating is probably outside the scope of XcodeGen. Generating a project spec from an existing project, or interactively from scratch is on the cards though.
Some other tools I know of in this space though are: https://github.com/audreyr/cookiecutter http://yeoman.io https://github.com/workshop/cook https://github.com/JohnSundell/SwiftPlate
Cookiecutter is probably your best bet
I think there's an opportunity in the community to build a good tool like this in Swift. I know that @jcampbell05 wanted to work on something like that, and @rjchatfield showed me a cool tool the other day that he's been building internally for Atlasssian that solves similar problems.
Personally I'd like to see something similar to the template files in SwagGen Basically a template manifest file that defines options and a list of Stencil files that get passed those options. These options could also be interactively queried for in the command line tool. There could be some default templates for Xcode Projects, and people could then edit and share them.
I started a basic tool for this. It essentially just consumed the XCTemplate file and hooked into a tool such as Xcake, Struct or XcodeGen to spit out the files.
This was a very early alpha of it https://github.com/workshop/cook its in ruby sadly. I've tried to re-start it in swift since but not got quite so far.
I’ve got some ideas about a tool like this... Watch this space
can we add support for env files to the project.yml?
then we could call it like
name=FOO code_signing_identity=BAR xcodegen
I'm curious what @yonaskolb has in mind, I would have gone the .erb route for customising the project.yml I guess.
Ok guys, I've written a new tool called Genesis for templating. It utilises a template manifest and templates written in Stencil.
Taking the exact @AliSoftware example originally posted, it would look like this in the most simplest form in Genesis.
template.yml
options:
- name: name
question: What's your project name?
- name: id
question: What's the bundle id?
- name: iOSVersion
question: What version of iOS is this using?
choices:
- 9.0
- 10.0
- 11.0
files:
- template: project.yml
project.yml:
name: {{ name }}
options:
createIntermediateGroups: true
bundleIdPrefix: {{ id }}
developmentLanguage: "en"
usesTabs: false
indentWidth: 2
tabWidth: 2
deploymentTarget:
watchOS: "2.0"
tvOS: "10.0"
iOS: {{ iOSVersion }}
settings:
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED: YES
GCC_WARN_MISSING_PARENTHESES: YES
GCC_WARN_ABOUT_RETURN_TYPE: YES
GCC_WARN_CHECK_SWITCH_STATEMENTS: YES
GCC_WARN_UNUSED_FUNCTION: YES
GCC_WARN_UNUSED_LABEL: YES
targets:
{{ name }}
type: application
UnitTests:
type: bundle.unit-test
You could then generate this using
genesis generate template.yml
It looks for options via various methods (env, file, arguments) and asks you interactively if none are found. An easy way to pass the options is like this:
genesis generate template.yml --options "name:MyProject, id: com.company, iOSVersion: 10.0"
There are more complex configuration options than this, but this is a simple example. If you could take a look at the repo and kick the tires I'd appreciate it.
Cool!
iiuc we can list as many files as we want in the files
entry and those files should actually be stencil templates that gets rendered using the barracks previously defined as context?
Yep!
Those files can also have dynamic paths, and even be rendered out multiple times with different child contexts if it reference an array via context
.
You could even make an XcodeGen project spec be the data for a template with --option-path
and then dynamically generate the folder structure from that by reading from it as a context, and then providing templated Info.plist files and things
I was looking for a way to use Environment variables in my project.yml file for project configuration. Looking into Genesis and it looks promising!
Coming back on this:
https://github.com/SwiftGen/SwiftGen/pull/564 implements this for SwiftGen https://github.com/krzysztofzablocki/Sourcery/pull/724 implements this for Sourcery
Can we please do something like this directly in XcodeGen? My team would crucify me, if I bring in yet another tool like Genesis 😅.
A PR has just been merged that supports referencing environment variables https://github.com/yonaskolb/XcodeGen/pull/594
While this is not interactive, a wrapper script could still ask the user for these values
@yonaskolb Awesome, looking forward to try it!
One use case I would have for XcodeGen would be to generate brand new projects when starting a new contract.
(For now we use liftoff for that but as it's not maintained anymore, we want to migrate to something else like XcodeGen)
The idea would be to create a
project.yml
with a magic syntax for values which, when encountered, would (1) interactively ask for the value to give to that setting (2) or allow for it to be specified via command line parameters (3) and once the project has been generated once, replace the values in theproject.yml
with the new onesSo, for example we could have a
template.yml
file like this:And then we could run the command, where we can provide values for all "?…" magic values, either using arguments via the command lines (using the parameter name provided next to the "?") or/and be interactively queried for others (using the second parameter provided after the "?…|" for the prompt, and the optional third part for the default value):