Crafter - Xcode project configuration CLI made easy.

Related tags

Graphics crafter
Overview

How do you setup your Cocoa projects? Do you always set same warnings, clone configurations and do bunch of other stuff? Or maybe you work in a big company and you are missing some standardised setup?

Programmers tend to automatise boring and repetitive tasks, yet I often see people spending time and time again configuring their Xcode Projects, even thought they always set it up same way.

We all know that Xcode templating system is far from perfect, beside we often use different templates, but same level of warnings, scripts etc.

What if you could define your project setup once (even with optional stuff) then just apply that to all your projects?

Enter crafter

That's why I've created crafter, a ruby gem that you can install, setup your configuration once and enjoy hours of time saved.

So how does it work?

Install it by calling:

gem install crafter
crafter reset

this will create your personal configuration file at ~/.crafter.rb

now open that file with your favourite editor and you will see default configuration, along with description of different parts:

load "#{Crafter::ROOT}/config/default_scripts.rb"

# All your configuration should happen inside configure block
Crafter.configure do

  # This are projects wide instructions
  add_platform({:platform => :ios, :deployment => 6.0})
  add_git_ignore
  duplicate_configurations({:adhoc => :debug, :profiling => :debug})

  # set of options, warnings, static analyser and anything else normal xcode treats as build options
  set_options %w(
     RUN_CLANG_STATIC_ANALYZER
     GCC_TREAT_WARNINGS_AS_ERRORS
   )
  
  # set shared build settings
  set_build_settings({
    :'WARNING_CFLAGS' => %w(
    -Weverything
    -Wno-objc-missing-property-synthesis
    -Wno-unused-macros
    -Wno-disabled-macro-expansion
    -Wno-gnu-statement-expression
    -Wno-language-extension-token
    -Wno-overriding-method-mismatch
    ).join(" ")
  })
  
  # and configuration specific ones
  set_build_settings({
    :'BUNDLE_ID_SUFFIX' => '.dev',
    :'BUNDLE_DISPLAY_NAME_SUFFIX' => 'dev'
  }, configuration: :debug)
  
  set_build_settings({
    :'BUNDLE_ID_SUFFIX' => '.adhoc',
    :'BUNDLE_DISPLAY_NAME_SUFFIX' => 'adhoc'
  }, configuration: :adhoc)
  
  set_build_settings({
    :'BUNDLE_ID_SUFFIX' => '',
    :'BUNDLE_DISPLAY_NAME_SUFFIX' => ''
  }, configuration: :release)
    

  # set non boolean options
  set_build_settings ({
    :'OTHER_CFLAGS' => '-Wall'
  })

  # target specific options, :default is just a name for you, feel free to call it whatever you like
  with :default do

    # each target have set of pods
    pods << %w(NSLogger-CocoaLumberjack-connector TestFlightSDK)

    # each target can have optional blocks, eg. crafter will ask you if you want to include networking with a project
    add_option :networking do
      pods << 'AFNetworking'
    end

    add_option :coredata do
      pods << 'MagicalRecord'
    end

    # each target can have shell scripts added, in this example we are adding my icon versioning script as in http://www.merowing.info/2013/03/overlaying-application-version-on-top-of-your-icon/
    scripts << {:name => 'icon versioning', :script => Crafter.icon_versioning_script}

    # we can also execute arbitrary ruby code when configuring our projects, here we rename all our standard icon* to icon_base for versioning script
    icon_rename = proc do |file|
      extension = File.extname(file)
      file_name = File.basename(file, extension)
      File.rename(file, "#{File.dirname(file)}/#{file_name}_base#{extension}")
    end

    Dir['**/Icon.png'].each(&icon_rename)
    Dir['**/[email protected]'].each(&icon_rename)
    Dir['**/Icon-72.png'].each(&icon_rename)
    Dir['**/[email protected]'].each(&icon_rename)
  end

  # more targets setup
  with :tests do
    add_option :kiwi do
      pods << 'Kiwi'
      scripts << {:name => 'command line unit tests', :script => Crafter.command_line_test_script}
    end
  end
end

