Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: objective-c
script: script/cibuild
notifications:
email: false
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Butter#
#Butter [![Build Status](https://travis-ci.org/ButterKit/Butter.svg?branch=master)](https://travis-ci.org/ButterKit/Butter)#

Butter is a framework for OS X that seeks to provide a set of commonly used controls which are full replacements for their cell-based AppKit counterparts. This framework is still a work in progress, but it is **usable in production apps.**

Expand Down
18 changes: 18 additions & 0 deletions script/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
**Copyright (c) 2013 Justin Spahr-Summers**

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
82 changes: 82 additions & 0 deletions script/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# objc-build-scripts

This project is a collection of scripts created with two goals:

1. To standardize how Objective-C projects are bootstrapped after cloning
1. To easily build Objective-C projects on continuous integration servers

## Scripts

Right now, there are two important scripts: [`bootstrap`](#bootstrap) and
[`cibuild`](#cibuild). Both are Bash scripts, to maximize compatibility and
eliminate pesky system configuration issues (like setting up a working Ruby
environment).

The structure of the scripts on disk is meant to follow that of a typical Ruby
project:

```
script/
bootstrap
cibuild
```

### bootstrap

This script is responsible for bootstrapping (initializing) your project after
it's been checked out. Here, you should install or clone any dependencies that
are required for a working build and development environment.

By default, the script will verify that [xctool][] is installed, then initialize
and update submodules recursively. If any submodules contain `script/bootstrap`,
that will be run as well.

To check that other tools are installed, you can set the `REQUIRED_TOOLS`
environment variable before running `script/bootstrap`, or edit it within the
script directly. Note that no installation is performed automatically, though
this can always be added within your specific project.

### cibuild

This script is responsible for building the project, as you would want it built
for continuous integration. This is preferable to putting the logic on the CI
server itself, since it ensures that any changes are versioned along with the
source.

By default, the script will run [`bootstrap`](#bootstrap), look for any Xcode
workspace or project in the working directory, then build all targets/schemes
(as found by `xcodebuild -list`) using [xctool][].

You can also specify the schemes to build by passing them into the script:

```sh
script/cibuild ReactiveCocoa-Mac ReactiveCocoa-iOS
```

As with the `bootstrap` script, there are several environment variables that can
be used to customize behavior. They can be set on the command line before
invoking the script, or the defaults changed within the script directly.

## Getting Started

To add the scripts to your project, read the contents of this repository into
a `script` folder:

```
$ git remote add objc-build-scripts https://github.com/jspahrsummers/objc-build-scripts.git
$ git fetch objc-build-scripts
$ git read-tree --prefix=script/ -u objc-build-scripts/master
```

Then commit the changes, to incorporate the scripts into your own repository's
history. You can also freely tweak the scripts for your specific project's
needs.

To merge in upstream changes later:

```
$ git fetch -p objc-build-scripts
$ git merge --ff --squash -Xsubtree=script objc-build-scripts/master
```

[xctool]: https://github.com/facebook/xctool
80 changes: 80 additions & 0 deletions script/bootstrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/bin/bash

export SCRIPT_DIR=$(dirname "$0")

##
## Configuration Variables
##

config ()
{
# A whitespace-separated list of executables that must be present and locatable.
: ${REQUIRED_TOOLS=""}

export REQUIRED_TOOLS
}

##
## Bootstrap Process
##

main ()
{
config

if [ -n "$REQUIRED_TOOLS" ]
then
echo "*** Checking dependencies..."
check_deps
fi

local submodules=$(git submodule status)
local result=$?

if [ "$result" -ne "0" ]
then
exit $result
fi

if [ -n "$submodules" ]
then
echo "*** Updating submodules..."
update_submodules
fi
}

check_deps ()
{
for tool in $REQUIRED_TOOLS
do
which -s "$tool"
if [ "$?" -ne "0" ]
then
echo "*** Error: $tool not found. Please install it and bootstrap again."
exit 1
fi
done
}

bootstrap_submodule ()
{
local bootstrap="script/bootstrap"

if [ -e "$bootstrap" ]
then
echo "*** Bootstrapping $name..."
"$bootstrap" >/dev/null
else
update_submodules
fi
}

update_submodules ()
{
git submodule sync --quiet && git submodule update --init && git submodule foreach --quiet bootstrap_submodule
}

export -f bootstrap_submodule
export -f update_submodules

main
142 changes: 142 additions & 0 deletions script/cibuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/bin/bash

export SCRIPT_DIR=$(dirname "$0")

##
## Configuration Variables
##

SCHEMES="$@"

config ()
{
# The workspace to build.
#
# If not set and no workspace is found, the -workspace flag will not be passed
# to `xctool`.
#
# Only one of `XCWORKSPACE` and `XCODEPROJ` needs to be set. The former will
# take precedence.
: ${XCWORKSPACE=$(find_pattern "*.xcworkspace")}

# The project to build.
#
# If not set and no project is found, the -project flag will not be passed
# to `xctool`.
#
# Only one of `XCWORKSPACE` and `XCODEPROJ` needs to be set. The former will
# take precedence.
: ${XCODEPROJ=$(find_pattern "*.xcodeproj")}

# A bootstrap script to run before building.
#
# If this file does not exist, it is not considered an error.
: ${BOOTSTRAP="$SCRIPT_DIR/bootstrap"}

# Extra options to pass to xctool.
: ${XCTOOL_OPTIONS="RUN_CLANG_STATIC_ANALYZER=NO"}

# A whitespace-separated list of default schemes to build.
#
# Individual names can be quoted to avoid word splitting.
: ${SCHEMES:=$(xcodebuild -list 2>/dev/null | awk -f "$SCRIPT_DIR/schemes.awk")}

export XCWORKSPACE
export XCODEPROJ
export BOOTSTRAP
export XCTOOL_OPTIONS
export SCHEMES
}

##
## Build Process
##

main ()
{
config

if [ -f "$BOOTSTRAP" ]
then
echo "*** Bootstrapping..."
"$BOOTSTRAP" || exit $?
fi

echo "*** The following schemes will be built:"
echo "$SCHEMES" | xargs -n 1 echo " "
echo

echo "$SCHEMES" | xargs -n 1 | (
local status=0

while read scheme
do
build_scheme "$scheme" || status=1
done

exit $status
)
}

find_pattern ()
{
ls -d $1 2>/dev/null | head -n 1
}

run_xctool ()
{
if [ -n "$XCWORKSPACE" ]
then
xctool -workspace "$XCWORKSPACE" $XCTOOL_OPTIONS "$@" 2>&1
elif [ -n "$XCODEPROJ" ]
then
xctool -project "$XCODEPROJ" $XCTOOL_OPTIONS "$@" 2>&1
else
echo "*** No workspace or project file found."
exit 1
fi
}

parse_build ()
{
awk -f "$SCRIPT_DIR/xctool.awk" 2>&1 >/dev/null
}

build_scheme ()
{
local scheme=$1

echo "*** Cleaning $scheme..."
run_xctool -scheme "$scheme" clean >/dev/null || exit $?

echo "*** Building and testing $scheme..."
echo

local sdkflag=
local action=test

# Determine whether we can run unit tests for this target.
run_xctool -scheme "$scheme" run-tests | parse_build

local awkstatus=$?

if [ "$awkstatus" -ne "0" ]
then
# Unit tests aren't supported.
action=build
fi

if [ "$awkstatus" -eq "1" ]
then
# Build for iOS.
sdkflag="-sdk iphonesimulator"
fi

run_xctool $sdkflag -scheme "$scheme" $action
}

export -f build_scheme
export -f run_xctool
export -f parse_build

main
12 changes: 12 additions & 0 deletions script/schemes.awk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
BEGIN {
FS = "\n";
}

/Targets:/ {
while (getline && $0 != "") {
if ($0 ~ /Test/) continue;

sub(/^ +/, "");
print "'" $0 "'";
}
}
25 changes: 25 additions & 0 deletions script/xctool.awk
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Exit statuses:
#
# 0 - No errors found.
# 1 - Wrong SDK. Retry with SDK `iphonesimulator`.
# 2 - Missing target.

BEGIN {
status = 0;
}

{
print;
}

/Testing with the '(.+)' SDK is not yet supported/ {
status = 1;
}

/does not contain a target named/ {
status = 2;
}

END {
exit status;
}