1 #!/usr/bin/env python 2 # 3 # Copyright (C) 2015 The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 # 17 """Builds libc++ for Android.""" 18 from __future__ import print_function 19 20 import os 21 import shutil 22 import site 23 import subprocess 24 25 THIS_DIR = os.path.realpath(os.path.dirname(__file__)) 26 site.addsitedir(os.path.join(THIS_DIR, '../../../build/lib')) 27 28 import build_support # pylint: disable=import-error 29 30 31 class ArgParser(build_support.ArgParser): 32 def __init__(self): # pylint: disable=super-on-old-class 33 super(ArgParser, self).__init__() 34 35 self.add_argument( 36 '--arch', choices=build_support.ALL_ARCHITECTURES, 37 help='Architectures to build. Builds all if not present.') 38 39 40 def main(args): 41 arches = build_support.ALL_ARCHITECTURES 42 if args.arch is not None: 43 arches = [args.arch] 44 45 abis = [] 46 for arch in arches: 47 abis.extend(build_support.arch_to_abis(arch)) 48 49 ndk_build = build_support.ndk_path('build/ndk-build') 50 prebuilt_ndk = build_support.android_path('prebuilts/ndk/current') 51 platforms_root = os.path.join(prebuilt_ndk, 'platforms') 52 toolchains_root = os.path.join(prebuilt_ndk, 'toolchains') 53 libcxx_path = build_support.ndk_path('sources/cxx-stl/llvm-libc++') 54 obj_out = os.path.join(args.out_dir, 'libcxx/obj') 55 56 # TODO(danalbert): Stop building to the source directory. 57 # This is historical, and simplifies packaging a bit. We need to pack up 58 # all the source as well as the libraries. If build_support.make_package 59 # were to change to allow a list of directories instead of one directory, 60 # we could make this unnecessary. Will be a follow up CL. 61 lib_out = os.path.join(libcxx_path, 'libs') 62 63 build_cmd = [ 64 'bash', ndk_build, '-C', THIS_DIR, build_support.jobs_arg(), 'V=1', 65 'APP_ABI=' + ' '.join(abis), 66 67 # Use the prebuilt platforms and toolchains. 68 'NDK_PLATFORMS_ROOT=' + platforms_root, 69 'NDK_TOOLCHAINS_ROOT=' + toolchains_root, 70 'NDK_NEW_TOOLCHAINS_LAYOUT=true', 71 72 # Tell ndk-build where all of our makefiles are and where outputs 73 # should go. The defaults in ndk-build are only valid if we have a 74 # typical ndk-build layout with a jni/{Android,Application}.mk. 75 'NDK_PROJECT_PATH=null', 76 'APP_BUILD_SCRIPT=' + os.path.join(THIS_DIR, 'Android.mk'), 77 'NDK_APPLICATION_MK=' + os.path.join(THIS_DIR, 'Application.mk'), 78 'NDK_OUT=' + obj_out, 79 'NDK_LIBS_OUT=' + lib_out, 80 81 # Make sure we don't pick up a cached copy. 82 'LIBCXX_FORCE_REBUILD=true', 83 84 # Put armeabi-v7a-hard in its own directory. 85 '_NDK_TESTING_ALL_=yes', 86 ] 87 print('Building libc++ for ABIs: {}'.format(', '.join(abis))) 88 subprocess.check_call(build_cmd) 89 90 # The static libraries are installed to NDK_OUT, not NDK_LIB_OUT, so we 91 # need to install them to our package directory. 92 for abi in abis: 93 static_lib_dir = os.path.join(obj_out, 'local', abi) 94 install_dir = os.path.join(lib_out, abi) 95 is_arm = abi.startswith('armeabi') 96 97 if is_arm: 98 shutil.copy2( 99 os.path.join(static_lib_dir, 'libunwind.a'), install_dir) 100 101 shutil.copy2(os.path.join(static_lib_dir, 'libc++abi.a'), install_dir) 102 shutil.copy2( 103 os.path.join(static_lib_dir, 'libandroid_support.a'), install_dir) 104 shutil.copy2( 105 os.path.join(static_lib_dir, 'libc++_static.a'), install_dir) 106 107 build_support.make_package('libcxx', libcxx_path, args.dist_dir) 108 109 110 if __name__ == '__main__': 111 build_support.run(main, ArgParser) 112