1*4882a593Smuzhiyun# GN host architecture helpers. 2*4882a593Smuzhiyun# 3*4882a593Smuzhiyun# BUILD_ARCH's value corresponds to what uname returns as the machine name. 4*4882a593Smuzhiyun# The mapping in gn_host_arch_name() tries to match several possible values 5*4882a593Smuzhiyun# returned by the Linux kernel in uname(2) into the corresponding values GN 6*4882a593Smuzhiyun# understands. 7*4882a593Smuzhiyundef gn_host_arch_name(d): 8*4882a593Smuzhiyun """Returns a GN architecture name corresponding to the build host's machine 9*4882a593Smuzhiyun architecture.""" 10*4882a593Smuzhiyun import re 11*4882a593Smuzhiyun arch_translations = { 12*4882a593Smuzhiyun r'aarch64.*': 'arm64', 13*4882a593Smuzhiyun r'arm.*': 'arm', 14*4882a593Smuzhiyun r'i[3456]86$': 'x86', 15*4882a593Smuzhiyun r'x86_64$': 'x64', 16*4882a593Smuzhiyun } 17*4882a593Smuzhiyun build_arch = d.getVar("BUILD_ARCH") 18*4882a593Smuzhiyun for arch_regexp, gn_arch_name in arch_translations.items(): 19*4882a593Smuzhiyun if re.match(arch_regexp, build_arch): 20*4882a593Smuzhiyun return gn_arch_name 21*4882a593Smuzhiyun bb.fatal('Unsuported BUILD_ARCH value: "%s"' % build_arch) 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun# GN target architecture helpers. 24*4882a593Smuzhiyun# 25*4882a593Smuzhiyun# Determining the target architecture is more difficult, as there are many 26*4882a593Smuzhiyun# different values we can use on the Yocto side (e.g. TUNE_ARCH, TARGET_ARCH, 27*4882a593Smuzhiyun# MACHINEOVERRIDES etc). What we do is define the mapping with regular, 28*4882a593Smuzhiyun# non-Python variables with overrides that are generic enough (i.e. "x86" 29*4882a593Smuzhiyun# instead of "i586") and then use gn_target_arch_name() to return the right 30*4882a593Smuzhiyun# value with some validation. 31*4882a593SmuzhiyunGN_TARGET_ARCH_NAME:aarch64 = "arm64" 32*4882a593SmuzhiyunGN_TARGET_ARCH_NAME:arm = "arm" 33*4882a593SmuzhiyunGN_TARGET_ARCH_NAME:x86 = "x86" 34*4882a593SmuzhiyunGN_TARGET_ARCH_NAME:x86-64 = "x64" 35*4882a593Smuzhiyun 36*4882a593Smuzhiyundef clang_install_path(d): 37*4882a593Smuzhiyun """Return clang compiler install path.""" 38*4882a593Smuzhiyun return d.getVar("STAGING_BINDIR_NATIVE") 39*4882a593Smuzhiyun 40*4882a593Smuzhiyundef gn_target_arch_name(d): 41*4882a593Smuzhiyun """Returns a GN architecture name corresponding to the target machine's 42*4882a593Smuzhiyun architecture.""" 43*4882a593Smuzhiyun name = d.getVar("GN_TARGET_ARCH_NAME") 44*4882a593Smuzhiyun if name is None: 45*4882a593Smuzhiyun bb.fatal('Unsupported target architecture. A valid override for the ' 46*4882a593Smuzhiyun 'GN_TARGET_ARCH_NAME variable could not be found.') 47*4882a593Smuzhiyun return name 48*4882a593Smuzhiyun 49*4882a593Smuzhiyundef write_toolchain_file(d, file_path): 50*4882a593Smuzhiyun """Creates a complete GN toolchain file in |file_path|.""" 51*4882a593Smuzhiyun import string 52*4882a593Smuzhiyun # Even though we always use clang, the "clang_toolchain" GN template is too 53*4882a593Smuzhiyun # restrictive in the way it sets variables such as |cxx|. Since it is just 54*4882a593Smuzhiyun # a wrapper on top of the "gcc_toolchain" template, we keep using the 55*4882a593Smuzhiyun # latter directly to accommodate our cross-compilation needs. 56*4882a593Smuzhiyun toolchain_tmpl = string.Template( 57*4882a593Smuzhiyun 'gcc_toolchain("${toolchain_name}") {\n' 58*4882a593Smuzhiyun ' cc = "${cc}"\n' 59*4882a593Smuzhiyun ' cxx = "${cxx}"\n' 60*4882a593Smuzhiyun ' ar = "${ar}"\n' 61*4882a593Smuzhiyun ' ld = cxx # GN expects a compiler, not a linker.\n' 62*4882a593Smuzhiyun ' nm = "${nm}"\n' 63*4882a593Smuzhiyun ' readelf = "${readelf}"\n' 64*4882a593Smuzhiyun ' extra_cflags = "${extra_cflags}"\n' 65*4882a593Smuzhiyun ' extra_cppflags = "${extra_cppflags}"\n' 66*4882a593Smuzhiyun ' extra_cxxflags = "${extra_cxxflags}"\n' 67*4882a593Smuzhiyun ' extra_ldflags = "${extra_ldflags}"\n' 68*4882a593Smuzhiyun ' toolchain_args = {\n' 69*4882a593Smuzhiyun ' current_cpu = "${current_cpu}"\n' 70*4882a593Smuzhiyun ' current_os = "linux"\n' 71*4882a593Smuzhiyun ' is_clang = true\n' 72*4882a593Smuzhiyun ' }\n' 73*4882a593Smuzhiyun '}\n' 74*4882a593Smuzhiyun ) 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun native_toolchain = { 77*4882a593Smuzhiyun 'toolchain_name': 'yocto_native', 78*4882a593Smuzhiyun 'current_cpu': gn_host_arch_name(d), 79*4882a593Smuzhiyun 'cc': d.expand('${BUILD_CC}'), 80*4882a593Smuzhiyun 'cxx': d.expand('${BUILD_CXX}'), 81*4882a593Smuzhiyun 'ar': d.expand('${BUILD_AR}'), 82*4882a593Smuzhiyun 'nm': d.expand('${BUILD_NM}'), 83*4882a593Smuzhiyun 'readelf': d.expand('${BUILD_PREFIX}readelf'), 84*4882a593Smuzhiyun 'extra_cflags': d.expand('${BUILD_CFLAGS}'), 85*4882a593Smuzhiyun 'extra_cppflags': d.expand('${BUILD_CPPFLAGS}'), 86*4882a593Smuzhiyun 'extra_cxxflags': d.expand('${BUILD_CXXFLAGS}'), 87*4882a593Smuzhiyun 'extra_ldflags': d.expand('${BUILD_LDFLAGS}'), 88*4882a593Smuzhiyun } 89*4882a593Smuzhiyun target_toolchain = { 90*4882a593Smuzhiyun 'toolchain_name': 'yocto_target', 91*4882a593Smuzhiyun 'current_cpu': gn_target_arch_name(d), 92*4882a593Smuzhiyun 'cc': d.expand('${CC}'), 93*4882a593Smuzhiyun 'cxx': d.expand('${CXX}'), 94*4882a593Smuzhiyun 'ar': d.expand('${AR}'), 95*4882a593Smuzhiyun 'nm': d.expand('${NM}'), 96*4882a593Smuzhiyun 'readelf': d.expand('${READELF}'), 97*4882a593Smuzhiyun 'extra_cflags': d.expand('${CFLAGS}'), 98*4882a593Smuzhiyun 'extra_cppflags': d.expand('${CPPFLAGS}'), 99*4882a593Smuzhiyun 'extra_cxxflags': d.expand('${CXXFLAGS}'), 100*4882a593Smuzhiyun 'extra_ldflags': d.expand('${LDFLAGS}'), 101*4882a593Smuzhiyun } 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun with open(file_path, 'w') as toolchain_file: 104*4882a593Smuzhiyun toolchain_file.write( 105*4882a593Smuzhiyun '# This file has been generated automatically.\n' 106*4882a593Smuzhiyun '\n' 107*4882a593Smuzhiyun 'import("//build/toolchain/gcc_toolchain.gni")\n' 108*4882a593Smuzhiyun '\n' 109*4882a593Smuzhiyun ) 110*4882a593Smuzhiyun toolchain_file.write(toolchain_tmpl.substitute(native_toolchain)) 111*4882a593Smuzhiyun toolchain_file.write(toolchain_tmpl.substitute(target_toolchain)) 112