1
#===============================================================================
2
# Filename:  boost.sh
3
# Author:    Pete Goodliffe
4
# Copyright: (c) Copyright 2009 Pete Goodliffe
5
# Licence:   Please feel free to use this, with attribution
6
#===============================================================================
7
#
8
# Builds a Boost framework for the iPhone.
9
# Creates a set of universal libraries that can be used on an iPhone and in the
10
# iPhone simulator. Then creates a pseudo-framework to make using boost in Xcode
11
# less painful.
12
#
13
# To configure the script, define:
14
#    BOOST_LIBS:        which libraries to build
15
#    BOOST_VERSION:     version number of the boost library (e.g. 1_41_0)
16
#    IPHONE_SDKVERSION: iPhone SDK version (e.g. 3.0)
17
#
18
# Then go get the source tar.bz of the boost you want to build, shove it in the
19
# same directory as this script, and run "./boost.sh". Grab a cuppa. And voila.
20
#===============================================================================
21
22
: ${BOOST_VERSION:=1_44_0}
23
: ${BOOST_LIBS:="thread signals filesystem regex program_options system"}
24
: ${IPHONE_SDKVERSION:=4.2}
25
: ${EXTRA_CPPFLAGS:="-DBOOST_AC_USE_PTHREADS -DBOOST_SP_USE_PTHREADS"}
26
27
# The EXTRA_CPPFLAGS definition works around a thread race issue in
28
# shared_ptr. I encountered this historically and have not verified that
29
# the fix is no longer required. Without using the posix thread primitives
30
# an invalid compare-and-swap ARM instruction (non-thread-safe) was used for the
31
# shared_ptr use count causing nasty and subtle bugs.
32
#
33
# Should perhaps also consider/use instead: -BOOST_SP_USE_PTHREADS
34
35
: ${TARBALLDIR:=`pwd`}
36
: ${SRCDIR:=`pwd`/src}
37
: ${BUILDDIR:=`pwd`/build}
38
: ${PREFIXDIR:=`pwd`/prefix}
39
: ${FRAMEWORKDIR:=`pwd`/framework}
40
41
BOOST_TARBALL=$TARBALLDIR/boost_$BOOST_VERSION.tar.bz2
42
    BOOST_SRC=$SRCDIR/boost_${BOOST_VERSION}
