summaryrefslogtreecommitdiff
path: root/build-kernel.sh
blob: c7e6c8042c5734302609e368f0608c7f96a9ea61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
#!/bin/sh
#
# A small script used to rebuild the Android goldfish kernel image
# See docs/KERNEL.TXT for usage instructions.
#

export LANG=C
export LC_ALL=C

PROGNAME=$(basename "$0")

MACHINE=goldfish
VARIANT=goldfish
OUTPUT=/tmp/kernel-qemu
CROSSPREFIX=arm-linux-androideabi-
CONFIG=goldfish
GCC_VERSION=4.9

VALID_ARCHS="arm x86 x86_64 mips arm64 mips64"

# Determine the host architecture, and which default prebuilt tag we need.
# For the toolchain auto-detection.
#
HOST_OS=`uname -s`
case "$HOST_OS" in
    Darwin)
        HOST_OS=darwin
        HOST_TAG=darwin-x86
        BUILD_NUM_CPUS=$(sysctl -n hw.ncpu)
        ;;
    Linux)
        # note that building  32-bit binaries on x86_64 is handled later
        HOST_OS=linux
        HOST_TAG=linux-x86
        BUILD_NUM_CPUS=$(grep -c processor /proc/cpuinfo)
        ;;
    *)
        echo "ERROR: Unsupported OS: $HOST_OS"
        exit 1
esac

# Default number of parallel jobs during the build: cores * 2
JOBS=$(( $BUILD_NUM_CPUS * 2 ))

ARCH=arm

OPTION_HELP=no
OPTION_ARMV7=yes
OPTION_OUT=
OPTION_CROSS=
OPTION_ARCH=
OPTION_CONFIG=
OPTION_SAVEDEFCONFIG=no
OPTION_JOBS=
OPTION_VERBOSE=
OPTION_GCC_VERSION=
CCACHE=

case "$USE_CCACHE" in
    "")
        CCACHE=
        ;;
    *)
        # use ccache bundled in AOSP source tree
        CCACHE=${ANDROID_BUILD_TOP:-$(dirname $0)/../..}/prebuilts/misc/$HOST_TAG/ccache/ccache
        [ -x $CCACHE ] || CCACHE=
        ;;
esac

for opt do
    optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
    case $opt in
    --help|-h|-\?) OPTION_HELP=yes
        ;;
    --arch=*)
        OPTION_ARCH=$optarg
        ;;
    --armv5)
        OPTION_ARMV7=no
        ;;
    --armv7)
        OPTION_ARMV7=yes
        ;;
    --ccache=*)
        CCACHE=$optarg
        ;;
    --config=*)
        OPTION_CONFIG=$optarg
        ;;
    --cross=*)
        OPTION_CROSS=$optarg
        ;;
    --gcc-version=*)
        OPTION_GCC_VERSION=$optarg
        ;;
    -j*|--jobs=*)
        OPTION_JOBS=$optarg
        ;;
    --out=*)
        OPTION_OUT=$optarg
        ;;
    --savedefconfig)
        OPTION_SAVEDEFCONFIG=yes
        ;;
    --verbose)
        OPTION_VERBOSE=true
        ;;
    *)
        echo "unknown option '$opt', use --help"
        exit 1
    esac
done

if [ $OPTION_HELP = "yes" ] ; then
    echo "Rebuild the prebuilt kernel binary for Android's emulator."
    echo ""
    echo "options (defaults are within brackets):"
    echo ""
    echo "  --help                   print this message"
    echo "  --arch=<arch>            change target architecture [$ARCH]"
    echo "  --armv5                  build ARMv5 binaries"
    echo "  --armv7                  build ARMv7 binaries (default. see note below)"
    echo "  --out=<directory>        output directory [$OUTPUT]"
    echo "  --cross=<prefix>         cross-toolchain prefix [$CROSSPREFIX]"
    echo "  --config=<name>          kernel config name [$CONFIG]"
    echo "  --savedefconfig          run savedefconfig"
    echo "  --ccache=<path>          use compiler cache [${CCACHE:-not set}]"
    echo "  --gcc-version=<version>  use specific GCC version [$GCC_VERSION]"
    echo "  --verbose                show build commands"
    echo "  -j<number>               launch <number> parallel build jobs [$JOBS]"
    echo ""
    echo "NOTE: --armv7 is equivalent to --config=goldfish_armv7. It is"
    echo "      ignored if --config=<name> is used."
    echo ""
    exit 0
fi

if [ ! -f include/linux/vermagic.h ]; then
    echo "ERROR: You must be in the top-level kernel source directory to run this script."
    exit 1
fi

# Extract kernel version, we'll need to put this in the final binaries names
# to ensure the emulator can trivially know it without probing the binary with
# 'file' or other unreliable heuristics.
KERNEL_MAJOR=$(awk '$1 == "VERSION" { print $3; }' Makefile)
KERNEL_MINOR=$(awk '$1 == "PATCHLEVEL" { print $3; }' Makefile)
KERNEL_PATCH=$(awk '$1 == "SUBLEVEL" { print $3; }' Makefile)
KERNEL_VERSION="$KERNEL_MAJOR.$KERNEL_MINOR.$KERNEL_PATCH"
echo "Found kernel version: $KERNEL_VERSION"

