aboutsummaryrefslogtreecommitdiff
path: root/sources/cxx-stl/llvm-libc++/build.py
blob: cd60c026dda5f83ded9e3a848f3c6430408e28d4 (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
#!/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.
#
"""Builds libc++ for Android."""
from __future__ import print_function

import os
import shutil
import site
import subprocess

THIS_DIR = os.path.realpath(os.path.dirname(__file__))
site.addsitedir(os.path.join(THIS_DIR, '../../../build/lib'))

import build_support  # pylint: disable=import-error


class ArgParser(build_support.ArgParser):
    def __init__(self):  # pylint: disable=super-on-old-class
        super(ArgParser, self).__init__()

        self.add_argument(
            '--arch', choices=build_support.ALL_ARCHITECTURES,
            help='Architectures to build. Builds all if not present.')


def make_linker_script(path, libs):
    with open(path, 'w') as linker_script:
        linker_script.write('INPUT({})\n'.format(' '.join(libs)))


def main(args):
    arches = build_support.ALL_ARCHITECTURES
    if args.arch is not None:
        arches = [args.arch]

    abis = []
    for arch in arches:
        abis.extend(build_support.arch_to_abis(arch))

    ndk_build = build_support.ndk_path('build/ndk-build')
    prebuilt_ndk = build_support.android_path('prebuilts/ndk')
    platform_prebuilts = os.path.join(prebuilt_ndk, 'platform')
    platforms_root = os.path.join(prebuilt_ndk, 'current/platforms')
    unified_sysroot_path = os.path.join(platform_prebuilts, 'sysroot')
    toolchains_root = os.path.join(prebuilt_ndk, 'current/toolchains')
    libcxx_path = build_support.android_path('external/libcxx')
    obj_out = os.path.join(args.out_dir, 'libcxx/obj')

    # TODO(danalbert): Stop building to the source directory.
    # This is historical, and simplifies packaging a bit. We need to pack up
    # all the source as well as the libraries. If build_support.make_package
    # were to change to allow a list of directories instead of one directory,
    # we could make this unnecessary.  Will be a follow up CL.
    lib_out = os.path.join(libcxx_path, 'libs')

    build_cmd = [
        'bash', ndk_build, '-C', THIS_DIR, build_support.jobs_arg(), 'V=1',
        'APP_ABI=' + ' '.join(abis),

        # Use the prebuilt platforms and toolchains.
        'NDK_UNIFIED_SYSROOT_PATH=' + unified_sysroot_path,
        'NDK_PLATFORMS_ROOT=' + platforms_root,
        'NDK_TOOLCHAINS_ROOT=' + toolchains_root,
        'NDK_NEW_TOOLCHAINS_LAYOUT=true',

        # Tell ndk-build where all of our makefiles are and where outputs
        # should go. The defaults in ndk-build are only valid if we have a
        # typical ndk-build layout with a jni/{Android,Application}.mk.
        'NDK_PROJECT_PATH=null',
        'APP_BUILD_SCRIPT=' + os.path.join(libcxx_path, 'Android.mk'),
        'NDK_APPLICATION_MK=' + os.path.join(libcxx_path, 'Application.mk'),
        'NDK_OUT=' + obj_out,
        'NDK_LIBS_OUT=' + lib_out,

        # Make sure we don't pick up a cached copy.
        'LIBCXX_FORCE_REBUILD=true',
    ]
    print('Building libc++ for ABIs: {}'.format(', '.join(abis)))
    print('Running: ' + ' '.join(build_cmd))
    subprocess.check_call(build_cmd)

    # The static libraries are installed to NDK_OUT, not NDK_LIB_OUT, so we
    # need to install them to our package directory.
    for abi in abis:
        static_lib_dir = os.path.join(obj_out, 'local', abi)
        install_dir = os.path.join(lib_out, abi)
        is_arm = abi.startswith('armeabi')

        if is_arm:
            shutil.copy2(
                os.path.join(static_lib_dir, 'libunwind.a'), install_dir)

        shutil.copy2(os.path.join(static_lib_dir, 'libc++abi.a'), install_dir)
        shutil.copy2(
            os.path.join(static_lib_dir, 'libandroid_support.a'), install_dir)
        shutil.copy2(
            os.path.join(static_lib_dir, 'libc++_static.a'), install_dir)

        # Create linker scripts for the libraries we use so that we link things
        # properly even when we're not using ndk-build. The linker will read
        # the script in place of the library so that we link the unwinder and
        # other support libraries appropriately.
        static_libs = ['-lc++_static', '-lc++abi', '-landroid_support']
        if is_arm:
            static_libs.extend(['-lunwind', '-latomic'])
        make_linker_script(os.path.join(install_dir, 'libc++.a'), static_libs)

        shared_libs = ['-landroid_support']
        if is_arm:
            shared_libs.extend(['-lunwind', '-latomic'])
        shared_libs.append('-lc++_shared')
        make_linker_script(os.path.join(install_dir, 'libc++.so'), shared_libs)

    build_support.make_package('libc++', libcxx_path, args.dist_dir)


if __name__ == '__main__':
    build_support.run(main, ArgParser)