4cabc3d by Pete Goodliffe at 2009-12-10 1
#===============================================================================
5b142b3 by Pete Goodliffe at 2009-12-09 2
# Filename:  boost.sh
3
# Author:    Pete Goodliffe
4
# Copyright: (c) Copyright 2009 Pete Goodliffe
3e2e3b2 by Pete Goodliffe at 2009-12-10 5
# Licence:   Please feel free to use this, with attribution
4cabc3d by Pete Goodliffe at 2009-12-10 6
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 7
#
eaf412c by Pete Goodliffe at 2009-12-09 8
# Builds a Boost framework for the iPhone.
e0b6e74 by Pete Goodliffe at 2009-12-09 9
# Creates a set of universal libraries that can be used on an iPhone and in the
3e2e3b2 by Pete Goodliffe at 2009-12-10 10
# iPhone simulator. Then creates a pseudo-framework to make using boost in Xcode
11
# less painful.
e0b6e74 by Pete Goodliffe at 2009-12-09 12
#
eaf412c by Pete Goodliffe at 2009-12-09 13
# To configure the script, define:
e0b6e74 by Pete Goodliffe at 2009-12-09 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)
eaf412c by Pete Goodliffe at 2009-12-09 17
#
18
# Then go get the source tar.bz of the boost you want to build, shove it in the
3e2e3b2 by Pete Goodliffe at 2009-12-10 19
# same directory as this script, and run "./boost.sh". Grab a cuppa. And voila.
4cabc3d by Pete Goodliffe at 2009-12-10 20
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 21
98b5793 by Pete Goodliffe at 2010-09-29 22
: ${BOOST_VERSION:=1_44_0}
eaf412c by Pete Goodliffe at 2009-12-09 23
: ${BOOST_LIBS:="thread signals filesystem regex program_options system"}
98b5793 by Pete Goodliffe at 2010-09-29 24
: ${IPHONE_SDKVERSION:=4.2}
4f9fd2e by Pete Goodliffe at 2010-10-08 25
: ${EXTRA_CPPFLAGS:="-DBOOST_AC_USE_PTHREADS -DBOOST_SP_USE_PTHREADS"}
a019320 by Pete Goodliffe at 2010-09-30 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
e0b6e74 by Pete Goodliffe at 2009-12-09 34
98b5793 by Pete Goodliffe at 2010-09-29 35
: ${TARBALLDIR:=`pwd`}
36
: ${SRCDIR:=`pwd`/src}
e0b6e74 by Pete Goodliffe at 2009-12-09 37
: ${BUILDDIR:=`pwd`/build}
38
: ${PREFIXDIR:=`pwd`/prefix}
eaf412c by Pete Goodliffe at 2009-12-09 39
: ${FRAMEWORKDIR:=`pwd`/framework}
e0b6e74 by Pete Goodliffe at 2009-12-09 40
98b5793 by Pete Goodliffe at 2010-09-29 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
e0b6e74 by Pete Goodliffe at 2009-12-09 51
4cabc3d by Pete Goodliffe at 2009-12-10 52
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 53
eaf412c by Pete Goodliffe at 2009-12-09 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
4cabc3d by Pete Goodliffe at 2009-12-10 64
#===============================================================================
eaf412c by Pete Goodliffe at 2009-12-09 65
# Functions
4cabc3d by Pete Goodliffe at 2009-12-10 66
#===============================================================================
eaf412c by Pete Goodliffe at 2009-12-09 67
e0b6e74 by Pete Goodliffe at 2009-12-09 68
abort()
69
{
70
    echo
71
    echo "Aborted: $@"
72
    exit 1
3e2e3b2 by Pete Goodliffe at 2009-12-10 73
}
74
98b5793 by Pete Goodliffe at 2010-09-29 75
doneSection()
76
{
77
    echo
78
    echo "    ================================================================="
79
    echo "    Done"
80
    echo
81
}
82
4cabc3d by Pete Goodliffe at 2009-12-10 83
#===============================================================================
3e2e3b2 by Pete Goodliffe at 2009-12-10 84
6d9cd5e by Pete Goodliffe at 2010-09-29 85
cleanEverythingReadyToStart()
86
{
f735914 by Pete Goodliffe at 2010-09-30 87
    echo Cleaning everything before we start to build...
6d9cd5e by Pete Goodliffe at 2010-09-29 88
    rm -rf $BOOST_SRC
89
    rm -rf $BUILDDIR
90
    rm -rf $PREFIXDIR
91
    rm -rf $FRAMEWORKDIR
f735914 by Pete Goodliffe at 2010-09-30 92
    doneSection
6d9cd5e by Pete Goodliffe at 2010-09-29 93
}
94
95
#===============================================================================
98b5793 by Pete Goodliffe at 2010-09-29 96
unpackBoost()
3e2e3b2 by Pete Goodliffe at 2009-12-10 97
{
98b5793 by Pete Goodliffe at 2010-09-29 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
e0b6e74 by Pete Goodliffe at 2009-12-09 103
}
104
4cabc3d by Pete Goodliffe at 2009-12-10 105
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 106
107
writeBjamUserConfig()
108
{
3e2e3b2 by Pete Goodliffe at 2009-12-10 109
    # You need to do this to point bjam at the right compiler
98b5793 by Pete Goodliffe at 2010-09-29 110
    # ONLY SEEMS TO WORK IN HOME DIR GRR
e0b6e74 by Pete Goodliffe at 2009-12-09 111
    echo Writing usr-config
98b5793 by Pete Goodliffe at 2010-09-29 112
    #mkdir -p $BUILDDIR
3bdf45e by Pete Goodliffe at 2010-09-29 113
    #cat > ~/user-config.jam <<EOF
114
    cat >> $BOOST_SRC/tools/build/v2/user-config.jam <<EOF
e0b6e74 by Pete Goodliffe at 2009-12-09 115
using darwin : 4.2.1~iphone
a019320 by Pete Goodliffe at 2010-09-30 116
   : /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -arch armv7 -mthumb -fvisibility=hidden -fvisibility-inlines-hidden $EXTRA_CPPFLAGS
e0b6e74 by Pete Goodliffe at 2009-12-09 117
   : <striper>
98b5793 by Pete Goodliffe at 2010-09-29 118
   : <architecture>arm <target-os>iphone
e0b6e74 by Pete Goodliffe at 2009-12-09 119
   ;
120
using darwin : 4.2.1~iphonesim
a019320 by Pete Goodliffe at 2010-09-30 121
   : /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -arch i386 -fvisibility=hidden -fvisibility-inlines-hidden $EXTRA_CPPFLAGS
e0b6e74 by Pete Goodliffe at 2009-12-09 122
   : <striper>
98b5793 by Pete Goodliffe at 2010-09-29 123
   : <architecture>x86 <target-os>iphone
124
   ;
e0b6e74 by Pete Goodliffe at 2009-12-09 125
EOF
98b5793 by Pete Goodliffe at 2010-09-29 126
    doneSection
e0b6e74 by Pete Goodliffe at 2009-12-09 127
}
128
4cabc3d by Pete Goodliffe at 2009-12-10 129
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 130
131
inventMissingHeaders()
132
{
eaf412c by Pete Goodliffe at 2009-12-09 133
    # These files are missing in the ARM iPhoneOS SDK, but they are in the simulator.
3e2e3b2 by Pete Goodliffe at 2009-12-10 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.
e0b6e74 by Pete Goodliffe at 2009-12-09 136
    echo Invent missing headers
98b5793 by Pete Goodliffe at 2010-09-29 137
    cp /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator${IPHONE_SDKVERSION}.sdk/usr/include/{crt_externs,bzlib}.h $BOOST_SRC
e0b6e74 by Pete Goodliffe at 2009-12-09 138
}
139
4cabc3d by Pete Goodliffe at 2009-12-10 140
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 141
98b5793 by Pete Goodliffe at 2010-09-29 142
bootstrapBoost()
e0b6e74 by Pete Goodliffe at 2009-12-09 143
{
98b5793 by Pete Goodliffe at 2010-09-29 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
e0b6e74 by Pete Goodliffe at 2009-12-09 149
}
150
98b5793 by Pete Goodliffe at 2010-09-29 151
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 152
98b5793 by Pete Goodliffe at 2010-09-29 153
buildBoostForiPhoneOS_1_44_0()
e0b6e74 by Pete Goodliffe at 2009-12-09 154
{
98b5793 by Pete Goodliffe at 2010-09-29 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
e0b6e74 by Pete Goodliffe at 2009-12-09 162
}
163
4cabc3d by Pete Goodliffe at 2009-12-10 164
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 165
eaf412c by Pete Goodliffe at 2009-12-09 166
# $1: Name of a boost library to lipoficate (technical term)
e0b6e74 by Pete Goodliffe at 2009-12-09 167
lipoficate()
168
{
169
    : ${1:?}
170
    NAME=$1
171
    echo liboficate: $1
98b5793 by Pete Goodliffe at 2010-09-29 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
e0b6e74 by Pete Goodliffe at 2009-12-09 174
175
    mkdir -p $PREFIXDIR/lib
176
    lipo \
177
        -create \
98b5793 by Pete Goodliffe at 2010-09-29 178
        "$ARMV6" \
179
        "$I386" \
e0b6e74 by Pete Goodliffe at 2009-12-09 180
        -o          "$PREFIXDIR/lib/libboost_$NAME.a" \
181
    || abort "Lipo $1 failed"
182
}
183
eaf412c by Pete Goodliffe at 2009-12-09 184
# This creates universal versions of each individual boost library
e0b6e74 by Pete Goodliffe at 2009-12-09 185
lipoAllBoostLibraries()
186
{
eaf412c by Pete Goodliffe at 2009-12-09 187
    for i in $BOOST_LIBS; do lipoficate $i; done;
98b5793 by Pete Goodliffe at 2010-09-29 188
189
    doneSection
190
}
191
3cf426e by Pete Goodliffe at 2010-09-29 192
scrunchAllLibsTogetherInOneLibPerPlatform()
98b5793 by Pete Goodliffe at 2010-09-29 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
3cf426e by Pete Goodliffe at 2010-09-29 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
84ae3b7 by Pete Goodliffe at 2010-09-29 215
    echo "Decomposing each architecture's .a files"