if [ -n "$OPTION_ARCH" ]; then
    ARCH=$OPTION_ARCH
fi

if [ -n "$OPTION_GCC_VERSION" ]; then
    GCC_VERSION=$OPTION_GCC_VERSION
else
    if [ "$ARCH" = "x86" ]; then
        # Work-around a nasty bug.
        # Hence 132637 is 2.6.29.
        if [ "$KERNEL_VERSION" = "2.6.29" ]; then
            GCC_VERSION=4.6
            echo "WARNING: android-goldfish-$KERNEL_VERSION doesn't build --arch=$ARCH with GCC 4.7"
        fi
    fi
    if [ "$ARCH" = "arm64" ]; then
        # There is no GCC 4.7 toolchain to build AARCH64 binaries.
        GCC_VERSION=4.8
    fi
    if [ "$ARCH" = "mips64" ]; then
        GCC_VERSION=4.9
    fi
    if [ "$ARCH" = "mips" ]; then
        GCC_VERSION=4.9
    fi
    echo "Autoconfig: --gcc-version=$GCC_VERSION"
fi

if [ -n "$OPTION_CONFIG" ]; then
    CONFIG=$OPTION_CONFIG
else
    case $ARCH in
        arm)
            CONFIG=goldfish_armv7
            if  [ "$OPTION_ARMV7" = "no" ]; then
                CONFIG=goldfish
            fi
            ;;
        x86)
            # Warning: this is ambiguous, should be 'goldfish' before 3.10,
            # and 'i386_emu" after it.
            if [ -f "arch/x86/configs/i386_emu_defconfig" ]; then
                CONFIG=i386_emu
            else
                CONFIG=goldfish
            fi
            ;;
        x86_64)
            CONFIG=x86_64_emu
            ;;
        mips)
            CONFIG=goldfish
            ;;
        mips64)
            CONFIG=ranchu64
            ;;
        arm64)
            CONFIG=ranchu
            ;;
        *)
            echo "ERROR: Invalid arch '$ARCH', try one of $VALID_ARCHS"
            exit 1
    esac
    echo "Auto-config: --config=$CONFIG"
fi

# Check output directory.
if [ -n "$OPTION_OUT" ] ; then
    if [ ! -d "$OPTION_OUT" ] ; then
        echo "Output directory '$OPTION_OUT' does not exist ! Aborting."
        exit 1
    fi
    OUTPUT=$OPTION_OUT
else
    OUTPUT=$OUTPUT/${ARCH}-${KERNEL_VERSION}
    case $CONFIG in
        vbox*)
            OUTPUT=${OUTPUT}-vbox
            ;;
        goldfish)
            if [ "$ARCH" = "arm" ]; then
                OUTPUT=${OUTPUT}-armv5
            fi
            ;;
    esac
    echo "Auto-config: --out=$OUTPUT"
    mkdir -p $OUTPUT
fi

if [ -n "$OPTION_CROSS" ] ; then
    CROSSPREFIX="$OPTION_CROSS"
    CROSSTOOLCHAIN=${CROSSPREFIX}$GCC_VERSION
else
    case $ARCH in
        arm)
            CROSSPREFIX=arm-linux-androideabi-
            ;;
        x86)
            CROSSPREFIX=x86_64-linux-android-
            # NOTE: kernel-toolchain/toolbox.sh will add -m32
            ;;
        x86_64)
            CROSSPREFIX=x86_64-linux-android-
            ;;
        mips)
            CROSSPREFIX=mips64el-linux-android-
            ;;
        mips64)
            CROSSPREFIX=mips64el-linux-android-
            ;;
        arm64)
            CROSSPREFIX=aarch64-linux-android-
            ;;
        *)
            echo "ERROR: Unsupported architecture!"
            exit 1
            ;;
    esac
    CROSSTOOLCHAIN=${CROSSPREFIX}$GCC_VERSION
    echo "Auto-config: --cross=$CROSSPREFIX"
fi

ZIMAGE=zImage

case $ARCH in
    x86|x86_64)
        ZIMAGE=bzImage
        ;;
    arm64)
        ZIMAGE=Image
        ;;
    mips)
        ZIMAGE=
        ;;
    mips64)
        ZIMAGE=
        ;;
esac

