checkbuild.py 20.6 KB
Newer Older
Dan Albert's avatar
Dan Albert committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#!/usr/bin/env python
#
# Copyright (C) 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Verifies that the build is sane.

Cleans old build artifacts, configures the required environment, determines
build goals, and invokes the build scripts.
"""
22 23
from __future__ import print_function

24
import argparse
25
import collections
26
import datetime
27
import inspect
Dan Albert's avatar
Dan Albert committed
28
import os
29
import shutil
30
import site
Dan Albert's avatar
Dan Albert committed
31 32
import subprocess
import sys
Dan Albert's avatar
Dan Albert committed
33
import tempfile
34
import textwrap
Dan Albert's avatar
Dan Albert committed
35

36 37
site.addsitedir(os.path.join(os.path.dirname(__file__), 'build/lib'))

38
import build_support  # pylint: disable=import-error
39

Dan Albert's avatar
Dan Albert committed
40

41
ALL_MODULES = {
Dan Albert's avatar
Dan Albert committed
42
    'binutils',
43
    'build',
44
    'clang',
Dan Albert's avatar
Dan Albert committed
45
    'cpufeatures',
46
    'gabi++',
47
    'gcc',
Dan Albert's avatar
Dan Albert committed
48
    'gcclibs',
Dan Albert's avatar
Dan Albert committed
49
    'gdbserver',
Dan Albert's avatar
Dan Albert committed
50
    'gnustl',
Dan Albert's avatar
Dan Albert committed
51
    'gtest',
52
    'host-tools',
53
    'libandroid_support',
Dan Albert's avatar
Dan Albert committed
54
    'libc++',
55
    'libc++abi',
56 57
    'native_app_glue',
    'ndk_helper',
Dan Albert's avatar
Dan Albert committed
58
    'platforms',
59
    'python-packages',
Dan Albert's avatar
Dan Albert committed
60
    'stlport',
61
    'system-stl',
62 63 64
}


65 66 67 68 69
class ArgParser(argparse.ArgumentParser):
    def __init__(self):
        super(ArgParser, self).__init__(
            description=inspect.getdoc(sys.modules[__name__]))

70 71 72 73 74
        self.add_argument(
            '--arch',
            choices=('arm', 'arm64', 'mips', 'mips64', 'x86', 'x86_64'),
            help='Build for the given architecture. Build all by default.')

75 76
        package_group = self.add_mutually_exclusive_group()
        package_group.add_argument(
77
            '--package', action='store_true', dest='package', default=True,
Dan Albert's avatar
Dan Albert committed
78
            help='Package the NDK when done building (default).')
79
        package_group.add_argument(
80 81 82
            '--no-package', action='store_false', dest='package',
            help='Do not package the NDK when done building.')

83 84 85 86 87 88 89 90 91 92 93
        test_group = self.add_mutually_exclusive_group()
        test_group.add_argument(
            '--test', action='store_true', dest='test', default=True,
            help=textwrap.dedent("""\
            Run host tests when finished. --package is required. Not supported
            when targeting Windows.
            """))
        test_group.add_argument(
            '--no-test', action='store_false', dest='test',
            help='Do not run host tests when finished.')

94
        self.add_argument(
95
            '--release',
96 97
            help='Release name. Package will be named android-ndk-RELEASE.')

98
        self.add_argument(
Dan Albert's avatar
Dan Albert committed
99
            '--system', choices=('darwin', 'linux', 'windows', 'windows64'),
Dan Albert's avatar
Dan Albert committed
100
            default=build_support.get_default_host(),
101 102
            help='Build for the given OS.')

103
        module_group = self.add_mutually_exclusive_group()
104

105
        module_group.add_argument(
Dan Albert's avatar
Dan Albert committed
106 107
            '--module', choices=sorted(ALL_MODULES),
            help='NDK modules to build.')
108 109 110 111 112 113 114

        module_group.add_argument(
            '--host-only', action='store_true',
            help='Skip building target components.')


def _invoke_build(script, args):
Dan Albert's avatar
Dan Albert committed
115 116
    if args is None:
        args = []
117
    subprocess.check_call([build_support.android_path(script)] + args)
Dan Albert's avatar
Dan Albert committed
118 119


120 121 122
def invoke_build(script, args=None):
    script_path = os.path.join('build/tools', script)
    _invoke_build(build_support.ndk_path(script_path), args)
123

124 125 126

def invoke_external_build(script, args=None):
    _invoke_build(build_support.android_path(script), args)
127 128


129 130 131
def package_ndk(out_dir, dist_dir, args):
    package_args = common_build_args(out_dir, dist_dir, args)
    package_args.append(dist_dir)
132 133 134 135 136 137 138 139

    if args.release is not None:
        package_args.append('--release={}'.format(args.release))

    if args.arch is not None:
        package_args.append('--arch={}'.format(args.arch))

    invoke_build('package.py', package_args)
140 141


142
def test_ndk(out_dir, args):
143 144 145
    release = args.release
    if args.release is None:
        release = datetime.date.today().strftime('%Y%m%d')
146

147 148 149 150
    # The packaging step extracts all the modules to a known directory for
    # packaging. This directory is not cleaned up after packaging, so we can
    # reuse that for testing.
    test_dir = os.path.join(out_dir, 'android-ndk-{}'.format(release))
151

152 153
    test_env = dict(os.environ)
    test_env['NDK'] = test_dir
154

155 156 157
    abis = build_support.ALL_ABIS
    if args.arch is not None:
        abis = build_support.arch_to_abis(args.arch)
158

159 160 161 162 163 164 165 166 167
    results = {}
    for abi in abis:
        cmd = [
            'python', build_support.ndk_path('tests/run-all.py'),
            '--abi', abi, '--suite', 'build'
        ]
        print('Running tests: {}'.format(' '.join(cmd)))
        result = subprocess.call(cmd, env=test_env)
        results[abi] = result == 0
168

169 170 171 172
    print('Results:')
    for abi, result in results.iteritems():
        print('{}: {}'.format(abi, 'PASS' if result else 'FAIL'))
    return all(results.values())
173 174


175 176 177
def common_build_args(out_dir, dist_dir, args):
    build_args = ['--out-dir={}'.format(out_dir)]
    build_args = ['--dist-dir={}'.format(dist_dir)]
Dan Albert's avatar
Dan Albert committed
178
    build_args.append('--host={}'.format(args.system))
179 180 181
    return build_args


Dan Albert's avatar
Dan Albert committed
182 183 184 185 186 187 188 189 190 191 192
def fixup_toolchain_triple(toolchain):
    """Maps toolchain names to their proper triple.

    The x86 toolchains are named stupidly and aren't a proper triple.
    """
    return {
        'x86': 'i686-linux-android',
        'x86_64': 'x86_64-linux-android',
    }.get(toolchain, toolchain)


Dan Albert's avatar
Dan Albert committed
193
def get_binutils_files(triple, has_gold, is_windows):
Dan Albert's avatar
Dan Albert committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
    files = [
        'ld.bfd',
        'nm',
        'as',
        'objcopy',
        'strip',
        'objdump',
        'ld',
        'ar',
        'ranlib',
    ]

    if has_gold:
        files.append('ld.gold')

Dan Albert's avatar
Dan Albert committed
209 210 211
    if is_windows:
        files = [f + '.exe' for f in files]

Dan Albert's avatar
Dan Albert committed
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
    # binutils programs get installed to two locations:
    # 1: $INSTALL_DIR/bin/$TRIPLE-$PROGRAM
    # 2: $INSTALL_DIR/$TRIPLE/bin/$PROGRAM
    #
    # We need to copy both.

    prefixed_files = []
    for file_name in files:
        prefixed_name = '-'.join([triple, file_name])
        prefixed_files.append(os.path.join('bin', prefixed_name))

    dir_prefixed_files = []
    for file_name in files:
        dir_prefixed_files.append(os.path.join(triple, 'bin', file_name))

    ldscripts_dir = os.path.join(triple, 'lib/ldscripts')
    return prefixed_files + dir_prefixed_files + [ldscripts_dir]


def install_file(file_name, src_dir, dst_dir):
    src_file = os.path.join(src_dir, file_name)
    dst_file = os.path.join(dst_dir, file_name)

    print('Copying {} to {}...'.format(src_file, dst_file))
    if os.path.isdir(src_file):
        _install_dir(src_file, dst_file)
    elif os.path.islink(src_file):
        _install_symlink(src_file, dst_file)
    else:
        _install_file(src_file, dst_file)


def _install_dir(src_dir, dst_dir):
    parent_dir = os.path.normpath(os.path.join(dst_dir, '..'))
    if not os.path.exists(parent_dir):
        os.makedirs(parent_dir)
    shutil.copytree(src_dir, dst_dir, symlinks=True)


def _install_symlink(src_file, dst_file):
    dirname = os.path.dirname(dst_file)
    if not os.path.exists(dirname):
        os.makedirs(dirname)
    link_target = os.readlink(src_file)
    os.symlink(link_target, dst_file)


def _install_file(src_file, dst_file):
    dirname = os.path.dirname(dst_file)
    if not os.path.exists(dirname):
        os.makedirs(dirname)
    # copy2 is just copy followed by copystat (preserves file metadata).
    shutil.copy2(src_file, dst_file)


267
def pack_binutils(arch, host_tag, out_dir, binutils_path):
Dan Albert's avatar
Dan Albert committed
268
    archive_name = '-'.join(['binutils', arch, host_tag])
269
    build_support.make_package(archive_name, binutils_path, out_dir)
Dan Albert's avatar
Dan Albert committed
270 271 272 273 274 275 276 277


def get_prebuilt_gcc(host, arch):
    tag = build_support.host_to_tag(host)
    system_subdir = 'prebuilts/ndk/current/toolchains/{}'.format(tag)
    system_path = build_support.android_path(system_subdir)
    toolchain = build_support.arch_to_toolchain(arch)
    toolchain_dir = toolchain + '-4.9'
278
    return os.path.join(system_path, toolchain_dir)
Dan Albert's avatar
Dan Albert committed
279 280


281
def build_binutils(out_dir, dist_dir, args):
Dan Albert's avatar
Dan Albert committed
282 283 284 285 286 287 288 289 290 291 292 293 294
    print('Extracting binutils package from GCC...')

    arches = build_support.ALL_ARCHITECTURES
    if args.arch is not None:
        arches = [args.arch]

    host_tag = build_support.host_to_tag(args.system)

    for arch in arches:
        toolchain = build_support.arch_to_toolchain(arch)
        toolchain_path = get_prebuilt_gcc(args.system, arch)

        triple = fixup_toolchain_triple(toolchain)
Dan Albert's avatar
Dan Albert committed
295

296 297 298 299
        install_dir = os.path.join(out_dir, 'binutils', triple)
        if os.path.exists(install_dir):
            shutil.rmtree(install_dir)
        os.makedirs(install_dir)
Dan Albert's avatar
Dan Albert committed
300

301 302 303 304 305 306
        has_gold = True
        if host_tag == 'windows':
            # Note: 64-bit Windows is fine.
            has_gold = False
        if arch in ('mips', 'mips64'):
            has_gold = False
Dan Albert's avatar
Dan Albert committed
307

308 309 310
        is_windows = host_tag.startswith('windows')
        for file_name in get_binutils_files(triple, has_gold, is_windows):
            install_file(file_name, toolchain_path, install_dir)
311

312 313 314
        license_path = build_support.android_path(
            'toolchain/binutils/binutils-2.25/COPYING')
        shutil.copy2(license_path, os.path.join(install_dir, 'NOTICE'))
Dan Albert's avatar
Dan Albert committed
315

316
        pack_binutils(arch, host_tag, dist_dir, install_dir)
Dan Albert's avatar
Dan Albert committed
317

318 319

def build_clang(out_dir, dist_dir, args):
320
    print('Building Clang...')
321
    invoke_build('build-llvm.py', common_build_args(out_dir, dist_dir, args))
322

323

324
def build_gcc(out_dir, dist_dir, args):
325
    print('Building GCC...')
326
    build_args = common_build_args(out_dir, dist_dir, args)
327 328 329
    if args.arch is not None:
        build_args.append('--arch={}'.format(args.arch))
    invoke_build('build-gcc.py', build_args)
330 331


332
def build_gcc_libs(out_dir, dist_dir, args):
Dan Albert's avatar
Dan Albert committed
333 334 335 336 337 338 339
    print('Packaging GCC libs...')

    arches = build_support.ALL_ARCHITECTURES
    if args.arch is not None:
        arches = [args.arch]

    for arch in arches:
340 341
        toolchain = build_support.arch_to_toolchain(arch)
        triple = fixup_toolchain_triple(toolchain)
342
        libgcc_subdir = 'lib/gcc/{}/4.9'.format(triple)
343 344 345 346 347 348 349 350 351
        is64 = arch.endswith('64')
        libatomic_subdir = '{}/lib{}'.format(triple, '64' if is64 else '')

        lib_names = [
            (libatomic_subdir, 'libatomic.a'),
            (libgcc_subdir, 'libgcc.a'),
        ]

        lib_dirs = ['']
Dan Albert's avatar
Dan Albert committed
352
        if arch == 'arm':
353 354 355 356 357 358
            lib_dirs += [
                'armv7-a',
                'armv7-a/hard',
                'armv7-a/thumb',
                'armv7-a/thumb/hard',
                'thumb',
Dan Albert's avatar
Dan Albert committed
359 360
            ]

361 362 363 364 365
        libs = []
        for lib_dir in lib_dirs:
            for subdir, lib in lib_names:
                libs.append((subdir, os.path.join(lib_dir, lib)))

366 367 368 369
        install_dir = os.path.join(out_dir, 'gcclibs', triple)
        if os.path.exists(install_dir):
            shutil.rmtree(install_dir)
        os.makedirs(install_dir)
Dan Albert's avatar
Dan Albert committed
370

371 372 373 374 375 376 377 378 379 380 381
        # These are target libraries, so the OS we use here is not
        # important. We explicitly use Linux because for whatever reason
        # the Windows aarch64 toolchain doesn't include libatomic.
        gcc_path = get_prebuilt_gcc('linux', arch)
        for gcc_subdir, lib in libs:
            src = os.path.join(gcc_path, gcc_subdir, lib)
            dst = os.path.join(install_dir, lib)
            dst_dir = os.path.dirname(dst)
            if not os.path.exists(dst_dir):
                os.makedirs(dst_dir)
            shutil.copy2(src, dst)
Dan Albert's avatar
Dan Albert committed
382

383 384 385
            shutil.copy2(
                os.path.join(gcc_path, 'NOTICE'),
                os.path.join(install_dir, 'NOTICE'))
386

387 388
        archive_name = os.path.join('gcclibs-' + arch)
        build_support.make_package(archive_name, install_dir, dist_dir)
Dan Albert's avatar
Dan Albert committed
389 390


391 392
def build_host_tools(out_dir, dist_dir, args):
    build_args = common_build_args(out_dir, dist_dir, args)
393

394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
    print('Building ndk-stack...')
    invoke_external_build(
        'ndk/sources/host-tools/ndk-stack/build.py', build_args)

    print('Building ndk-depends...')
    invoke_external_build(
        'ndk/sources/host-tools/ndk-depends/build.py', build_args)

    print('Building awk...')
    invoke_external_build(
        'ndk/sources/host-tools/nawk-20071023/build.py', build_args)

    print('Building make...')
    invoke_external_build(
        'ndk/sources/host-tools/make-3.81/build.py', build_args)
409

410 411 412 413 414 415 416 417 418 419 420 421 422 423
    if args.system in ('windows', 'windows64'):
        print('Building toolbox...')
        invoke_external_build(
            'ndk/sources/host-tools/toolbox/build.py', build_args)

    print('Building Python...')
    invoke_external_build('toolchain/python/build.py', build_args)

    print('Building GDB...')
    invoke_external_build('toolchain/gdb/build.py', build_args)

    print('Building YASM...')
    invoke_external_build('toolchain/yasm/build.py', build_args)

424
    package_host_tools(out_dir, dist_dir, args.system)
Dan Albert's avatar
Dan Albert committed
425 426


427 428 429 430 431 432 433 434 435 436
def merge_license_files(output_path, files):
    licenses = []
    for license_path in files:
        with open(license_path) as license_file:
            licenses.append(license_file.read())

    with open(output_path, 'w') as output_file:
        output_file.write('\n'.join(licenses))


437
def package_host_tools(out_dir, dist_dir, host):
Dan Albert's avatar
Dan Albert committed
438 439 440 441 442 443 444 445 446 447
    packages = [
        'gdb-multiarch-7.10',
        'ndk-awk',
        'ndk-depends',
        'ndk-make',
        'ndk-python',
        'ndk-stack',
        'ndk-yasm',
    ]

448 449 450 451 452 453
    files = [
        'ndk-gdb',
        'ndk-gdb.cmd',
        'ndk-gdb.py',
    ]

Dan Albert's avatar
Dan Albert committed
454 455 456 457 458 459
    if host in ('windows', 'windows64'):
        packages.append('toolbox')

    host_tag = build_support.host_to_tag(host)

    package_names = [p + '-' + host_tag + '.tar.bz2' for p in packages]
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
    for package_name in package_names:
        package_path = os.path.join(out_dir, package_name)
        subprocess.check_call(['tar', 'xf', package_path, '-C', out_dir])

    for f in files:
        shutil.copy2(f, os.path.join(out_dir, 'host-tools/bin'))

    merge_license_files(os.path.join(out_dir, 'host-tools/NOTICE'), [
        build_support.android_path('toolchain/gdb/gdb-7.10/COPYING'),
        build_support.ndk_path('sources/host-tools/nawk-20071023/NOTICE'),
        build_support.ndk_path('sources/host-tools/ndk-depends/NOTICE'),
        build_support.ndk_path('sources/host-tools/make-3.81/COPYING'),
        build_support.android_path(
            'toolchain/python/Python-2.7.5/LICENSE'),
        build_support.ndk_path('sources/host-tools/ndk-stack/NOTICE'),
        build_support.ndk_path('sources/host-tools/toolbox/NOTICE'),
        build_support.android_path('toolchain/yasm/COPYING'),
        build_support.android_path('toolchain/yasm/BSD.txt'),
        build_support.android_path('toolchain/yasm/Artistic.txt'),
        build_support.android_path('toolchain/yasm/GNU_GPL-2.0'),
        build_support.android_path('toolchain/yasm/GNU_LGPL-2.0'),
    ])

    package_name = 'host-tools-' + host_tag
    path = os.path.join(out_dir, 'host-tools')
    build_support.make_package(package_name, path, dist_dir)
Dan Albert's avatar
Dan Albert committed
486

487

488
def build_gdbserver(out_dir, dist_dir, args):
Dan Albert's avatar
Dan Albert committed
489
    print('Building gdbserver...')
490
    build_args = common_build_args(out_dir, dist_dir, args)
Dan Albert's avatar
Dan Albert committed
491 492 493 494 495
    if args.arch is not None:
        build_args.append('--arch={}'.format(args.arch))
    invoke_build('build-gdbserver.py', build_args)


496 497
def _build_stl(out_dir, dist_dir, args, stl):
    build_args = common_build_args(out_dir, dist_dir, args)
Dan Albert's avatar
Dan Albert committed
498 499
    if args.arch is not None:
        build_args.append('--arch={}'.format(args.arch))
500 501 502 503
    script = 'ndk/sources/cxx-stl/{}/build.py'.format(stl)
    invoke_external_build(script, build_args)


504
def build_gnustl(out_dir, dist_dir, args):
505
    print('Building gnustl...')
506
    _build_stl(out_dir, dist_dir, args, 'gnu-libstdc++')
Dan Albert's avatar
Dan Albert committed
507 508


509
def build_libcxx(out_dir, dist_dir, args):
Dan Albert's avatar
Dan Albert committed
510
    print('Building libc++...')
511
    _build_stl(out_dir, dist_dir, args, 'llvm-libc++')
Dan Albert's avatar
Dan Albert committed
512 513


514
def build_stlport(out_dir, dist_dir, args):
Dan Albert's avatar
Dan Albert committed
515
    print('Building stlport...')
516
    _build_stl(out_dir, dist_dir, args, 'stlport')
Dan Albert's avatar
Dan Albert committed
517

518

519
def build_platforms(out_dir, dist_dir, args):
Dan Albert's avatar
Dan Albert committed
520
    print('Building platforms...')
521 522
    build_args = common_build_args(out_dir, dist_dir, args)
    invoke_build('build-platforms.py', build_args)
523 524


525
def build_cpufeatures(_, dist_dir, __):
526
    path = build_support.ndk_path('sources/android/cpufeatures')
527
    build_support.make_package('cpufeatures', path, dist_dir)
Dan Albert's avatar
Dan Albert committed
528 529


530
def build_native_app_glue(_, dist_dir, __):
531 532
    path = build_support.android_path(
        'development/ndk/sources/android/native_app_glue')
533
    build_support.make_package('native_app_glue', path, dist_dir)
534 535


536
def build_ndk_helper(_, dist_dir, __):
537 538
    path = build_support.android_path(
        'development/ndk/sources/android/ndk_helper')
539
    build_support.make_package('ndk_helper', path, dist_dir)
540 541


542
def build_gtest(_, dist_dir, __):
543
    path = build_support.ndk_path('sources/third_party/googletest')
544
    build_support.make_package('gtest', path, dist_dir)
Dan Albert's avatar
Dan Albert committed
545 546


547
def build_build(_, dist_dir, __):
548
    path = build_support.ndk_path('build')
549
    build_support.make_package('build', path, dist_dir)
550

Dan Albert's avatar
Dan Albert committed
551

552
def build_python_packages(_, dist_dir, __):
553 554 555
    # Stage the files in a temporary directory to make things easier.
    temp_dir = tempfile.mkdtemp()
    try:
556
        path = os.path.join(temp_dir, 'python-packages')
557
        shutil.copytree(
558
            build_support.android_path('development/python-packages'), path)
559
        build_support.make_package('python-packages', path, dist_dir)
560 561 562
    finally:
        shutil.rmtree(temp_dir)

563

564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
def build_gabixx(_out_dir, dist_dir, _args):
    print('Building gabi++...')
    path = build_support.ndk_path('sources/cxx-stl/gabi++')
    build_support.make_package('gabixx', path, dist_dir)


def build_system_stl(_out_dir, dist_dir, _args):
    print('Building system-stl...')
    path = build_support.ndk_path('sources/cxx-stl/system')
    build_support.make_package('system-stl', path, dist_dir)


def build_libandroid_support(_out_dir, dist_dir, _args):
    print('Building libandroid_support...')
    path = build_support.ndk_path('sources/android/support')
    build_support.make_package('libandroid_support', path, dist_dir)


def build_libcxxabi(_out_dir, dist_dir, _args):
    print('Building libc++abi...')
    path = build_support.ndk_path('sources/cxx-stl/llvm-libc++abi')
    build_support.make_package('libcxxabi', path, dist_dir)


Dan Albert's avatar
Dan Albert committed
588
def main():
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
    parser = ArgParser()
    args = parser.parse_args()

    if args.module is None:
        modules = ALL_MODULES
    else:
        modules = {args.module}

    if args.host_only:
        modules = {
            'clang',
            'gcc',
            'host-tools',
        }

    required_package_modules = ALL_MODULES
    if args.package and required_package_modules <= modules:
        do_package = True
    else:
        do_package = False

    # TODO(danalbert): wine?
    # We're building the Windows packages from Linux, so we can't actually run
    # any of the tests from here.
    if args.system.startswith('windows') or not do_package:
        args.test = False
615

616 617 618 619
    # Disable buffering on stdout so the build output doesn't hide all of our
    # "Building..." messages.
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

Dan Albert's avatar
Dan Albert committed
620 621 622 623 624 625
    os.chdir(os.path.dirname(os.path.realpath(__file__)))

    # Set ANDROID_BUILD_TOP.
    if 'ANDROID_BUILD_TOP' not in os.environ:
        os.environ['ANDROID_BUILD_TOP'] = os.path.realpath('..')

626 627
    out_dir = build_support.get_out_dir()
    dist_dir = build_support.get_dist_dir(out_dir)
628 629

    print('Cleaning up...')
630
    invoke_build('dev-cleanup.sh')
631

632
    module_builds = collections.OrderedDict([
Dan Albert's avatar
Dan Albert committed
633
        ('binutils', build_binutils),
634
        ('build', build_build),
635
        ('clang', build_clang),
Dan Albert's avatar
Dan Albert committed
636
        ('cpufeatures', build_cpufeatures),
637
        ('gabi++', build_gabixx),
638
        ('gcc', build_gcc),
Dan Albert's avatar
Dan Albert committed
639
        ('gcclibs', build_gcc_libs),
Dan Albert's avatar
Dan Albert committed
640
        ('gdbserver', build_gdbserver),
Dan Albert's avatar
Dan Albert committed
641
        ('gnustl', build_gnustl),
Dan Albert's avatar
Dan Albert committed
642
        ('gtest', build_gtest),
643
        ('host-tools', build_host_tools),
644
        ('libandroid_support', build_libandroid_support),
Dan Albert's avatar
Dan Albert committed
645
        ('libc++', build_libcxx),
646
        ('libc++abi', build_libcxxabi),
647 648
        ('native_app_glue', build_native_app_glue),
        ('ndk_helper', build_ndk_helper),
Dan Albert's avatar
Dan Albert committed
649
        ('platforms', build_platforms),
650
        ('python-packages', build_python_packages),
Dan Albert's avatar
Dan Albert committed
651
        ('stlport', build_stlport),
652
        ('system-stl', build_system_stl),
653 654 655 656
    ])

    print('Building modules: {}'.format(' '.join(modules)))
    for module in modules:
657
        module_builds[module](out_dir, dist_dir, args)
658

659
    if do_package:
660
        package_ndk(out_dir, dist_dir, args)
Dan Albert's avatar
Dan Albert committed
661

662
    if args.test:
663
        result = test_ndk(out_dir, args)
664 665
        sys.exit(0 if result else 1)

Dan Albert's avatar
Dan Albert committed
666 667 668

if __name__ == '__main__':
    main()