As you can see the configuration files is quite easy, yet is pretty flexible. Once you set it up as you see fit, go to your project folder (the one with xcodeproj, workspace etc.) and call:

crafter

it will guide you through project setup, with default configuration it would look like this:

1. sample
2. sampleTests
Which target should I use for default?
1
1. sample
2. sampleTests
Which target should I use for tests?
2
do you want to add networking? [Yn]
n
do you want to add coredata? [Yn]
y
do you want to add testing? [Yn]
n
duplicating configurations
setting up variety of options
preparing git ignore
preparing pod file
adding scripts
Finished.

Now your project should have all options applied, generated Podfile (call pod install or set it up in your configuration).

I'm learning Ruby, so I'm looking forward to pull requests on GitHub

Send me your thoughts, I'm merowing_ on twitter

Acknowledgements:

The App Business (the company I worked for) for supporting my idea.

to @alloy, @orta, @romainbriche - for taking some of their valuable time and sharing their thoughts about beta version.

Inspired by liftoff

Comments
  • Trouble using Crafter script

    Trouble using Crafter script

    I tried using the script for Crafter, but it throws an error.

    Svens-MacBook-Pro-3:ShakeHands sven$ crafter /Library/Ruby/Gems/2.0.0/gems/crafter-0.1.39/lib/crafter.rb:57:in set_build_settings': wrong number of arguments (2 for 1) (ArgumentError) from /Users/sven/.crafter.rb:29:inblock in <top (required)>' from /Library/Ruby/Gems/2.0.0/gems/crafter-0.1.39/lib/crafter.rb:22:in instance_eval' from /Library/Ruby/Gems/2.0.0/gems/crafter-0.1.39/lib/crafter.rb:22:inconfigure' from /Users/sven/.crafter.rb:4:in <top (required)>' from /Library/Ruby/Gems/2.0.0/gems/crafter-0.1.39/lib/crafter.rb:122:inload' from /Library/Ruby/Gems/2.0.0/gems/crafter-0.1.39/lib/crafter.rb:122:in <module:Crafter>' from /Library/Ruby/Gems/2.0.0/gems/crafter-0.1.39/lib/crafter.rb:13:in<top (required)>' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in require' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:inrequire' from /Library/Ruby/Gems/2.0.0/gems/crafter-0.1.39/bin/crafter:13:in <top (required)>' from /usr/bin/crafter:23:inload' from /usr/bin/crafter:23:in `

    '

    opened by iCarambaa 6
  • Adds a way to set non-boolean build settings.

    Adds a way to set non-boolean build settings.

    Hi! As discussed on Twitter, I am here now with the pull request. I added a way to set non-boolean build settings with Crafter. Although the way via 'options' is somehow redundant, I kept it because Crafter is a library and I don't want to force any user to change their configuration files. Here is an example how to use it in the config: set_build_settings ({ :'OTHER_CFLAGS' => '-Wall' }) I added a few checks too. In case someone wan't use 'options' or 'build_settings' in the config file. Hope that is all ok with you.

    Best, Stephan

    opened by StephanPartzsch 3
  • Fix operator precedence bug

    Fix operator precedence bug

    Would fail with "undefined method empty?' for nil:NilClass" if@build_settingswasnil`.

    I prefer explicit "old school" operators in this case, but it could also work reversing it: ... unless @build_settings.empty? if @build_settings

    opened by marcboquet 2
  • License missing from gemspec

    License missing from gemspec

    Some companies will only use gems with a certain license. The canonical and easy way to check is via the gemspec via e.g.

    spec.license = 'MIT'
    # or
    spec.licenses = ['MIT', 'GPL-2']
    

    There is even a License Finder to help companies ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. Including a license in your gemspec is a good practice, in any case.

    How did I find you?

    I'm using a script to collect stats on gems, originally looking for download data, but decided to collect licenses too, and make issues for missing ones as a public service :) https://gist.github.com/bf4/5952053#file-license_issue-rb-L13 So far it's going pretty well

    opened by bf4 2
  • Convert symbols to strings before passing them to nanaimo

    Convert symbols to strings before passing them to nanaimo

    Nanaimo blew up with this error:

    `sort': comparison of Array with Array failed

    Which was caused by :KZEnv being compared with another build configuration key which was a string.

    :KZEnv <=> "foobar" # => nil
    
    opened by mrcljx 1
  • Updating gemspec's xcodeproj version

    Updating gemspec's xcodeproj version

    The newest version of xcodeproj required a few tweaks to the code to get working. One thing to keep in mind, and perhaps something you should write as an example in your default crafter script, is that all set_build_settings() can't be made with ruby symbols anymore. The keys have to be strings (e.g. :'KZBEnv' is not ok): set_build_settings({ 'BUNDLE_ID_SUFFIX' => '.dev', 'BUNDLE_DISPLAY_NAME_SUFFIX' => 'dev', 'KZBEnv' => 'DEV' }, configuration: :Debug)

    opened by myster-t 1
  • Is it possible to run a custom config file other than ~/.crafter.rb?

    Is it possible to run a custom config file other than ~/.crafter.rb?

    I want to write a config file to be reused within a specific set of developers. How do I run the crafter command, along with that custom file?

    Something like?

    crafter ~/path/to/my/file.rb
    
    opened by wilmarvh 1
  • Detect ImageMagick

    Detect ImageMagick

    I did not specifically test this, nor did I check the code, but I don’t think there currently is any graceful failing when ImageMagick isn't installed. It would be nice to warn the user and give them an example on how to easily install it. (E.g. with homebrew.)

    opened by alloy 0
  • Improve output

    Improve output

    The output could be a bit nicer. Currently it looks like this:

    ~/C/F/mtreader [master] » crafter
    1. MTReader
    2. spec
    Which target should I use for default?
    1
    1. MTReader
    2. spec
    Which target should I use for tests?
    2
    do you want to add networking?
    y
    do you want to add coredata?
    y
    do you want to add testing?
    y
    

    I would opt for something like:

    ~/C/F/mtreader [master] » crafter
    To which target should the defaults be applied?
    1. MTReader
    2. spec
    Choice [1, 2]: 1
    
    Which target is used for testing purposes?
    1. MTReader
    2. spec
    Choice [1, 2]: 2
    
    Do you want to add networking?
    Choice [Y/n]: y
    
    Do you want to add coredata?
    Choice: [Y/n]: y
    
    Do you want to add testing?
    Choice: [Y/n]: y
    

    I saw that you have a dependency on Highline, but I wasn't really sure where you were actually using it and what for. I would probably create this UI in pure Ruby (without the dependency).

    opened by alloy 0
  • Make Podfile more pretty.

    Make Podfile more pretty.

    Some whitespace in the generated Podfile would be nice :)

    E.g.

    platform :ios, '6.0'
    
    target :CrafterTest, :exclusive => true do
      pod 'NSLogger-CocoaLumberjack-connector'
      pod 'TestFlightSDK'
      pod 'AFNetworking'
      pod 'MagicalRecord'
    end
    
    target :CrafterTestTests, :exclusive => true do
      pod 'Kiwi'
    end
    
    opened by alloy 0
  • Icon versioning build phase order.

    Icon versioning build phase order.

    The icon versioning shell script phase should probably be inserted before the copy bundle resources phase, so that the copy phase copies the generated icon, instead of older versions or even break if there are no generated versions yet.

    opened by alloy 0
  • Not working on Xcode 8 - issue

    Not working on Xcode 8 - issue "Could not found any Target!"

    Hi, I trying to setup a project with Xcode 8, cause issue "Could not found any Target!"

    Traceback here: Duongs-MacBook-Pro:<project_dir> socoboy$ crafter /Users/socoboy/workspace/tools/crafter/lib/project_helper.rb:97:in choose_item': Could not locate any Targets! (RuntimeError) from /Users/socoboy/workspace/tools/crafter/lib/project_helper.rb:64:inselect_target_for_name' from /Users/socoboy/workspace/tools/crafter/lib/crafter.rb:37:in find_target_configuration' from /Users/socoboy/workspace/tools/crafter/lib/crafter.rb:28:inwith' from /Users/socoboy/.crafter.rb:77:in block in <top (required)>' from /Users/socoboy/workspace/tools/crafter/lib/crafter.rb:24:ininstance_eval' from /Users/socoboy/workspace/tools/crafter/lib/crafter.rb:24:in configure' from /Users/socoboy/.crafter.rb:4:in<top (required)>' from /Users/socoboy/workspace/tools/crafter/lib/crafter.rb:134:in load' from /Users/socoboy/workspace/tools/crafter/lib/crafter.rb:134:inmodule:Crafter' from /Users/socoboy/workspace/tools/crafter/lib/crafter.rb:13:in <top (required)>' from /Users/socoboy/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:inrequire' from /Users/socoboy/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in require' from /Users/socoboy/workspace/tools/crafter/bin/crafter:13:in

    '

    opened by socoboy 3
  • cannot set build setting for Release

    cannot set build setting for Release

    set_build_settings({
        :'BUNDLE_ID_SUFFIX' => '',
        :'BUNDLE_DISPLAY_NAME_SUFFIX' => '',
        :'KZBEnv' => 'PRODUCTION'
      }, configuration: :release)
    
    

    doesn't work for Xcode 7.3.1

    opened by CharlyZhang 0
  • set_build_settings not working on duplicated configurations

    set_build_settings not working on duplicated configurations

    I am trying to duplicate my release settings and then set specific values for each configuration but it does not seem to work.

    I have this duplicate_configurations({:staging => :release})

    and right after I have

    set_build_settings({ :'BUNDLE_ID_SUFFIX' => '.staging', :'BUNDLE_DISPLAY_NAME_SUFFIX' => 'staging', :'KZBEnv' => 'STAGING' }, configuration: :staging)

    set_build_settings({ :'BUNDLE_ID_SUFFIX' => '', :'BUNDLE_DISPLAY_NAME_SUFFIX' => '', :'KZBEnv' => 'PRODUCTION' }, configuration: :release)

    I end up with Release being set to Staging values

    screen shot 2014-12-17 at 2 31 02 pm

    If I invert the values like

    duplicate_configurations({:release => :staging})

    Then Staging is not created

    opened by linkrjr 0
  • post_install hook on Podfile [question]

    post_install hook on Podfile [question]

    Hi; don't know if there's a way to actually add a post_install or append some code to the Podfile from Crafter.

    This tool is really nice and I'm setting a Crafter configuration file to share among the developers of the department.

    We use the Acknowledgements post install to generate and move to the Settings.bundle and would very much like to include this from crafter to avoid copying and pasting on every new project.

    I know pretty much nothing about Ruby and just wandering if Crafter already supports this.

    Thanks.

    opened by esttorhe 1
Owner
Krzysztof Zabłocki
Making Swift engineers more efficient through tools and workflows.  My code powers up over 80 000+ apps.
Krzysztof Zabłocki
🎞 Powerful gradient animations made simple for iOS.

AnimatedGradientView is a UIView subclass which makes it simple to add animated gradients to your iOS app. It is written purely in Swift. Further docu

Ross Butler 431 Dec 12, 2022
NXDrawKit is a simple and easy but useful drawing kit for iPhone

⚠️ To use with Swift 5.0 please ensure you are using >= 0.8.0 ⚠️ ⚠️ To use with Swift 4.2 please ensure you are using >= 0.7.1 ⚠️ ⚠️ To use with Swift

Nicejinux 1.3k Dec 31, 2022
Powerful and easy-to-use vector graphics Swift library with SVG support

Macaw Powerful and easy-to-use vector graphics Swift library with SVG support We are a development agency building phenomenal apps. What is Macaw? Mac

Exyte 5.9k Jan 2, 2023
A super easy way to check if the installed app has an update available. It is built with simplicity and customisability in mind and comes with pre-written tests.

UpdateAvailableKit This is UpdateAvailableKit: a super easy way to check if the installed app has an update available. It is built with simplicity and

Swapnanil Dhol 22 Jan 5, 2023
An xcconfig (Xcode configuration) file for easily turning on a boatload of warnings in your project or its targets.

Warnings This is an xcconfig file to make it easy for you to turn on a large suite of useful warnings in your Xcode project. These warnings catch bugs

Peter Hosey 438 Nov 8, 2022
🔥 🔥 🔥Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

?? ?? ??Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

null 60 Dec 12, 2022
Handles some of the base configuration to make creating a UIAlertController with text entry even easier. Plus validation!

?? FancyTextEntryController A simpler/easier API for adding text fields to UIAlertControllers. Not a custom view, just uses good ol' UIAlertController

Christian Selig 22 Jul 18, 2022
Remote configuration and A/B Testing framework for iOS

MSActiveConfig v1.0.1 Remote configuration and A/B Testing framework for iOS. Documentation available online. MSActiveConfig at a glance One of the bi

Elevate 78 Jan 13, 2021
Appfiguratesdk - Appfigurate provides the ability to change configuration properties in iOS and watchOS, apps and app extensions, securely, at runtime.

Appfigurate™ Appfigurate provides the ability to change configuration properties in iOS and watchOS, apps and app extensions, securely, at runtime. Do

Electric Bolt 21 Dec 14, 2022
DataDrivenAlert - Extension for SwiftUI.Alert for data driven configuration

Data driven alert and confirmation dialog Based on Composable Architecture Alert

Evgeny 2 Apr 9, 2022
A CMIO Camera Extension of the creative camera type, with configuration app

ArtFilm A CMIO Camera Extension of the creative camera type, with configuration app ArtFilm is the sample code for the blog post Getting To Grips With

Halle 7 Jan 1, 2023
A CLI tool for localization resource management on Xcode. Built with Google Translator.

Supported by Jetbrains Open Source License Program Automatically translate and synchronize '.strings' files from the defined base language The basic c

gitmerge 164 May 4, 2022
A CLI to Alcatraz, the Xcode package manager.

Azkaban This project is deprecated in favor of Editor Extensions support in Xcode 8+. A CLI to Alcatraz, the Xcode package manager. Usage Install a pl

Boris Bügling 64 Jun 3, 2021
🧸 Xcode Playground management made easy

Toybox Toybox made easy to manage Xcode Playgrounds. You can create and open Xcode Playground from CLI. $ toybox create Snippet # Generate ~/.toybox/S

Kohki Miki 130 Nov 8, 2022
Synx - A command-line tool that reorganizes your Xcode project folder to match your Xcode groups

A command-line tool that reorganizes your Xcode project folder to match your Xcode groups. Xcode Finder Installation $ gem install synx Usage Basic ⚠

Venmo 6.1k Jan 2, 2023
🛰 CoreLocation Made Easy - Efficient & Easy Location Tracker, IP Location, Gecoder, Geofence, Autocomplete, Beacon Ranging, Broadcaster and Visits Monitoring

Location Manager Made Easy SwiftLocation is a lightweight Swift Library that provides an easy way to work with location-related functionalities. No mo

Daniele Margutti 3.2k Dec 30, 2022
🛰 CoreLocation Made Easy - Efficient & Easy Location Tracker, IP Location, Gecoder, Geofence, Autocomplete, Beacon Ranging, Broadcaster and Visits Monitoring

Location Manager Made Easy SwiftLocation is a lightweight Swift Library that provides an easy way to work with location-related functionalities. No mo

Daniele Margutti 3.2k Dec 30, 2022
Clocks made out of clocks made out of code

Clocks I came across this digital clock composed out of a set of analog clocks, created by Humans Since 1982, in a tweet, so I decided to remake it in

Harshil Shah 43 Sep 28, 2022
A starter project for Sample Project in swift 5, Xcode 12.5

A starter project for Sample Project in swift 5, Xcode 12.5 (also bridging header included so you could use objective c code in it as well ).

Zeeshan Haider 51 Oct 27, 2022
Guaka - Smart and beautiful POSIX compliant CLI framework for Swift.

Guaka - Smart and beautiful POSIX compliant CLI framework for Swift. It helps you create modern and familiar CLI apps in the vein of widely used proje

Omar Abdelhafith 1.1k Dec 24, 2022