diff options
author | Dan Albert <danalbert@google.com> | 2018-08-28 12:42:26 -0700 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2018-08-30 13:01:00 -0700 |
commit | 8d8d7ec9b0da6472079521312532d1d15eece1ed (patch) | |
tree | f091b0121fb0b002be5043b31dc9f016e4c74e88 /checkbuild.py | |
parent | 622f06695746244e9f82b17e5ad56fb16716ea60 (diff) | |
download | ndk-8d8d7ec9b0da6472079521312532d1d15eece1ed.tar.gz |
Install the Just Works toolchain.
Install a copy (we can't remove the old paths until gradle has adapted
to the new layout) of the toolchain/sysroot/etc to $NDK/toolchain such
that it can be invoked without the build system needing to juggle
--sysroot/-gcc-toolchain/etc.
This follows the second approach described on
https://github.com/android-ndk/ndk/issues/780. That is it installs a
full copy of the toolchain rather than installing scripts to refer to
the old toolchain during the transition period.
Test: ./checkbuild.py && ./run_tests.py
Bug: https://github.com/android-ndk/ndk/issues/780
Change-Id: I8d8f10ea6c95378937ac54e440c5e1a9cb3bbeaa
Diffstat (limited to 'checkbuild.py')
-rwxr-xr-x | checkbuild.py | 174 |
1 files changed, 173 insertions, 1 deletions
diff --git a/checkbuild.py b/checkbuild.py index 222a3d1a3..7e0a024f1 100755 --- a/checkbuild.py +++ b/checkbuild.py @@ -27,6 +27,7 @@ from __future__ import unicode_literals import argparse import contextlib import copy +from distutils.dir_util import copy_tree import errno import glob import inspect @@ -406,11 +407,40 @@ def install_gcc_crtbegin(install_path, host, arch, subarch): install_gcc_lib(install_path, host, arch, subarch, subdir, 'crtbegin.o') -def install_libgcc(install_path, host, arch, subarch): +def install_libgcc(install_path, host, arch, subarch, new_layout=False): triple = ndk.abis.arch_to_triple(arch) subdir = os.path.join('lib/gcc', triple, '4.9.x') install_gcc_lib(install_path, host, arch, subarch, subdir, 'libgcc.a') + if new_layout and arch == 'arm': + # For ARM32 we need to use LLVM's libunwind rather than libgcc. + # Unfortunately we still use libgcc for the compiler builtins, so we we + # have to link both. To make sure that the LLVM unwinder gets used, add + # a linker script for libgcc to make sure that libunwind is placed + # first whenever libgcc is used. This also necessitates linking libdl + # since libunwind makes use of dl_iterate_phdr. + # + # Historically we dealt with this in the libc++ linker script, but + # since the new toolchain setup has the toolchain link the STL for us + # the correct way to use the static libc++ is to use + # `-static-libstdc++' which will expand to `-Bstatic -lc++ -Bshared`, + # which results in the static libdl being used. The stub implementation + # of libdl.a causes the unwind to fail, so we can't link libdl there. + # If we don't link it at all, linking fails when building a static + # executable since the driver does not link libdl when building a + # static executable. + # + # We only do this for the new toolchain layout since build systems + # using the legacy toolchain already needed to handle this, and + # -lunwind may not be valid in those configurations (it could have been + # linked by a full path instead). + libgcc_base_path = os.path.join(install_path, subdir, subarch) + libgcc_path = os.path.join(libgcc_base_path, 'libgcc.a') + libgcc_real_path = os.path.join(libgcc_base_path, 'libgcc_real.a') + shutil.move(libgcc_path, libgcc_real_path) + with open(libgcc_path, 'w') as script: + script.write('INPUT(-lunwind -lgcc_real -ldl)') + def install_libatomic(install_path, host, arch, subarch): triple = ndk.abis.arch_to_triple(arch) @@ -1344,6 +1374,147 @@ class Sysroot(ndk.builds.Module): shutil.rmtree(temp_dir) +class Toolchain(ndk.builds.Module): + name = 'toolchain' + path = 'toolchain' + enabled = False + deps = { + 'binutils', + 'clang', + 'libandroid_support', + 'libc++', + 'libc++abi', + 'platforms', + 'sysroot', + 'system-stl', + } + + @property + def notices(self): + return (Binutils().notices + Clang().notices + Libcxx().notices + + Libcxxabi().notices + LibAndroidSupport().notices + + Platforms().notices + Sysroot().notices + SystemStl().notices) + + def build(self, _out_dir, _dist_dir, _args): + pass + + def install(self, out_dir, dist_dir, args): + install_dir = self.get_install_path(out_dir, args.system) + clang_dir = Clang().get_install_path(out_dir, args.system) + platforms_dir = Platforms().get_install_path(out_dir, args.system) + sysroot_dir = Sysroot().get_install_path(out_dir, args.system) + libcxx_dir = Libcxx().get_install_path(out_dir, args.system) + libcxxabi_dir = Libcxxabi().get_install_path(out_dir, args.system) + system_stl_dir = SystemStl().get_install_path(out_dir, args.system) + libandroid_support_dir = LibAndroidSupport().get_install_path( + out_dir, args.system) + + if os.path.exists(install_dir): + shutil.rmtree(install_dir) + + copy_tree(clang_dir, install_dir) + copy_tree(sysroot_dir, os.path.join(install_dir, 'sysroot')) + + arches = build_support.ALL_ARCHITECTURES + if args.arch is not None: + arches = [args.arch] + + for arch in arches: + binutils_dir = Binutils().get_install_path(out_dir, args.system, + arch) + copy_tree(binutils_dir, install_dir) + + # We need to replace libgcc with linker scripts that also use + # libunwind on arm32. We already get libunwind from copying + # binutils, but re-install libgcc so we get the linker scripts. + for subarch in get_subarches(arch): + install_libgcc( + install_dir, args.system, arch, subarch, new_layout=True) + + for api in Platforms().get_apis(): + if api in Platforms.skip_apis: + continue + + platform = 'android-{}'.format(api) + for arch in Platforms().get_arches(api): + triple = ndk.abis.arch_to_triple(arch) + arch_name = 'arch-{}'.format(arch) + lib_dir = 'lib64' if arch == 'x86_64' else 'lib' + src_dir = os.path.join(platforms_dir, platform, arch_name, + 'usr', lib_dir) + dst_dir = os.path.join(install_dir, 'sysroot/usr/lib', triple, + str(api)) + shutil.copytree(src_dir, dst_dir) + + # Also install a libc++.so and libc++.a linker script per API + # level. We need this to be done on a per-API level basis + # because libandroid_support is only used on pre-21 API levels. + static_script = ['-lc++_static', '-lc++abi'] + shared_script = ['-lc++_shared'] + if api < 21: + static_script.append('-landroid_support') + shared_script.insert(0, '-landroid_support') + + libcxx_so_path = os.path.join(dst_dir, 'libc++.so') + with open(libcxx_so_path, 'w') as script: + script.write('INPUT({})'.format(' '.join(shared_script))) + + libcxx_a_path = os.path.join(dst_dir, 'libc++.a') + with open(libcxx_a_path, 'w') as script: + script.write('INPUT({})'.format(' '.join(static_script))) + + # Clang searches for libstdc++ headers at $GCC_PATH/../include/c++. It + # maybe be worth adding a search for the same path within the usual + # sysroot location to centralize these, or possibly just remove them + # from the NDK since they aren't particularly useful anyway. + system_stl_hdr_dir = os.path.join(install_dir, 'include/c++') + os.makedirs(system_stl_hdr_dir) + system_stl_inc_src = os.path.join(system_stl_dir, 'include') + system_stl_inc_dst = os.path.join(system_stl_hdr_dir, '4.9.x') + shutil.copytree(system_stl_inc_src, system_stl_inc_dst) + + libcxx_hdr_dir = os.path.join(install_dir, 'sysroot/usr/include/c++') + os.makedirs(libcxx_hdr_dir) + libcxx_inc_src = os.path.join(libcxx_dir, 'include') + libcxx_inc_dst = os.path.join(libcxx_hdr_dir, 'v1') + shutil.copytree(libcxx_inc_src, libcxx_inc_dst) + + libcxxabi_inc_src = os.path.join(libcxxabi_dir, 'include') + copy_tree(libcxxabi_inc_src, libcxx_inc_dst) + + # $SYSROOT/usr/local/include comes before $SYSROOT/usr/include, so we + # can use that for libandroid_support's headers. Puting them here + # *does* mean that libandroid_support's headers get used even when + # we're not using libandroid_support, but they should be a no-op for + # android-21+ and in the case of pre-21 without libandroid_support + # (libstdc++), we're only degrading the UX; the user will get a linker + # error instead of a compiler error. + support_hdr_dir = os.path.join(install_dir, 'sysroot/usr/local') + os.makedirs(support_hdr_dir) + support_inc_src = os.path.join(libandroid_support_dir, 'include') + support_inc_dst = os.path.join(support_hdr_dir, 'include') + shutil.copytree(support_inc_src, support_inc_dst) + + for arch in arches: + triple = ndk.abis.arch_to_triple(arch) + abi, = ndk.abis.arch_to_abis(arch) + libcxx_lib_dir = os.path.join(libcxx_dir, 'libs', abi) + sysroot_dst = os.path.join(install_dir, 'sysroot/usr/lib', triple) + + libs = [ + 'libc++_shared.so', + 'libc++_static.a', + 'libc++abi.a', + ] + if arch == 'arm': + libs.append('libunwind.a') + if abi in ndk.abis.LP32_ABIS: + libs.append('libandroid_support.a') + + for lib in libs: + shutil.copy2(os.path.join(libcxx_lib_dir, lib), sysroot_dst) + + class Vulkan(ndk.builds.Module): name = 'vulkan' path = 'sources/third_party/vulkan' @@ -1913,6 +2084,7 @@ ALL_MODULES = [ SourceProperties(), Sysroot(), SystemStl(), + Toolchain(), Vulkan(), WrapSh(), ] |