From 761c4c6466d2a1a7f0c2e9e8155bff72872e3825 Mon Sep 17 00:00:00 2001 From: "brettw@chromium.org" Date: Fri, 22 Nov 2013 23:30:28 +0000 Subject: [PATCH] GN: Add support for 32- and 64-bit cross-compiles. This makes it possible on Linux to refer to 64-bit targets from a 32-bit build, and 32-bit targets from a 64-bit build. This also adds flags for Mac cross-compiles but I haven't written the toolchain definitions yet. BUG=322106 R=scottmg@chromium.org Review URL: https://codereview.chromium.org/81153003 git-svn-id: http://src.chromium.org/svn/trunk/src/build@236871 4ff67af0-8c30-449e-8e8b-ad334ec8d88c --- config/BUILDCONFIG.gn | 32 ++++--- config/compiler/BUILD.gn | 28 ++++-- toolchain/linux/BUILD.gn | 188 +++++++++++++++++++++++++-------------- 3 files changed, 168 insertions(+), 80 deletions(-) diff --git a/config/BUILDCONFIG.gn b/config/BUILDCONFIG.gn index f67106baa..de1ee08b5 100644 --- a/config/BUILDCONFIG.gn +++ b/config/BUILDCONFIG.gn @@ -383,20 +383,32 @@ set_defaults("source_set") { # default toolchain. if (is_win) { - if (cpu_arch == "x64") { + if (build_cpu_arch == "x64") { host_toolchain = "//build/toolchain/win:64" - } else if (cpu_arch == "x86") { + } else if (build_cpu_arch == "x86") { host_toolchain = "//build/toolchain/win:32" } - set_default_toolchain(host_toolchain) + + if (cpu_arch == "x64") { + set_default_toolchain("//build/toolchain/win:64") + } else if (cpu_arch == "x86") { + set_default_toolchain("//build/toolchain/win:32") + } } else if (is_linux) { - host_toolchain = "//build/toolchain/linux:host" - if (cpu_arch == "arm" && build_cpu_arch != "arm") { - # Special toolchain for ARM cross-compiling. - set_default_toolchain("//build/toolchain/linux:arm-cross-compile") - } else { - # Use whatever GCC is on the current platform. - set_default_toolchain(host_toolchain) + if (build_cpu_arch == "arm") { + host_toolchain = "//build/toolchain/linux:arm" + } else if (build_cpu_arch == "x86") { + host_toolchain = "//build/toolchain/linux:32" + } else if (build_cpu_arch == "x64") { + host_toolchain = "//build/toolchain/linux:64" + } + + if (build_cpu_arch == "arm") { + set_default_toolchain("//build/toolchain/linux:arm") + } else if (build_cpu_arch == "x86") { + set_default_toolchain("//build/toolchain/linux:32") + } else if (build_cpu_arch == "x64") { + set_default_toolchain("//build/toolchain/linux:64") } } else if (is_mac) { host_toolchain = "//build/toolchain/mac:clang" diff --git a/config/compiler/BUILD.gn b/config/compiler/BUILD.gn index 6f69e05d3..2ded34ed0 100644 --- a/config/compiler/BUILD.gn +++ b/config/compiler/BUILD.gn @@ -39,14 +39,12 @@ config("compiler") { cflags += [ "-fstack-protector", "--param=ssp-buffer-size=4" ] } - # Mac-specific compiler flags setup. - # ---------------------------------- if (is_mac) { + # Mac-specific compiler flags setup. + # ---------------------------------- + # These flags are shared between the C compiler and linker. common_mac_flags = [ - # TODO(brettw) obviously this arch flag needs to be parameterized. - "-arch i386", - # Set which SDK to use. # TODO(brettw) this needs to be configurable somehow. "-isysroot", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk", @@ -54,6 +52,13 @@ config("compiler") { "-mmacosx-version-min=10.6", ] + # CPU architecture. + if (cpu_arch == "x64") { + common_mac_flags += "-arch x86_64" + } else if (cpu_arch == "x32") { + common_mac_flags += "-arch i386" + } + cflags += common_mac_flags + [ # Without this, the constructors and destructors of a C++ object inside # an Objective C struct won't be called, which is very bad. @@ -70,6 +75,19 @@ config("compiler") { "-Wl,-rpath,@loader_path/.", "-Wl,-rpath,@loader_path/../../..", ] + } else { + # Non-Mac Posix compiler flags setup. + # ----------------------------------- + + # CPU architecture. We may or may not be doing a cross compile now, so for + # simplicity we always explicitly set the architecture. + if (cpu_arch == "x64") { + cflags += "-m64" + ldflags += "-m64" + } else if (cpu_arch == "x32") { + cflags += "-m32" + ldflags += "-m32" + } } # Linux-specific compiler flags setup. diff --git a/toolchain/linux/BUILD.gn b/toolchain/linux/BUILD.gn index 016bf29a9..ffb378beb 100644 --- a/toolchain/linux/BUILD.gn +++ b/toolchain/linux/BUILD.gn @@ -7,110 +7,64 @@ cxx = "g++" ar = "ar" ld = cxx -# Everything up to the toolchain args is an exact copy of the GCC version -# below. Keep in sync! Only the compiler variable definitions have changed. -toolchain("host") { - # Make these apply to all tools below. - lib_prefix = "-l" - lib_dir_prefix="-L" +# The toolchains below all issue the same commands with some different flags. +# TODO(brettw) it would be nice to have a different way to express this without +# so much duplication. +cc_command = "$cc -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_c -c \$in -o \$out" +cxx_command = "$cxx -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_cc -c \$in -o \$out" +alink_command = "rm -f \$out && $ar rcs \$out \$in" +solink_command = "if [ ! -e \$lib -o ! -e \${lib}.TOC ]; then $ld -shared \$ldflags -o \$lib -Wl,-soname=\$soname -Wl,--whole-archive \$in \$solibs -Wl,--no-whole-archive \$libs && { readelf -d \${lib} | grep SONAME ; nm -gD -f p \${lib} | cut -f1-2 -d' '; } > \${lib}.TOC; else $ld -shared \$ldflags -o \$lib -Wl,-soname=\$soname -Wl,--whole-archive \$in \$solibs -Wl,--no-whole-archive \$libs && { readelf -d \${lib} | grep SONAME ; nm -gD -f p \${lib} | cut -f1-2 -d' '; } > \${lib}.tmp && if ! cmp -s \${lib}.tmp \${lib}.TOC; then mv \${lib}.tmp \${lib}.TOC ; fi; fi" +link_command = "$ld \$ldflags -o \$out -Wl,--start-group \$in \$solibs -Wl,--end-group \$libs" +stamp_command = "\${postbuilds}touch \$out" +copy_command = "ln -f \$in \$out 2>/dev/null || (rm -rf \$out && cp -af \$in \$out)" - tool("cc") { - # cflags_pch_c - command = "$cc -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_c -c \$in -o \$out" - description = "CC \$out" - depfile = "\$out.d" - deps = "gcc" - } - tool("cxx") { - # cflags_pch_cc - command = "$cxx -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_cc -c \$in -o \$out" - description = "CXX \$out" - depfile = "\$out.d" - deps = "gcc" - } - tool("alink") { - command = "rm -f \$out && $ar rcs \$out \$in" - description = "AR \$out" - } - tool("solink") { - command = "if [ ! -e \$lib -o ! -e \${lib}.TOC ]; then $ld -shared \$ldflags -o \$lib -Wl,-soname=\$soname -Wl,--whole-archive \$in \$solibs -Wl,--no-whole-archive \$libs && { readelf -d \${lib} | grep SONAME ; nm -gD -f p \${lib} | cut -f1-2 -d' '; } > \${lib}.TOC; else $ld -shared \$ldflags -o \$lib -Wl,-soname=\$soname -Wl,--whole-archive \$in \$solibs -Wl,--no-whole-archive \$libs && { readelf -d \${lib} | grep SONAME ; nm -gD -f p \${lib} | cut -f1-2 -d' '; } > \${lib}.tmp && if ! cmp -s \${lib}.tmp \${lib}.TOC; then mv \${lib}.tmp \${lib}.TOC ; fi; fi" - description = "SOLINK \$lib" - #pool = "link_pool" - restat = "1" - } - tool("link") { - command = "$ld \$ldflags -o \$out -Wl,--start-group \$in \$solibs -Wl,--end-group \$libs" - description = "LINK \$out" - #pool = "link_pool" - } - tool("stamp") { - command = "\${postbuilds}touch \$out" - description = "STAMP \$out" - } - tool("copy") { - command = "ln -f \$in \$out 2>/dev/null || (rm -rf \$out && cp -af \$in \$out)" - description = "COPY \$in \$out" - } - - # When invoking this toolchain not as the default one, these args will be - # passed to the build. They are ignored when this is the default toolchain. - toolchain_args() { - # Pass the current CPU architecture to the build as the toolchain to use. - # If the default toolchain is set to ARM and the local system is x86, this - # will make this secondary toolchain refer to the host GCC again. - cpu_arch = build_cpu_arch - } -} - -# ARM Cross-Compile ------------------------------------------------------------ +# ARM -------------------------------------------------------------------------- cc = "arm-linux-gnueabi-gcc" cxx = "arm-linux-gnueabi-g++" ar = "arm-linux-gnueabi-ar" ld = cxx -# Everything up the the toolchain args is an exact copy of the GCC version -# below. Keep in sync! Only the compiler variable definitions have changed. -toolchain("arm-cross-compile") { +toolchain("arm") { # Make these apply to all tools below. lib_prefix = "-l" lib_dir_prefix="-L" tool("cc") { # cflags_pch_c - command = "$cc -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_c -c \$in -o \$out" + command = cc_command description = "CC \$out" depfile = "\$out.d" deps = "gcc" } tool("cxx") { # cflags_pch_cc - command = "$cxx -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_cc -c \$in -o \$out" + command = cxx_command description = "CXX \$out" depfile = "\$out.d" deps = "gcc" } tool("alink") { - command = "rm -f \$out && $ar rcs \$out \$in" + command = alink_command description = "AR \$out" } tool("solink") { - command = "if [ ! -e \$lib -o ! -e \${lib}.TOC ]; then $ld -shared \$ldflags -o \$lib -Wl,-soname=\$soname -Wl,--whole-archive \$in \$solibs -Wl,--no-whole-archive \$libs && { readelf -d \${lib} | grep SONAME ; nm -gD -f p \${lib} | cut -f1-2 -d' '; } > \${lib}.TOC; else $ld -shared \$ldflags -o \$lib -Wl,-soname=\$soname -Wl,--whole-archive \$in \$solibs -Wl,--no-whole-archive \$libs && { readelf -d \${lib} | grep SONAME ; nm -gD -f p \${lib} | cut -f1-2 -d' '; } > \${lib}.tmp && if ! cmp -s \${lib}.tmp \${lib}.TOC; then mv \${lib}.tmp \${lib}.TOC ; fi; fi" + command = solink_command description = "SOLINK \$lib" #pool = "link_pool" restat = "1" } tool("link") { - command = "$ld \$ldflags -o \$out -Wl,--start-group \$in \$solibs -Wl,--end-group \$libs" + command = link_command description = "LINK \$out" #pool = "link_pool" } tool("stamp") { - command = "\${postbuilds}touch \$out" + command = stamp_command description = "STAMP \$out" } tool("copy") { - command = "ln -f \$in \$out 2>/dev/null || (rm -rf \$out && cp -af \$in \$out)" + command = copy_command description = "COPY \$in \$out" } @@ -120,3 +74,107 @@ toolchain("arm-cross-compile") { cpu_arch = "arm" } } + +# 32-bit ----------------------------------------------------------------------- + +toolchain("32") { + # Make these apply to all tools below. + lib_prefix = "-l" + lib_dir_prefix="-L" + + tool("cc") { + # cflags_pch_c + command = cc_command + description = "CC \$out" + depfile = "\$out.d" + deps = "gcc" + } + tool("cxx") { + # cflags_pch_cc + command = cxx_command + description = "CXX \$out" + depfile = "\$out.d" + deps = "gcc" + } + tool("alink") { + command = alink_command + description = "AR \$out" + } + tool("solink") { + command = solink_command + description = "SOLINK \$lib" + #pool = "link_pool" + restat = "1" + } + tool("link") { + command = link_command + description = "LINK \$out" + #pool = "link_pool" + } + tool("stamp") { + command = stamp_command + description = "STAMP \$out" + } + tool("copy") { + command = copy_command + description = "COPY \$in \$out" + } + + # When invoking this toolchain not as the default one, these args will be + # passed to the build. They are ignored when this is the default toolchain. + toolchain_args() { + cpu_arch = "x32" + } +} + +# 64-bit ----------------------------------------------------------------------- + +toolchain("64") { + # Make these apply to all tools below. + lib_prefix = "-l" + lib_dir_prefix="-L" + + tool("cc") { + # cflags_pch_c + command = cc_command + description = "CC \$out" + depfile = "\$out.d" + deps = "gcc" + } + tool("cxx") { + # cflags_pch_cc + command = cxx_command + description = "CXX \$out" + depfile = "\$out.d" + deps = "gcc" + } + tool("alink") { + command = alink_command + description = "AR \$out" + } + tool("solink") { + command = solink_command + description = "SOLINK \$lib" + #pool = "link_pool" + restat = "1" + } + tool("link") { + command = link_command + description = "LINK \$out" + #pool = "link_pool" + } + tool("stamp") { + command = stamp_command + description = "STAMP \$out" + } + tool("copy") { + command = copy_command + description = "COPY \$in \$out" + } + + # When invoking this toolchain not as the default one, these args will be + # passed to the build. They are ignored when this is the default toolchain. + toolchain_args() { + cpu_arch = "x64" + } +}