43
44
#===============================================================================
45
46
ARM_DEV_DIR=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/
47
SIM_DEV_DIR=/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/
48
49
ARM_COMBINED_LIB=$BUILDDIR/lib_boost_arm.a
50
SIM_COMBINED_LIB=$BUILDDIR/lib_boost_x86.a
51
52
#===============================================================================
53
54
echo "BOOST_VERSION:     $BOOST_VERSION"
55
echo "BOOST_LIBS:        $BOOST_LIBS"
56
echo "BOOST_TARBALL:     $BOOST_TARBALL"
57
echo "BOOST_SRC:         $BOOST_SRC"
58
echo "BUILDDIR:          $BUILDDIR"
59
echo "PREFIXDIR:         $PREFIXDIR"
60
echo "FRAMEWORKDIR:      $FRAMEWORKDIR"
61
echo "IPHONE_SDKVERSION: $IPHONE_SDKVERSION"
62
echo
63
64
#===============================================================================
65
# Functions
66
#===============================================================================
67
68
abort()
69
{
70
    echo
71
    echo "Aborted: $@"
72
    exit 1
73
}
74
75
doneSection()
76
{
77
    echo
78
    echo "    ================================================================="
79
    echo "    Done"
80
    echo
81
}
82
83
#===============================================================================
84
85
cleanEverythingReadyToStart()
86
{
87
    echo Cleaning everything before we start to build...
88
    rm -rf $BOOST_SRC
89
    rm -rf $BUILDDIR
90
    rm -rf $PREFIXDIR
91
    rm -rf $FRAMEWORKDIR
92
    doneSection
93
}
94
95
#===============================================================================
96
unpackBoost()
97
{
98
    echo Unpacking boost into $SRCDIR...
99
    [ -d $SRCDIR ]    || mkdir -p $SRCDIR
100
    [ -d $BOOST_SRC ] || ( cd $SRCDIR; tar xfj $BOOST_TARBALL )
101
    [ -d $BOOST_SRC ] && echo "    ...unpacked as $BOOST_SRC"
102
    doneSection
103
}
104
105
#===============================================================================
106
107
writeBjamUserConfig()
108
{
109
    # You need to do this to point bjam at the right compiler
110
    # ONLY SEEMS TO WORK IN HOME DIR GRR
111
    echo Writing usr-config
112
    #mkdir -p $BUILDDIR
113
    #cat > ~/user-config.jam <<EOF
114
    cat >> $BOOST_SRC/tools/build/v2/user-config.jam <<EOF
115
using darwin : 4.2.1~iphone
116
   : /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -arch armv7 -mthumb -fvisibility=hidden -fvisibility-inlines-hidden $EXTRA_CPPFLAGS
117
   : <striper>
118
   : <architecture>arm <target-os>iphone
119
   ;
120
using darwin : 4.2.1~iphonesim
121
   : /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -arch i386 -fvisibility=hidden -fvisibility-inlines-hidden $EXTRA_CPPFLAGS
122
   : <striper>
123
   : <architecture>x86 <target-os>iphone
124
   ;
125
EOF
126
    doneSection
127
}
128
129
#===============================================================================
130
131
inventMissingHeaders()
132
{
133
    # These files are missing in the ARM iPhoneOS SDK, but they are in the simulator.
134
    # They are supported on the device, so we copy them from x86 SDK to a staging area
135
    # to use them on ARM, too.
136
    echo Invent missing headers
137
    cp /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${IPHONE_SDKVERSION}.sdk/usr/include/{crt_externs,bzlib}.h $BOOST_SRC
138
}
139
140
#===============================================================================
141
142
bootstrapBoost()
143
{
144
    cd $BOOST_SRC
145
    BOOST_LIBS_COMMA=$(echo $BOOST_LIBS | sed -e "s/ /,/g")
146
    echo "Bootstrapping (with libs $BOOST_LIBS_COMMA)"
147
    ./bootstrap.sh --with-libraries=$BOOST_LIBS_COMMA
148
    doneSection
149
}
150
151
#===============================================================================
152
153
buildBoostForiPhoneOS_1_44_0()
154
{
155
    cd $BOOST_SRC
156
    
157
    ./bjam --prefix="$PREFIXDIR" toolset=darwin architecture=arm target-os=iphone macosx-version=iphone-${IPHONE_SDKVERSION} define=_LITTLE_ENDIAN link=static install
158
    doneSection
159
160
    ./bjam toolset=darwin architecture=x86 target-os=iphone macosx-version=iphonesim-${IPHONE_SDKVERSION} link=static stage
161
    doneSection
162
}
163
164
#===============================================================================
165
166
# $1: Name of a boost library to lipoficate (technical term)
167
lipoficate()
168
{
169
    : ${1:?}
170
    NAME=$1
171
    echo liboficate: $1
172
    ARMV6=$BOOST_SRC/bin.v2/libs/$NAME/build/darwin-4.2.1~iphone/release/architecture-arm/link-static/macosx-version-iphone-$IPHONE_SDKVERSION/target-os-iphone/threading-multi/libboost_$NAME.a
173
    I386=$BOOST_SRC/bin.v2/libs/$NAME/build/darwin-4.2.1~iphonesim/release/architecture-x86/link-static/macosx-version-iphonesim-$IPHONE_SDKVERSION/target-os-iphone/threading-multi/libboost_$NAME.a
174
175
    mkdir -p $PREFIXDIR/lib
176
    lipo \
177
        -create \
178
        "$ARMV6" \
179
        "$I386" \
180
        -o          "$PREFIXDIR/lib/libboost_$NAME.a" \
181
    || abort "Lipo $1 failed"
182
}
183
184
# This creates universal versions of each individual boost library
185
lipoAllBoostLibraries()
186
{
187
    for i in $BOOST_LIBS; do lipoficate $i; done;
188
189
    doneSection
190
}
191
192
scrunchAllLibsTogetherInOneLibPerPlatform()
193
{
194
    ALL_LIBS_ARM=""
195
    ALL_LIBS_SIM=""
196
    for NAME in $BOOST_LIBS; do
197
        ALL_LIBS_ARM="$ALL_LIBS_ARM $BOOST_SRC/bin.v2/libs/$NAME/build/darwin-4.2.1~iphone/release/architecture-arm/link-static/macosx-version-iphone-$IPHONE_SDKVERSION/target-os-iphone/threading-multi/libboost_$NAME.a";
198
        ALL_LIBS_SIM="$ALL_LIBS_SIM $BOOST_SRC/bin.v2/libs/$NAME/build/darwin-4.2.1~iphonesim/release/architecture-x86/link-static/macosx-version-iphonesim-$IPHONE_SDKVERSION/target-os-iphone/threading-multi/libboost_$NAME.a";
199
    done;
200
201
    mkdir -p $BUILDDIR/armv6/obj
202
    mkdir -p $BUILDDIR/armv7/obj
203
    mkdir -p $BUILDDIR/i386/obj
204
205
    ALL_LIBS=""
206
207
    echo Splitting all existing fat binaries...
208
    for NAME in $BOOST_LIBS; do
209
        ALL_LIBS="$ALL_LIBS libboost_$NAME.a"
210
        lipo "$BOOST_SRC/bin.v2/libs/$NAME/build/darwin-4.2.1~iphone/release/architecture-arm/link-static/macosx-version-iphone-$IPHONE_SDKVERSION/target-os-iphone/threading-multi/libboost_$NAME.a" -thin armv6 -o $BUILDDIR/armv6/libboost_$NAME.a
211
        lipo "$BOOST_SRC/bin.v2/libs/$NAME/build/darwin-4.2.1~iphone/release/architecture-arm/link-static/macosx-version-iphone-$IPHONE_SDKVERSION/target-os-iphone/threading-multi/libboost_$NAME.a" -thin armv7 -o $BUILDDIR/armv7/libboost_$NAME.a
212
        cp "$BOOST_SRC/bin.v2/libs/$NAME/build/darwin-4.2.1~iphonesim/release/architecture-x86/link-static/macosx-version-iphonesim-$IPHONE_SDKVERSION/target-os-iphone/threading-multi/libboost_$NAME.a" $BUILDDIR/i386/
213
    done
214
215
    echo "Decomposing each architecture's .a files"
216
    for NAME in $ALL_LIBS; do
217
        echo Decomposing $NAME...
218
        (cd $BUILDDIR/armv6/obj; ar -x ../$NAME );
219
        (cd $BUILDDIR/armv7/obj; ar -x ../$NAME );
220
        (cd $BUILDDIR/i386/obj; ar -x ../$NAME );
221
    done
222
223
    echo "Linking each architecture into an uberlib ($ALL_LIBS => libboost.a )"
224
    rm $BUILDDIR/*/libboost.a
225
    echo ...armv6
226
    (cd $BUILDDIR/armv6; $ARM_DEV_DIR/ar crus libboost.a obj/*.o; )
227
    echo ...armv7
228
    (cd $BUILDDIR/armv7; $ARM_DEV_DIR/ar crus libboost.a obj/*.o; )
229
    echo ...i386
230
    (cd $BUILDDIR/i386;  $SIM_DEV_DIR/ar crus libboost.a obj/*.o; )
231
}
232
233
#===============================================================================
234
235
                    VERSION_TYPE=Alpha
236
                  FRAMEWORK_NAME=boost
237
               FRAMEWORK_VERSION=A
238
239
       FRAMEWORK_CURRENT_VERSION=$BOOST_VERSION
240
 FRAMEWORK_COMPATIBILITY_VERSION=$BOOST_VERSION
241
242
buildFramework()
243
{
244
    FRAMEWORK_BUNDLE=$FRAMEWORKDIR/$FRAMEWORK_NAME.framework
245
246
    rm -rf $FRAMEWORK_BUNDLE
247
248
    echo "Framework: Setting up directories..."
249
    mkdir -p $FRAMEWORK_BUNDLE
250
    mkdir -p $FRAMEWORK_BUNDLE/Versions
251
    mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION
252
    mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/Resources
253
    mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/Headers
254
    mkdir -p $FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/Documentation
255
256
    echo "Framework: Creating symlinks..."
257
    ln -s $FRAMEWORK_VERSION               $FRAMEWORK_BUNDLE/Versions/Current
258
    ln -s Versions/Current/Headers         $FRAMEWORK_BUNDLE/Headers
259
    ln -s Versions/Current/Resources       $FRAMEWORK_BUNDLE/Resources
260
    ln -s Versions/Current/Documentation   $FRAMEWORK_BUNDLE/Documentation
261
    ln -s Versions/Current/$FRAMEWORK_NAME $FRAMEWORK_BUNDLE/$FRAMEWORK_NAME
262
263
    FRAMEWORK_INSTALL_NAME=$FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/$FRAMEWORK_NAME
264
265
    echo "Lipoing library into $FRAMEWORK_INSTALL_NAME..."
266
    lipo \
267
        -create \
268
        -arch armv6 "$BUILDDIR/armv6/libboost.a" \
269
        -arch armv7 "$BUILDDIR/armv7/libboost.a" \
270
        -arch i386  "$BUILDDIR/i386/libboost.a" \
271
        -o          "$FRAMEWORK_INSTALL_NAME" \
272
    || abort "Lipo $1 failed"
273
274
    echo "Framework: Copying includes..."
275
    cp -r $PREFIXDIR/include/boost/*  $FRAMEWORK_BUNDLE/Headers/
276
277
    echo "Framework: Creating plist..."
278
    cat > $FRAMEWORK_BUNDLE/Resources/Info.plist <<EOF
279
<?xml version="1.0" encoding="UTF-8"?>
280
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
281
<plist version="1.0">
282
<dict>
283
	<key>CFBundleDevelopmentRegion</key>
284
	<string>English</string>
285
	<key>CFBundleExecutable</key>
286
	<string>${FRAMEWORK_NAME}</string>
287
	<key>CFBundleIdentifier</key>
288
	<string>org.boost</string>
289
	<key>CFBundleInfoDictionaryVersion</key>
290
	<string>6.0</string>
291
	<key>CFBundlePackageType</key>
292
	<string>FMWK</string>
293
	<key>CFBundleSignature</key>
294
	<string>????</string>
295
	<key>CFBundleVersion</key>
296
	<string>${FRAMEWORK_CURRENT_VERSION}</string>
297
</dict>
298
</plist>
299
EOF
300
    doneSection
301
}
302
303
#===============================================================================
304
# Execution starts here
305
#===============================================================================
306
307
[ -f "$BOOST_TARBALL" ] || abort "Source tarball missing."
308
309
mkdir -p $BUILDDIR
310
311
case $BOOST_VERSION in
312
    1_44_0 )
313
        cleanEverythingReadyToStart
314
        unpackBoost
315
        inventMissingHeaders
316
        writeBjamUserConfig
317
        bootstrapBoost
318
        buildBoostForiPhoneOS_1_44_0
319
        scrunchAllLibsTogetherInOneLibPerPlatform
320
        lipoAllBoostLibraries
321
        buildFramework
322
        ;;
323
    default )
324
        echo "This version ($BOOST_VERSION) is not supported"
325
        ;;
326
esac
327
328
echo "Completed successfully"
329
330
#===============================================================================