Skip to content
This repository was archived by the owner on Dec 5, 2019. It is now read-only.

Commit c5a6a22

Browse files
committed
Update objc-build-scripts
1 parent 75aff11 commit c5a6a22

File tree

5 files changed

+274
-85
lines changed

5 files changed

+274
-85
lines changed

script/README.md

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,82 @@
1-
These scripts are primarily meant to support the use of
2-
[Janky](https://github.com/github/janky). To use them, read the contents of this
3-
repository into a `script` folder:
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:
464

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

11-
Then commit the changes to incorporate the scripts into your own repository's
71+
Then commit the changes, to incorporate the scripts into your own repository's
1272
history. You can also freely tweak the scripts for your specific project's
1373
needs.
1474

15-
To bring in upstream changes later:
75+
To merge in upstream changes later:
1676

1777
```
1878
$ git fetch -p objc-build-scripts
19-
$ git merge -Xsubtree=script objc-build-scripts/master
79+
$ git merge --ff --squash -Xsubtree=script objc-build-scripts/master
2080
```
81+
82+
[xctool]: https://github.com/facebook/xctool

script/bootstrap

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,73 @@
11
#!/bin/bash
22

3-
SCRIPT_DIR=$(dirname "$0")
4-
cd "$SCRIPT_DIR/.."
3+
export SCRIPT_DIR=$(dirname "$0")
54

6-
set -o errexit
5+
##
6+
## Configuration Variables
7+
##
78

8-
echo "*** Updating submodules..."
9-
git submodule sync --quiet
10-
git submodule update --init
11-
git submodule foreach --recursive --quiet "git submodule sync --quiet && git submodule update --init"
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 2>/dev/null)
32+
if [ -n "$submodules" ]
33+
then
34+
echo "*** Updating submodules..."
35+
update_submodules
36+
fi
37+
}
38+
39+
check_deps ()
40+
{
41+
for tool in $REQUIRED_TOOLS
42+
do
43+
which -s "$tool"
44+
if [ "$?" -ne "0" ]
45+
then
46+
echo "*** Error: $tool not found. Please install it and bootstrap again."
47+
exit 1
48+
fi
49+
done
50+
}
51+
52+
bootstrap_submodule ()
53+
{
54+
local bootstrap="script/bootstrap"
55+
56+
if [ -e "$bootstrap" ]
57+
then
58+
echo "*** Bootstrapping $name..."
59+
"$bootstrap" >/dev/null
60+
else
61+
update_submodules
62+
fi
63+
}
64+
65+
update_submodules ()
66+
{
67+
git submodule sync --quiet && git submodule update --init && git submodule foreach --quiet bootstrap_submodule
68+
}
69+
70+
export -f bootstrap_submodule
71+
export -f update_submodules
72+
73+
main

script/cibuild

Lines changed: 100 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,142 @@
11
#!/bin/bash
22

3-
SCRIPT_DIR=$(dirname "$0")
4-
cd "$SCRIPT_DIR/.."
3+
export SCRIPT_DIR=$(dirname "$0")
54

65
##
76
## Configuration Variables
87
##
98

10-
# The build configuration to use.
11-
if [ -z "$XCCONFIGURATION" ]
12-
then
13-
XCCONFIGURATION="Release"
14-
fi
15-
16-
# The workspace to build.
17-
#
18-
# If not set and no workspace is found, the -workspace flag will not be passed
19-
# to xcodebuild.
20-
if [ -z "$XCWORKSPACE" ]
21-
then
22-
XCWORKSPACE=$(ls -d *.xcworkspace 2>/dev/null | head -n 1)
23-
fi
24-
25-
# A bootstrap script to run before building.
26-
#
27-
# If this file does not exist, it is not considered an error.
28-
BOOTSTRAP="$SCRIPT_DIR/bootstrap"
29-
30-
# A whitespace-separated list of default targets or schemes to build, if none
31-
# are specified on the command line.
32-
#
33-
# Individual names can be quoted to avoid word splitting.
34-
DEFAULT_TARGETS=
35-
36-
# Extra build settings to pass to xcodebuild.
37-
XCODEBUILD_SETTINGS="TEST_AFTER_BUILD=YES"
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 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+
}
3850

3951
##
4052
## Build Process
4153
##
4254