3cf426e by Pete Goodliffe at 2010-09-29 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; )
e0b6e74 by Pete Goodliffe at 2009-12-09 231
}
232
4cabc3d by Pete Goodliffe at 2009-12-10 233
#===============================================================================
5b142b3 by Pete Goodliffe at 2009-12-09 234
235
                    VERSION_TYPE=Alpha
98b5793 by Pete Goodliffe at 2010-09-29 236
                  FRAMEWORK_NAME=boost
5b142b3 by Pete Goodliffe at 2009-12-09 237
               FRAMEWORK_VERSION=A
238
98b5793 by Pete Goodliffe at 2010-09-29 239
       FRAMEWORK_CURRENT_VERSION=$BOOST_VERSION
240
 FRAMEWORK_COMPATIBILITY_VERSION=$BOOST_VERSION
5b142b3 by Pete Goodliffe at 2009-12-09 241
242
buildFramework()
243
{
eaf412c by Pete Goodliffe at 2009-12-09 244
    FRAMEWORK_BUNDLE=$FRAMEWORKDIR/$FRAMEWORK_NAME.framework
5b142b3 by Pete Goodliffe at 2009-12-09 245
4a8a163 by Pete Goodliffe at 2009-12-10 246
    rm -rf $FRAMEWORK_BUNDLE
247
5b142b3 by Pete Goodliffe at 2009-12-09 248
    echo "Framework: Setting up directories..."
eaf412c by Pete Goodliffe at 2009-12-09 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
5b142b3 by Pete Goodliffe at 2009-12-09 255
256
    echo "Framework: Creating symlinks..."
eaf412c by Pete Goodliffe at 2009-12-09 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
5b142b3 by Pete Goodliffe at 2009-12-09 262
eaf412c by Pete Goodliffe at 2009-12-09 263
    FRAMEWORK_INSTALL_NAME=$FRAMEWORK_BUNDLE/Versions/$FRAMEWORK_VERSION/$FRAMEWORK_NAME
5b142b3 by Pete Goodliffe at 2009-12-09 264
3cf426e by Pete Goodliffe at 2010-09-29 265
    echo "Lipoing library into $FRAMEWORK_INSTALL_NAME..."
eaf412c by Pete Goodliffe at 2009-12-09 266
    lipo \
267
        -create \
3cf426e by Pete Goodliffe at 2010-09-29 268
        -arch armv6 "$BUILDDIR/armv6/libboost.a" \
269
        -arch armv7 "$BUILDDIR/armv7/libboost.a" \
270
        -arch i386  "$BUILDDIR/i386/libboost.a" \
eaf412c by Pete Goodliffe at 2009-12-09 271
        -o          "$FRAMEWORK_INSTALL_NAME" \
272
    || abort "Lipo $1 failed"
5b142b3 by Pete Goodliffe at 2009-12-09 273
274
    echo "Framework: Copying includes..."
eaf412c by Pete Goodliffe at 2009-12-09 275
    cp -r $PREFIXDIR/include/boost/*  $FRAMEWORK_BUNDLE/Headers/
3cf426e by Pete Goodliffe at 2010-09-29 276
5b142b3 by Pete Goodliffe at 2009-12-09 277
    echo "Framework: Creating plist..."
eaf412c by Pete Goodliffe at 2009-12-09 278
    cat > $FRAMEWORK_BUNDLE/Resources/Info.plist <<EOF
5b142b3 by Pete Goodliffe at 2009-12-09 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
98b5793 by Pete Goodliffe at 2010-09-29 300
    doneSection
5b142b3 by Pete Goodliffe at 2009-12-09 301
}
302
4cabc3d by Pete Goodliffe at 2009-12-10 303
#===============================================================================
5b142b3 by Pete Goodliffe at 2009-12-09 304
# Execution starts here
4cabc3d by Pete Goodliffe at 2009-12-10 305
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 306
307
[ -f "$BOOST_TARBALL" ] || abort "Source tarball missing."
308
309
mkdir -p $BUILDDIR
98b5793 by Pete Goodliffe at 2010-09-29 310
311
case $BOOST_VERSION in
312
    1_44_0 )
84ae3b7 by Pete Goodliffe at 2010-09-29 313
        cleanEverythingReadyToStart
314
        unpackBoost
315
        inventMissingHeaders
316
        writeBjamUserConfig
317
        bootstrapBoost
318
        buildBoostForiPhoneOS_1_44_0
3cf426e by Pete Goodliffe at 2010-09-29 319
        scrunchAllLibsTogetherInOneLibPerPlatform
84ae3b7 by Pete Goodliffe at 2010-09-29 320
        lipoAllBoostLibraries
98b5793 by Pete Goodliffe at 2010-09-29 321
        buildFramework
322
        ;;
323
    default )
324
        echo "This version ($BOOST_VERSION) is not supported"
325
        ;;
326
esac
e0b6e74 by Pete Goodliffe at 2009-12-09 327
328
echo "Completed successfully"
329
4cabc3d by Pete Goodliffe at 2009-12-10 330
#===============================================================================
e0b6e74 by Pete Goodliffe at 2009-12-09 331