# If the cross-compiler is not in the path, try to find it automatically
CROSS_COMPILER="${CROSSPREFIX}gcc"
CROSS_COMPILER_VERSION=$($CROSS_COMPILER --version 2>/dev/null)
if [ $? != 0 ] ; then
    BUILD_TOP=$ANDROID_BUILD_TOP
    if [ -z "$BUILD_TOP" ]; then
        # Assume this script is under external/qemu/distrib/ in the
        # Android source tree.
        BUILD_TOP=$(dirname $0)/../..
        if [ ! -d "$BUILD_TOP/prebuilts" ]; then
            BUILD_TOP=
        else
            BUILD_TOP=$(cd $BUILD_TOP && pwd)
        fi
    fi
    case $ARCH in
        x86_64)
            # x86_46 binaries are under prebuilts/gcc/<host>/x86 !!
            PREBUILT_ARCH=x86
            ;;
        arm64)
            PREBUILT_ARCH=aarch64
            ;;
        mips64)
            PREBUILT_ARCH=mips
            ;;
        *)
            PREBUILT_ARCH=$ARCH
            ;;
    esac
    CROSSPREFIX=$BUILD_TOP/prebuilts/gcc/$HOST_TAG/$PREBUILT_ARCH/$CROSSTOOLCHAIN/bin/$CROSSPREFIX
    echo "Checking for ${CROSSPREFIX}gcc"
    if [ "$BUILD_TOP" -a -f ${CROSSPREFIX}gcc ]; then
        echo "Auto-config: --cross=$CROSSPREFIX"
    else
        echo "It looks like $CROSS_COMPILER is not in your path ! Aborting."
        exit 1
    fi
fi

if [ "$CCACHE" ] ; then
    echo "Using ccache program: $CCACHE"
    CROSSPREFIX="$CCACHE $CROSSPREFIX"
fi

export CROSS_COMPILE="$CROSSPREFIX" ARCH SUBARCH=$ARCH

if [ "$OPTION_JOBS" ]; then
    JOBS=$OPTION_JOBS
else
    echo "Auto-config: -j$JOBS"
fi


# Special magic redirection with our magic toolbox script
# This is needed to add extra compiler flags to compiler.
# See kernel-toolchain/android-kernel-toolchain-* for details
#
export REAL_CROSS_COMPILE="$CROSS_COMPILE"
CROSS_COMPILE=$(dirname "$0")/kernel-toolchain/android-kernel-toolchain-

MAKE_FLAGS=
if [ "$OPTION_VERBOSE" ]; then
  MAKE_FLAGS="$MAKE_FLAGS V=1"
fi

case $CONFIG in
    defconfig)
        MAKE_DEFCONFIG=$CONFIG
        ;;
    *)
        MAKE_DEFCONFIG=${CONFIG}_defconfig
        ;;
esac

ORG_ARCH=$ARCH
case $ARCH in
    mips64)
        # MIPS64 Kernel code base is under arch/mips
        ARCH=mips
        ;;
esac

# Do the build
#
rm -f include/asm &&
make $MAKE_DEFCONFIG &&    # configure the kernel
make -j$JOBS $MAKE_FLAGS       # build it

if [ $? != 0 ] ; then
    echo "Could not build the kernel. Aborting !"
    exit 1
fi

if [ "$OPTION_SAVEDEFCONFIG" = "yes" ]; then
    case $ARCH in
        x86_64)
            DEFCONFIG_ARCH=x86
            ;;
        *)
            DEFCONFIG_ARCH=$ARCH
            ;;
    esac
    make savedefconfig
    mv -f defconfig arch/$DEFCONFIG_ARCH/configs/${CONFIG}_defconfig
fi

# Note: The exact names of the output files are important for the Android build,
#       do not change the definitions lightly.
KERNEL_PREFIX=kernel-$KERNEL_VERSION

# Naming conventions for the kernel image files:
#
#   1) The kernel image is called kernel-qemu, except for 32-bit ARM
#      where it must be called kernel-qemu-armv7
#
#   2) The debug symbol file is called vmlinux-qemu, except for 32-bit
#      ARM where it must be called vmlinux-qemu-armv7
#
OUTPUT_KERNEL=kernel-qemu
OUTPUT_VMLINUX=vmlinux-qemu
if [ "$CONFIG" = "goldfish_armv7" ]; then
    OUTPUT_KERNEL=${OUTPUT_KERNEL}-armv7
    OUTPUT_VMLINUX=${OUTPUT_VMLINUX}-armv7
fi

cp -f vmlinux $OUTPUT/$OUTPUT_VMLINUX
if [ ! -z $ZIMAGE ]; then
    cp -f arch/$ARCH/boot/$ZIMAGE $OUTPUT/$OUTPUT_KERNEL
else
    cp -f vmlinux $OUTPUT/$OUTPUT_KERNEL
fi
echo "Kernel $CONFIG prebuilt images ($OUTPUT_KERNEL and $OUTPUT_VMLINUX) copied to $OUTPUT successfully !"

cp COPYING $OUTPUT/LINUX_KERNEL_COPYING

cat > $OUTPUT/README <<EOF
This directory contains kernel images to be used with the Android emulator
program, for the $ORG_ARCH CPU architecture. It was built with the $PROGNAME
script. For more details, read:

  \$AOSP/external/qemu/docs/ANDROID-KERNEL.TXT

EOF

exit 0