43-
if [ -z "$*" ]
44-
then
45-
# lol recursive shell script
46-
if [ -n "$DEFAULT_TARGETS" ]
55+
main ()
56+
{
57+
config
58+
59+
if [ -f "$BOOTSTRAP" ]
4760
then
48-
echo "$DEFAULT_TARGETS" | xargs "$SCRIPT_DIR/cibuild"
49-
else
50-
xcodebuild -list | awk -f "$SCRIPT_DIR/targets.awk" | xargs "$SCRIPT_DIR/cibuild"
61+
echo "*** Bootstrapping..."
62+
"$BOOTSTRAP" || exit $?
5163
fi
5264

53-
exit $?
54-
fi
55-
56-
if [ -f "$BOOTSTRAP" ]
57-
then
58-
echo "*** Bootstrapping..."
59-
bash "$BOOTSTRAP" || exit $?
60-
fi
65+
echo "*** The following schemes will be built:"
66+
echo "$SCHEMES" | xargs -n 1 echo " "
67+
echo
6168

62-
echo "*** The following targets will be built:"
69+
echo "$SCHEMES" | xargs -n 1 | (
70+
local status=0
6371

64-
for target in "$@"
65-
do
66-
echo "$target"
67-
done
72+
while read scheme
73+
do
74+
build_scheme "$scheme" || status=1
75+
done
6876

69-
echo "*** Cleaning all targets..."
70-
xcodebuild -alltargets clean OBJROOT="$PWD/build" SYMROOT="$PWD/build" $XCODEBUILD_SETTINGS
77+
exit $status
78+
)
79+
}
7180

72-
run_xcodebuild ()
81+
find_pattern ()
7382
{
74-
local scheme=$1
83+
ls -d $1 2>/dev/null | head -n 1
84+
}
7585

86+
run_xctool ()
87+
{
7688
if [ -n "$XCWORKSPACE" ]
7789
then
78-
xcodebuild -workspace "$XCWORKSPACE" -scheme "$scheme" -configuration "$XCCONFIGURATION" build OBJROOT="$PWD/build" SYMROOT="$PWD/build" $XCODEBUILD_SETTINGS
90+
xctool -workspace "$XCWORKSPACE" $XCTOOL_OPTIONS "$@" 2>&1
91+
elif [ -n "$XCODEPROJ" ]
92+
then
93+
xctool -project "$XCODEPROJ" $XCTOOL_OPTIONS "$@" 2>&1
7994
else
80-
xcodebuild -scheme "$scheme" -configuration "$XCCONFIGURATION" build OBJROOT="$PWD/build" SYMROOT="$PWD/build" $XCODEBUILD_SETTINGS
95+
echo "*** No workspace or project file found."
96+
exit 1
8197
fi
98+
}
8299

83-
local status=$?
84-
85-
return $status
100+
parse_build ()
101+
{
102+
awk -f "$SCRIPT_DIR/xctool.awk" 2>&1 >/dev/null
86103
}
87104

88105
build_scheme ()
89106
{
90107
local scheme=$1
91108

92-
run_xcodebuild "$scheme" 2>&1 | awk -f "$SCRIPT_DIR/xcodebuild.awk"
109+
echo "*** Cleaning $scheme..."
110+
run_xctool -scheme "$scheme" clean >/dev/null || exit $?
111+
112+
echo "*** Building and testing $scheme..."
113+
echo
114+
115+
local sdkflag=
116+
local action=test
117+
118+
# Determine whether we can run unit tests for this target.
119+
run_xctool -scheme "$scheme" run-tests | parse_build
93120

94121
local awkstatus=$?
95-
local xcstatus=${PIPESTATUS[0]}
96122

97-
if [ "$xcstatus" -eq "65" ]
123+
if [ "$awkstatus" -ne "0" ]
98124
then
99-
# This probably means that there's no scheme by that name. Give up.
100-
echo "*** Error building scheme $scheme -- perhaps it doesn't exist"
101-
elif [ "$awkstatus" -eq "1" ]
125+
# Unit tests aren't supported.
126+
action=build
127+
fi
128+
129+
if [ "$awkstatus" -eq "1" ]
102130
then
103-
return $awkstatus
131+
# Build for iOS.
132+
sdkflag="-sdk iphonesimulator"
104133
fi
105134

106-
return $xcstatus
135+
run_xctool $sdkflag -scheme "$scheme" $action
107136
}
108137

109-
echo "*** Building..."
138+
export -f build_scheme
139+
export -f run_xctool
140+
export -f parse_build
110141

111-
for scheme in "$@"
112-
do
113-
build_scheme "$scheme" || exit $?
114-
done
142+
main

script/schemes.awk

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

0 commit comments

Comments
 (0)