Skip to content

Commit f950821

Browse files
committed
Add jspahrsummers/objc-build-scripts
1 parent 3dd8265 commit f950821

File tree

6 files changed

+365
-0
lines changed

6 files changed

+365
-0
lines changed

script/LICENSE.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
**Copyright (c) 2013 Justin Spahr-Summers**
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7+
the Software, and to permit persons to whom the Software is furnished to do so,
8+
subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

script/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# objc-build-scripts
2+
3+
This project is a collection of scripts created with two goals:
4+
5+
1. To standardize how Objective-C projects are bootstrapped after cloning
6+
1. To easily build Objective-C projects on continuous integration servers
7+
8+
## Scripts
9+
10+
Right now, there are two important scripts: [`bootstrap`](#bootstrap) and
11+
[`cibuild`](#cibuild). Both are Bash scripts, to maximize compatibility and
12+
eliminate pesky system configuration issues (like setting up a working Ruby
13+
environment).
14+
15+
The structure of the scripts on disk is meant to follow that of a typical Ruby
16+
project:
17+
18+
```
19+
script/
20+
bootstrap
21+
cibuild
22+
```
23+
24+
### bootstrap
25+
26+
This script is responsible for bootstrapping (initializing) your project after
27+
it's been checked out. Here, you should install or clone any dependencies that
28+
are required for a working build and development environment.
29+
30+
By default, the script will verify that [xctool][] is installed, then initialize
31+
and update submodules recursively. If any submodules contain `script/bootstrap`,
32+
that will be run as well.
33+
34+
To check that other tools are installed, you can set the `REQUIRED_TOOLS`
35+
environment variable before running `script/bootstrap`, or edit it within the
36+
script directly. Note that no installation is performed automatically, though
37+
this can always be added within your specific project.
38+
39+
### cibuild
40+
41+
This script is responsible for building the project, as you would want it built
42+
for continuous integration. This is preferable to putting the logic on the CI
43+
server itself, since it ensures that any changes are versioned along with the
44+
source.
45+
46+
By default, the script will run [`bootstrap`](#bootstrap), look for any Xcode
47+
workspace or project in the working directory, then build all targets/schemes
48+
(as found by `xcodebuild -list`) using [xctool][].
49+
50+
You can also specify the schemes to build by passing them into the script:
51+
52+
```sh
53+
script/cibuild ReactiveCocoa-Mac ReactiveCocoa-iOS
54+
```
55+
56+
As with the `bootstrap` script, there are several environment variables that can
57+
be used to customize behavior. They can be set on the command line before
58+
invoking the script, or the defaults changed within the script directly.
59+
60+
## Getting Started
61+
62+
To add the scripts to your project, read the contents of this repository into
63+
a `script` folder:
64+
65+
```
66+
$ git remote add objc-build-scripts https://github.com/jspahrsummers/objc-build-scripts.git
67+
$ git fetch objc-build-scripts
68+
$ git read-tree --prefix=script/ -u objc-build-scripts/master
69+
```
70+
71+
Then commit the changes, to incorporate the scripts into your own repository's
72+
history. You can also freely tweak the scripts for your specific project's
73+
needs.
74+
75+
To merge in upstream changes later:
76+
77+
```
78+
$ git fetch -p objc-build-scripts
79+
$ git merge --ff --squash -Xsubtree=script objc-build-scripts/master
80+
```
81+
82+
[xctool]: https://github.com/facebook/xctool

script/bootstrap

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/bin/bash
2+
3+
export SCRIPT_DIR=$(dirname "$0")
4+
5+
##
6+
## Configuration Variables
7+
##
8+
9+
config ()
10+
{
11+
# A whitespace-separated list of executables that must be present and locatable.
12+
: ${REQUIRED_TOOLS="xctool"}
13+
14+
export REQUIRED_TOOLS
15+
}
16+
17+
##
18+
## Bootstrap Process
19+
##
20+
21+
main ()
22+
{
23+
config
24+
25+
if [ -n "$REQUIRED_TOOLS" ]
26+
then
27+
echo "*** Checking dependencies..."
28+
check_deps
29+
fi
30+
31+
local submodules=$(git submodule status)
32+
local result=$?
33+
34+
if [ "$result" -ne "0" ]
35+
then
36+
exit $result
37+
fi
38+
39+
if [ -n "$submodules" ]
40+
then
41+
echo "*** Updating submodules..."
42+
update_submodules
43+
fi
44+
}
45+
46+
check_deps ()
47+
{
48+
for tool in $REQUIRED_TOOLS
49+
do
50+
which -s "$tool"
51+
if [ "$?" -ne "0" ]
52+
then
53+
echo "*** Error: $tool not found. Please install it and bootstrap again."
54+
exit 1
55+
fi
56+
done
57+
}
58+
59+
bootstrap_submodule ()
60+
{
61+
local bootstrap="script/bootstrap"
62+
63+
if [ -e "$bootstrap" ]
64+
then
65+
echo "*** Bootstrapping $name..."
66+
"$bootstrap" >/dev/null
67+
else
68+
update_submodules
69+
fi
70+
}
71+
72+
update_submodules ()
73+
{
74+
git submodule sync --quiet && git submodule update --init && git submodule foreach --quiet bootstrap_submodule
75+
}
76+
77+
export -f bootstrap_submodule
78+
export -f update_submodules
79+
80+
main

script/cibuild

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/bin/bash
2+
3+
export SCRIPT_DIR=$(dirname "$0")
4+
5+
##
6+
## Configuration Variables
7+
##
8+
9+
SCHEMES="$@"
10+
11+
config ()
12+
{
13+
# The workspace to build.
14+
#
15+
# If not set and no workspace is found, the -workspace flag will not be passed
16+
# to `xctool`.
17+
#
18+
# Only one of `XCWORKSPACE` and `XCODEPROJ` needs to be set. The former will
19+
# take precedence.
20+
: ${XCWORKSPACE=$(find_pattern "*.xcworkspace")}
21+
22+
# The project to build.
23+
#
24+
# If not set and no project is found, the -project flag will not be passed
25+
# to `xctool`.
26+
#
27+
# Only one of `XCWORKSPACE` and `XCODEPROJ` needs to be set. The former will
28+
# take precedence.
29+
: ${XCODEPROJ=$(find_pattern "*.xcodeproj")}
30+
31+
# A bootstrap script to run before building.
32+
#
33+
# If this file does not exist, it is not considered an error.
34+
: ${BOOTSTRAP="$SCRIPT_DIR/bootstrap"}
35+
36+
# Extra options to pass to xctool.
37+
: ${XCTOOL_OPTIONS="RUN_CLANG_STATIC_ANALYZER=NO"}
38+
39+
# A whitespace-separated list of default schemes to build.
40+
#
41+
# Individual names can be quoted to avoid word splitting.
42+
: ${SCHEMES:=$(xcodebuild -list -project "$XCODEPROJ" 2>/dev/null | awk -f "$SCRIPT_DIR/schemes.awk")}
43+
44+
export XCWORKSPACE
45+
export XCODEPROJ
46+
export BOOTSTRAP
47+
export XCTOOL_OPTIONS
48+
export SCHEMES
49+
}
50+
51+
##
52+
## Build Process
53+
##
54+
55+
main ()
56+
{
57+
config
58+
59+
if [ -f "$BOOTSTRAP" ]
60+
then
61+
echo "*** Bootstrapping..."
62+
"$BOOTSTRAP" || exit $?
63+
fi
64+
65+
echo "*** The following schemes will be built:"
66+
echo "$SCHEMES" | xargs -n 1 echo " "
67+
echo
68+
69+
echo "$SCHEMES" | xargs -n 1 | (
70+
local status=0
71+
72+
while read scheme
73+
do
74+
build_scheme "$scheme" || status=1
75+
done
76+
77+
exit $status
78+
)
79+
}
80+
81+
find_pattern ()
82+
{
83+
ls -d $1 2>/dev/null | head -n 1
84+
}
85+
86+
run_xctool ()
87+
{
88+
if [ -n "$XCWORKSPACE" ]
89+
then
90+
xctool -workspace "$XCWORKSPACE" $XCTOOL_OPTIONS "$@" 2>&1
91+
elif [ -n "$XCODEPROJ" ]
92+
then
93+
xctool -project "$XCODEPROJ" $XCTOOL_OPTIONS "$@" 2>&1
94+
else
95+
echo "*** No workspace or project file found."
96+
exit 1
97+
fi
98+
}
99+
100+
parse_build ()
101+
{
102+
awk -f "$SCRIPT_DIR/xctool.awk" 2>&1 >/dev/null
103+
}
104+
105+
build_scheme ()
106+
{
107+
local scheme=$1
108+
109+
echo "*** Building and testing $scheme..."
110+
echo
111+
112+
local sdkflag=
113+
local action=test
114+
115+
# Determine whether we can run unit tests for this target.
116+
run_xctool -scheme "$scheme" run-tests | parse_build
117+
118+
local awkstatus=$?
119+
120+
if [ "$awkstatus" -eq "1" ]
121+
then
122+
# SDK not found, try for iphonesimulator.
123+
sdkflag="-sdk iphonesimulator"
124+
125+
# Determine whether the unit tests will run with iphonesimulator
126+
run_xctool $sdkflag -scheme "$scheme" run-tests | parse_build
127+
128+
awkstatus=$?
129+
130+
if [ "$awkstatus" -ne "0" ]
131+
then
132+
# Unit tests will not run on iphonesimulator.
133+
sdkflag=""
134+
fi
135+
fi
136+
137+
if [ "$awkstatus" -ne "0" ]
138+
then
139+
# Unit tests aren't supported.
140+
action=build
141+
fi
142+
143+
run_xctool $sdkflag -scheme "$scheme" $action
144+
}
145+
146+
export -f build_scheme
147+
export -f run_xctool
148+
export -f parse_build
149+
150+
main

script/schemes.awk

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
BEGIN {
2+
FS = "\n";
3+
}
4+
5+
/Schemes:/ {
6+
while (getline && $0 != "") {
7+
sub(/^ +/, "");
8+
print "'" $0 "'";
9+
}
10+
}

script/xctool.awk

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Exit statuses:
2+
#
3+
# 0 - No errors found.
4+
# 1 - Wrong SDK. Retry with SDK `iphonesimulator`.
5+
# 2 - Missing target.
6+
7+
BEGIN {
8+
status = 0;
9+
}
10+
11+
{
12+
print;
13+
}
14+
15+
/Testing with the '(.+)' SDK is not yet supported/ {
16+
status = 1;
17+
}
18+
19+
/does not contain a target named/ {
20+
status = 2;
21+
}
22+
23+
END {
24+
exit status;
25+
}

0 commit comments

Comments
 (0)