diff options
author | Dan Albert <danalbert@google.com> | 2018-11-14 13:10:50 -0800 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2018-11-14 13:21:08 -0800 |
commit | 19a85198bf8e119b16d07ec823183f47a144a2e8 (patch) | |
tree | 30ecf1e01287863eb1d5024708f6178844be91ee | |
parent | 2245cc50640cda3d695525a2fdd935f227615af1 (diff) | |
download | binutils-19a85198bf8e119b16d07ec823183f47a144a2e8.tar.gz |
Bootstrap Python 3 for the build.
The Python libraries we depend on from the NDK are now Python 3.
Test: ./build.py --arch arm64 --host linux
Bug: None
Change-Id: I7725069b37be531b43851f7bc37400493cff616d
-rwxr-xr-x | build.py | 263 | ||||
-rwxr-xr-x | do_build.py | 280 |
2 files changed, 294 insertions, 249 deletions
@@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (C) 2017 The Android Open Source Project +# Copyright (C) 2018 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. @@ -14,268 +14,33 @@ # See the License for the specific language governing permissions and # limitations under the License. # -"""Builds binutils.""" -from __future__ import print_function - -import argparse +"""Bootstrapper for do_build.py.""" import logging -import multiprocessing import os -import shutil import site import subprocess +import sys THIS_DIR = os.path.realpath(os.path.dirname(__file__)) -site.addsitedir(os.path.join(THIS_DIR, '../../ndk')) - -# pylint: disable=wrong-import-position -import ndk.abis # pylint: disable=import-error -import ndk.ext.shutil # pylint: disable=import-error -import ndk.paths # pylint: disable=import-error -import ndk.timer # pylint: disable=import-error -# pylint: enable=wrong-import-position - - -def logger(): - """Returns the module level logger.""" - return logging.getLogger(__name__) - - -def makedirs(path): - """os.makedirs with logging.""" - logger().info('makedirs ' + path) - os.makedirs(path) - - -def rmtree(path): - """shutil.rmtree with logging.""" - logger().info('rmtree ' + path) - shutil.rmtree(path) - - -def chdir(path): - """os.chdir with logging.""" - logger().info('chdir ' + path) - os.chdir(path) - - -def install_file(src, dst): - """shutil.copy2 with logging.""" - logger().info('copy %s %s', src, dst) - shutil.copy2(src, dst) - - -def check_call(cmd, *args, **kwargs): - """subprocess.check_call with logging.""" - logger().info('check_call %s', subprocess.list2cmdline(cmd)) - subprocess.check_call(cmd, *args, **kwargs) - - -def configure(arch, host, install_dir, src_dir): - """Configures binutils.""" - is_windows = host in ('win', 'win64') - - configure_host = { - 'darwin': 'x86_64-apple-darwin', - 'linux': 'x86_64-linux-gnu', - 'win': 'i686-w64-mingw32', - 'win64': 'x86_64-w64-mingw32', - }[host] - - sysroot = ndk.paths.sysroot_path(ndk.abis.arch_to_toolchain(arch)) - configure_args = [ - os.path.join(src_dir, 'configure'), - '--target={}'.format(ndk.abis.arch_to_triple(arch)), - '--host={}'.format(configure_host), - '--enable-initfini-array', - '--enable-plugins', - '--enable-threads', - '--disable-nls', - '--with-sysroot={}'.format(sysroot), - '--prefix={}'.format(install_dir), - ] - - if arch == 'arm64': - configure_args.append('--enable-fix-cortex-a53-835769') - configure_args.append('--enable-gold') - else: - # Gold for aarch64 currently emits broken debug info. - # https://issuetracker.google.com/70838247 - configure_args.append('--enable-gold=default') - - env = {} - - m32 = False - if host == 'darwin': - toolchain = ndk.paths.android_path( - 'prebuilts/gcc/darwin-x86/host/i686-apple-darwin-4.2.1') - toolchain_prefix = 'i686-apple-darwin10' - env['MACOSX_DEPLOYMENT_TARGET'] = '10.6' - elif host == 'linux': - toolchain = ndk.paths.android_path( - 'prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8') - toolchain_prefix = 'x86_64-linux' - elif is_windows: - toolchain = ndk.paths.android_path( - 'prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8') - toolchain_prefix = 'x86_64-w64-mingw32' - if host == 'win': - m32 = True - else: - raise NotImplementedError - - cc = os.path.join(toolchain, 'bin', '{}-gcc'.format(toolchain_prefix)) - cxx = os.path.join(toolchain, 'bin', '{}-g++'.format(toolchain_prefix)) - - # Our darwin prebuilts are gcc *only*. No binutils. - if host == 'darwin': - ar = 'ar' - strip = 'strip' - else: - ar = os.path.join(toolchain, 'bin', '{}-ar'.format(toolchain_prefix)) - strip = os.path.join( - toolchain, 'bin', '{}-strip'.format(toolchain_prefix)) - - env['AR'] = ar - env['CC'] = cc - env['CXX'] = cxx - env['STRIP'] = strip - if m32: - env['CFLAGS'] = '-m32' - env['CXXFLAGS'] = '-m32' - env['LDFLAGS'] = '-m32' - else: - env['CFLAGS'] = '-m64' - env['CXXFLAGS'] = '-m64' - env['LDFLAGS'] = '-m64' - - env_args = ['env'] + ['='.join([k, v]) for k, v in env.items()] - check_call(env_args + configure_args) +ANDROID_TOP = os.path.join(THIS_DIR, '../..') -def build(jobs): - """Builds binutils.""" - check_call(['make', '-j', str(jobs)]) - - -def install_winpthreads(is_windows32, install_dir): - """Installs the winpthreads runtime to the Windows bin directory.""" - lib_name = 'libwinpthread-1.dll' - mingw_dir = ndk.paths.android_path( - 'prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8', - 'x86_64-w64-mingw32') - # Yes, this indeed may be found in bin/ because the executables are the - # 64-bit version by default. - pthread_dir = 'lib32' if is_windows32 else 'bin' - lib_path = os.path.join(mingw_dir, pthread_dir, lib_name) - - lib_install = os.path.join(install_dir, 'bin', lib_name) - install_file(lib_path, lib_install) - - -def install(jobs, arch, host, install_dir): - """Installs binutils.""" - check_call(['make', 'install-strip', '-j', str(jobs)]) - - if host in ('win', 'win64'): - arch_install_dir = os.path.join( - install_dir, ndk.abis.arch_to_triple(arch)) - install_winpthreads(host == 'win', install_dir) - install_winpthreads(host == 'win', arch_install_dir) - - -def dist(dist_dir, base_dir, package_name): - """Packages binutils for distribution.""" - has_pbzip2 = ndk.ext.shutil.which('pbzip2') is not None - if has_pbzip2: - compress_arg = '--use-compress-prog=pbzip2' - else: - compress_arg = '-j' - - package_path = os.path.join(dist_dir, package_name + '.tar.bz2') - cmd = [ - 'tar', compress_arg, '-cf', package_path, '-C', base_dir, package_name, - ] - subprocess.check_call(cmd) - - -def parse_args(): - """Parse command line arguments.""" - parser = argparse.ArgumentParser() - - parser.add_argument( - '--arch', choices=ndk.abis.ALL_ARCHITECTURES, required=True) - parser.add_argument( - '--host', choices=('darwin', 'linux', 'win', 'win64'), required=True) - - parser.add_argument( - '--clean', action='store_true', - help='Clean the out directory before building.') - parser.add_argument( - '-j', '--jobs', type=int, default=multiprocessing.cpu_count(), - help='Number of jobs to use when building.') - - return parser.parse_args() +site.addsitedir(os.path.join(ANDROID_TOP, 'ndk')) +import bootstrap # pylint: disable=import-error,wrong-import-position def main(): - """Program entry point.""" - args = parse_args() - logging.basicConfig(level=logging.INFO) - - total_timer = ndk.timer.Timer() - total_timer.start() - - out_dir = ndk.paths.get_out_dir() - dist_dir = ndk.paths.get_dist_dir(out_dir) - base_build_dir = os.path.join( - out_dir, 'binutils', args.host, args.arch) - build_dir = os.path.join(base_build_dir, 'build') - package_name = 'binutils-{}-{}'.format(args.arch, args.host) - install_dir = os.path.join(base_build_dir, 'install', package_name) - binutils_path = os.path.join(THIS_DIR, 'binutils-2.27') - - did_clean = False - clean_timer = ndk.timer.Timer() - if args.clean and os.path.exists(build_dir): - did_clean = True - with clean_timer: - rmtree(build_dir) + """Program entry point. - if not os.path.exists(build_dir): - makedirs(build_dir) - - orig_dir = os.getcwd() - chdir(build_dir) - try: - configure_timer = ndk.timer.Timer() - with configure_timer: - configure(args.arch, args.host, install_dir, binutils_path) - - build_timer = ndk.timer.Timer() - with build_timer: - build(args.jobs) - - install_timer = ndk.timer.Timer() - with install_timer: - install(args.jobs, args.arch, args.host, install_dir) - finally: - chdir(orig_dir) - - package_timer = ndk.timer.Timer() - with package_timer: - dist(dist_dir, os.path.dirname(install_dir), package_name) - - total_timer.finish() + Bootstraps the do_build.py with Python 3. + """ + logging.basicConfig(level=logging.INFO) - if did_clean: - print('Clean: {}'.format(clean_timer.duration)) - print('Configure: {}'.format(configure_timer.duration)) - print('Build: {}'.format(build_timer.duration)) - print('Install: {}'.format(install_timer.duration)) - print('Package: {}'.format(package_timer.duration)) - print('Total: {}'.format(total_timer.duration)) + bootstrap.bootstrap() + subprocess.check_call( + ['python3', os.path.join(THIS_DIR, 'do_build.py')] + + sys.argv[1:]) if __name__ == '__main__': diff --git a/do_build.py b/do_build.py new file mode 100755 index 00000000..9e0b41ce --- /dev/null +++ b/do_build.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017 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 binutils.""" +import argparse +import logging +import multiprocessing +import os +import shutil +import site +import subprocess + + +THIS_DIR = os.path.realpath(os.path.dirname(__file__)) +site.addsitedir(os.path.join(THIS_DIR, '../../ndk')) + +# pylint: disable=wrong-import-position +import ndk.abis # pylint: disable=import-error +import ndk.ext.shutil # pylint: disable=import-error +import ndk.paths # pylint: disable=import-error +import ndk.timer # pylint: disable=import-error +# pylint: enable=wrong-import-position + + +def logger(): + """Returns the module level logger.""" + return logging.getLogger(__name__) + + +def makedirs(path): + """os.makedirs with logging.""" + logger().info('makedirs %s', path) + os.makedirs(path) + + +def rmtree(path): + """shutil.rmtree with logging.""" + logger().info('rmtree %s', path) + shutil.rmtree(path) + + +def chdir(path): + """os.chdir with logging.""" + logger().info('chdir %s', path) + os.chdir(path) + + +def install_file(src, dst): + """shutil.copy2 with logging.""" + logger().info('copy %s %s', src, dst) + shutil.copy2(src, dst) + + +def check_call(cmd, *args, **kwargs): + """subprocess.check_call with logging.""" + logger().info('check_call %s', subprocess.list2cmdline(cmd)) + subprocess.check_call(cmd, *args, **kwargs) + + +def configure(arch, host, install_dir, src_dir): + """Configures binutils.""" + is_windows = host in ('win', 'win64') + + configure_host = { + 'darwin': 'x86_64-apple-darwin', + 'linux': 'x86_64-linux-gnu', + 'win': 'i686-w64-mingw32', + 'win64': 'x86_64-w64-mingw32', + }[host] + + sysroot = ndk.paths.sysroot_path(ndk.abis.arch_to_toolchain(arch)) + configure_args = [ + os.path.join(src_dir, 'configure'), + '--target={}'.format(ndk.abis.arch_to_triple(arch)), + '--host={}'.format(configure_host), + '--enable-initfini-array', + '--enable-plugins', + '--enable-threads', + '--disable-nls', + '--with-sysroot={}'.format(sysroot), + '--prefix={}'.format(install_dir), + ] + + if arch == 'arm64': + configure_args.append('--enable-fix-cortex-a53-835769') + configure_args.append('--enable-gold') + else: + # Gold for aarch64 currently emits broken debug info. + # https://issuetracker.google.com/70838247 + configure_args.append('--enable-gold=default') + + env = {} + + m32 = False + if host == 'darwin': + toolchain = ndk.paths.android_path( + 'prebuilts/gcc/darwin-x86/host/i686-apple-darwin-4.2.1') + toolchain_prefix = 'i686-apple-darwin10' + env['MACOSX_DEPLOYMENT_TARGET'] = '10.6' + elif host == 'linux': + toolchain = ndk.paths.android_path( + 'prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8') + toolchain_prefix = 'x86_64-linux' + elif is_windows: + toolchain = ndk.paths.android_path( + 'prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8') + toolchain_prefix = 'x86_64-w64-mingw32' + if host == 'win': + m32 = True + else: + raise NotImplementedError + + cc = os.path.join(toolchain, 'bin', '{}-gcc'.format(toolchain_prefix)) + cxx = os.path.join(toolchain, 'bin', '{}-g++'.format(toolchain_prefix)) + + # Our darwin prebuilts are gcc *only*. No binutils. + if host == 'darwin': + ar = 'ar' + strip = 'strip' + else: + ar = os.path.join(toolchain, 'bin', '{}-ar'.format(toolchain_prefix)) + strip = os.path.join( + toolchain, 'bin', '{}-strip'.format(toolchain_prefix)) + + env['AR'] = ar + env['CC'] = cc + env['CXX'] = cxx + env['STRIP'] = strip + if m32: + env['CFLAGS'] = '-m32' + env['CXXFLAGS'] = '-m32' + env['LDFLAGS'] = '-m32' + else: + env['CFLAGS'] = '-m64' + env['CXXFLAGS'] = '-m64' + env['LDFLAGS'] = '-m64' + + env_args = ['env'] + ['='.join([k, v]) for k, v in env.items()] + check_call(env_args + configure_args) + + +def build(jobs): + """Builds binutils.""" + check_call(['make', '-j', str(jobs)]) + + +def install_winpthreads(is_windows32, install_dir): + """Installs the winpthreads runtime to the Windows bin directory.""" + lib_name = 'libwinpthread-1.dll' + mingw_dir = ndk.paths.android_path( + 'prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8', + 'x86_64-w64-mingw32') + # Yes, this indeed may be found in bin/ because the executables are the + # 64-bit version by default. + pthread_dir = 'lib32' if is_windows32 else 'bin' + lib_path = os.path.join(mingw_dir, pthread_dir, lib_name) + + lib_install = os.path.join(install_dir, 'bin', lib_name) + install_file(lib_path, lib_install) + + +def install(jobs, arch, host, install_dir): + """Installs binutils.""" + check_call(['make', 'install-strip', '-j', str(jobs)]) + + if host in ('win', 'win64'): + arch_install_dir = os.path.join( + install_dir, ndk.abis.arch_to_triple(arch)) + install_winpthreads(host == 'win', install_dir) + install_winpthreads(host == 'win', arch_install_dir) + + +def dist(dist_dir, base_dir, package_name): + """Packages binutils for distribution.""" + has_pbzip2 = ndk.ext.shutil.which('pbzip2') is not None + if has_pbzip2: + compress_arg = '--use-compress-prog=pbzip2' + else: + compress_arg = '-j' + + package_path = os.path.join(dist_dir, package_name + '.tar.bz2') + cmd = [ + 'tar', compress_arg, '-cf', package_path, '-C', base_dir, package_name, + ] + subprocess.check_call(cmd) + + +def parse_args(): + """Parse command line arguments.""" + parser = argparse.ArgumentParser() + + parser.add_argument( + '--arch', choices=ndk.abis.ALL_ARCHITECTURES, required=True) + parser.add_argument( + '--host', choices=('darwin', 'linux', 'win', 'win64'), required=True) + + parser.add_argument( + '--clean', action='store_true', + help='Clean the out directory before building.') + parser.add_argument( + '-j', '--jobs', type=int, default=multiprocessing.cpu_count(), + help='Number of jobs to use when building.') + + return parser.parse_args() + + +def main(): + """Program entry point.""" + args = parse_args() + logging.basicConfig(level=logging.INFO) + + total_timer = ndk.timer.Timer() + total_timer.start() + + out_dir = ndk.paths.get_out_dir() + dist_dir = ndk.paths.get_dist_dir(out_dir) + base_build_dir = os.path.join( + out_dir, 'binutils', args.host, args.arch) + build_dir = os.path.join(base_build_dir, 'build') + package_name = 'binutils-{}-{}'.format(args.arch, args.host) + install_dir = os.path.join(base_build_dir, 'install', package_name) + binutils_path = os.path.join(THIS_DIR, 'binutils-2.27') + + did_clean = False + clean_timer = ndk.timer.Timer() + if args.clean and os.path.exists(build_dir): + did_clean = True + with clean_timer: + rmtree(build_dir) + + if not os.path.exists(build_dir): + makedirs(build_dir) + + orig_dir = os.getcwd() + chdir(build_dir) + try: + configure_timer = ndk.timer.Timer() + with configure_timer: + configure(args.arch, args.host, install_dir, binutils_path) + + build_timer = ndk.timer.Timer() + with build_timer: + build(args.jobs) + + install_timer = ndk.timer.Timer() + with install_timer: + install(args.jobs, args.arch, args.host, install_dir) + finally: + chdir(orig_dir) + + package_timer = ndk.timer.Timer() + with package_timer: + dist(dist_dir, os.path.dirname(install_dir), package_name) + + total_timer.finish() + + if did_clean: + print('Clean: {}'.format(clean_timer.duration)) + print('Configure: {}'.format(configure_timer.duration)) + print('Build: {}'.format(build_timer.duration)) + print('Install: {}'.format(install_timer.duration)) + print('Package: {}'.format(package_timer.duration)) + print('Total: {}'.format(total_timer.duration)) + + +if __name__ == '__main__': + main() |