diff --git a/scripts/waifulib/xcompile.py b/scripts/waifulib/xcompile.py index 3244a95..96f9450 100644 --- a/scripts/waifulib/xcompile.py +++ b/scripts/waifulib/xcompile.py @@ -38,16 +38,18 @@ class Android: ndk_rev = 0 is_hardfloat = False clang = False - + def __init__(self, ctx, arch, toolchain, api): self.ctx = ctx + self.api = api + for i in ['ANDROID_NDK_HOME', 'ANDROID_NDK']: self.ndk_home = os.getenv(i) if self.ndk_home != None: break if not self.ndk_home: - conf.fatal('Set ANDROID_NDK_HOME environment variable pointing to the root of Android NDK!') + ctx.fatal('Set ANDROID_NDK_HOME environment variable pointing to the root of Android NDK!') # TODO: this were added at some point of NDK development # but I don't know at which version @@ -64,7 +66,7 @@ class Android: else: self.ndk_rev = 10 - if self.ndk_rev not in [10, 19]: + if self.ndk_rev not in [10, 19, 20]: ctx.fatal('Unknown NDK revision: {}'.format(self.ndk_rev)) self.arch = arch @@ -86,13 +88,18 @@ class Android: elif self.ndk_rev >= 19 and self.api < 16: Logs.warn('API level automatically was set to 16 due to NDK support') self.api = 16 - else: self.api = api self.toolchain_path = self.gen_toolchain_path() # TODO: Crystax support? # TODO: Support for everything else than linux-x86_64? # TODO: Determine if I actually need to implement listed above + def is_host(self): + ''' + Checks if we using host compiler(implies clang) + ''' + return self.toolchain == 'host' + def is_arm(self): ''' Checks if selected architecture is **32-bit** ARM @@ -126,7 +133,16 @@ class Android: def is_hardfp(self): return self.is_hardfloat - def gen_toolchain_path(self): + def ndk_triplet(self): + if self.is_x86(): + triplet = 'i686-linux-android' + elif self.is_arm(): + triplet = 'arm-linux-androideabi' + else: + triplet = self.arch + '-linux-android' + return triplet + + def gen_gcc_toolchain_path(self): path = 'toolchains' if sys.platform.startswith('linux'): @@ -140,7 +156,7 @@ class Android: toolchain_host += '-' # Assuming we are building on x86 - if sys.maxsize > 2**32: + if sys.maxsize > 2**32: toolchain_host += 'x86_64' else: toolchain_host += 'x86' @@ -149,13 +165,6 @@ class Android: raise Exception('Clang is not supported for this NDK') toolchain_folder = 'llvm' - - if self.is_x86(): - triplet = 'i686-linux-android{}-'.format(self.api) - elif self.is_arm(): - triplet = 'armv7a-linux-androideabi{}-'.format(self.api) - else: - triplet = self.arch + '-linux-android{}-'.format(self.api) else: if self.is_x86() or self.is_amd64(): toolchain_folder = self.arch + '-' + self.toolchain @@ -164,40 +173,79 @@ class Android: else: toolchain_folder = self.arch + '-linux-android-' + self.toolchain - if self.is_x86(): - triplet = 'i686-linux-android-' - elif self.is_arm(): - triplet = 'arm-linux-androideabi-' - else: - triplet = self.arch + '-linux-android-' + return os.path.abspath(os.path.join(self.ndk_home, path, toolchain_folder, 'prebuilt', toolchain_host)) - return os.path.join(path, toolchain_folder, 'prebuilt', toolchain_host, 'bin', triplet) + def gen_toolchain_path(self): + if self.is_clang(): + if self.is_x86(): + triplet = 'i686-linux-android{}-'.format(self.api) + elif self.is_arm(): + triplet = 'armv7a-linux-androideabi{}-'.format(self.api) + else: + triplet = self.arch + '-linux-android{}-'.format(self.api) + else: + triplet = self.ndk_triplet() + '-' + return os.path.join(self.gen_gcc_toolchain_path(), 'bin', triplet) + + def gen_binutils_path(self): + return os.path.join(self.gen_gcc_toolchain_path(), self.ndk_triplet(), 'bin') def cc(self): - return os.path.abspath(os.path.join(self.ndk_home, self.toolchain_path + ('clang' if self.is_clang() else 'gcc'))) + if self.is_host(): + return 'clang' + return self.toolchain_path + ('clang' if self.is_clang() else 'gcc') def cxx(self): - return os.path.abspath(os.path.join(self.ndk_home, self.toolchain_path + ('clang++' if self.is_clang() else 'g++'))) + if self.is_host(): + return 'clang++' + return self.toolchain_path + ('clang++' if self.is_clang() else 'g++') + + def strip(self): + if self.is_host(): + return 'strip' + return os.path.join(self.gen_binutils_path(), 'strip') def system_stl(self): # TODO: proper STL support return os.path.abspath(os.path.join(self.ndk_home, 'sources', 'cxx-stl', 'system', 'include')) + def libsysroot(self): + arch = self.arch + if self.is_arm(): + arch = 'arm' + elif self.is_arm64(): + arch = 'arm64' + path = 'platforms/android-{}/arch-{}'.format(self.api, arch) + + return os.path.abspath(os.path.join(self.ndk_home, path)) + def sysroot(self): - if self.ndk_rev >= 19: + if self.ndk_rev >= 19 or self.is_host(): return os.path.abspath(os.path.join(self.ndk_home, 'sysroot')) else: - arch = self.arch - if self.is_arm(): - arch = 'arm' - elif self.is_arm64(): - arch = 'arm64' - path = 'platforms/android-{}/arch-{}'.format(self.api, arch) + return self.libsysroot() - return os.path.abspath(os.path.join(self.ndk_home, path)) + def clang_host_triplet(self): + triplet = '' + if self.is_arm(): + triplet += 'arm' + elif self.is_x86(): + triplet += 'i686' + else: + triplet += self.arch + triplet += '-linux-android' + return triplet def cflags(self): - cflags = ['--sysroot={0}'.format(self.sysroot()), '-DANDROID', '-D__ANDROID__'] + cflags = [] + if self.is_host(): + cflags += ['-nostdlib', '--target=%s' % self.clang_host_triplet()] + + if self.ndk_rev < 20: + cflags += ['--sysroot={0}'.format(self.sysroot())] + elif self.is_host(): + cflags += ['-isysroot={0}'.format(self.sysroot())] + cflags += ['-DANDROID', '-D__ANDROID__'] cflags += ['-I{0}'.format(self.system_stl())] if self.is_arm(): if self.arch == 'armeabi-v7a': @@ -218,14 +266,27 @@ class Android: # they go before object list def linkflags(self): - linkflags = ['--sysroot={0}'.format(self.sysroot())] + linkflags = [] + if self.is_host(): + linkflags += ['-fuse-ld=lld', '-nostdlib', '--target=%s' % self.clang_host_triplet(), + '--gcc-toolchain=%s' % self.gen_gcc_toolchain_path()] + + if self.ndk_rev < 20 or self.is_host(): + linkflags += ['--sysroot={0}'.format(self.libsysroot())] + + if self.is_host(): + linkflags += ['-L{0}/usr/lib/{1}'.format(self.sysroot(), self.ndk_triplet()), + '-L{0}/sysroot/usr/lib/{1}/'.format(self.gen_gcc_toolchain_path(), self.ndk_triplet())] return linkflags def ldflags(self): ldflags = ['-lgcc', '-no-canonical-prefixes'] if self.is_arm(): if self.arch == 'armeabi-v7a': - ldflags += ['-march=armv7-a', '-Wl,--fix-cortex-a8', '-mthumb'] + ldflags += ['-march=armv7-a'] + if not self.is_host(): # lld only + ldflags += ['-Wl,--fix-cortex-a8'] + ldflags += ['-mthumb'] if self.is_hardfloat: ldflags += ['-Wl,--no-warn-mismatch', '-lm_hard'] else: @@ -252,6 +313,7 @@ def configure(conf): setattr(conf, 'android', android) conf.environ['CC'] = android.cc() conf.environ['CXX'] = android.cxx() + conf.environ['STRIP'] = android.strip() conf.env.CFLAGS += android.cflags() conf.env.CXXFLAGS += android.cflags() conf.env.LINKFLAGS += android.linkflags() @@ -277,7 +339,7 @@ def configure(conf): def post_compiler_cxx_configure(conf): if conf.options.ANDROID_OPTS: - if conf.android.ndk_rev >= 19: + if conf.android.ndk_rev == 19: conf.env.CXXFLAGS_cxxshlib += ['-static-libstdc++'] conf.env.LDFLAGS_cxxshlib += ['-static-libstdc++'] return