From f6208725ab0c122e9fb0810c6cecc4a21629da51 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Mon, 15 Oct 2018 13:02:57 -0700 Subject: [PATCH] Allow specification of a custom toolchain and sysroot for host builds. Along with the specification of a custom target triple, this allows us to reuse the GN logic for hosts to build artifacts for unknown targets. This makes it easier to support more platforms using the build system without having to add platform specific knowledge to all GN files. --- build/config/BUILDCONFIG.gn | 10 +- build/toolchain/custom/BUILD.gn | 152 ++++++++++++++++++++++++++++++ build/toolchain/custom/custom.gni | 17 ++++ third_party/libpng/BUILD.gn | 3 +- 4 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 build/toolchain/custom/BUILD.gn create mode 100644 build/toolchain/custom/custom.gni diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 584a9159c4..afc827bdab 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -568,8 +568,14 @@ set_defaults("test") { # which will identify the toolchain corresponding to the local system when # doing cross-compiles. When not cross-compiling, this will be the same as the # default toolchain. - -if (is_win) { +import("//build/toolchain/custom/custom.gni") + +if (custom_toolchain != "") { + assert(custom_sysroot != "") + assert(custom_target_triple != "") + host_toolchain = "//build/toolchain/linux:clang_$host_cpu" + set_default_toolchain("//build/toolchain/custom") +} else if (is_win) { # On windows we use the same toolchain for host and target by default. host_toolchain = "//build/toolchain/win:$current_cpu" set_default_toolchain("$host_toolchain") diff --git a/build/toolchain/custom/BUILD.gn b/build/toolchain/custom/BUILD.gn new file mode 100644 index 0000000000..8189b78072 --- /dev/null +++ b/build/toolchain/custom/BUILD.gn @@ -0,0 +1,152 @@ +# Copyright 2017 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/toolchain/custom/custom.gni") + +toolchain("custom") { + toolchain_bin = "${custom_toolchain}/bin" + + # We can't do string interpolation ($ in strings) on things with dots in + # them. To allow us to use $cc below, for example, we create copies of + # these values in our scope. + cc = "${toolchain_bin}/clang" + cxx = "${toolchain_bin}/clang++" + ar = "${toolchain_bin}/${custom_target_triple}-ar" + ld = "${toolchain_bin}/clang++" + readelf = "${toolchain_bin}/${custom_target_triple}-readelf" + nm = "${toolchain_bin}/${custom_target_triple}-nm" + + target_triple_flags = "--target=${custom_target_triple}" + sysroot_flags = "--sysroot ${custom_sysroot}" + + custom_lib_flags = "-L${custom_toolchain}/lib" + + # These library switches can apply to all tools below. + lib_switch = "-l" + lib_dir_switch = "-L" + + tool("cc") { + depfile = "{{output}}.d" + command = "$cc -MMD -MF $depfile $target_triple_flags $sysroot_flags {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" + depsformat = "gcc" + description = "CC {{output}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o", + ] + } + + tool("cxx") { + depfile = "{{output}}.d" + command = "$cxx -MMD -MF $depfile $target_triple_flags $sysroot_flags {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}" + depsformat = "gcc" + description = "CXX {{output}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o", + ] + } + + tool("asm") { + depfile = "{{output}}.d" + command = "$cc -MMD -MF $depfile $target_triple_flags $sysroot_flags {{defines}} {{include_dirs}} {{asmflags}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" + depsformat = "gcc" + description = "ASM {{output}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o", + ] + } + + tool("alink") { + rspfile = "{{output}}.rsp" + command = "rm -f {{output}} && $ar rcs {{output}} @$rspfile" + description = "AR {{output}}" + rspfile_content = "{{inputs}}" + outputs = [ + "{{target_out_dir}}/{{target_output_name}}{{output_extension}}", + ] + default_output_extension = ".a" + output_prefix = "lib" + } + + tool("solink") { + soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so". + sofile = "{{root_out_dir}}/$soname" # Possibly including toolchain dir. + rspfile = sofile + ".rsp" + + # These variables are not built into GN but are helpers that implement + # (1) linking to produce a .so, (2) extracting the symbols from that file + # to a temporary file, (3) if the temporary file has differences from the + # existing .TOC file, overwrite it, otherwise, don't change it. + tocfile = sofile + ".TOC" + temporary_tocname = sofile + ".tmp" + link_command = "$ld $target_triple_flags $sysroot_flags -shared {{ldflags}} -o $sofile $custom_lib_flags -Wl,--build-id -Wl,-soname=$soname @$rspfile" + toc_command = "{ $readelf -d $sofile | grep SONAME ; $nm -gD -f p $sofile | cut -f1-2 -d' '; } > $temporary_tocname" + replace_command = "if ! cmp -s $temporary_tocname $tocfile; then mv $temporary_tocname $tocfile; fi" + + command = "$link_command && $toc_command && $replace_command" + rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}" + + description = "SOLINK $sofile" + + # Use this for {{output_extension}} expansions unless a target manually + # overrides it (in which case {{output_extension}} will be what the target + # specifies). + default_output_extension = ".so" + + output_prefix = "lib" + + # Since the above commands only updates the .TOC file when it changes, ask + # Ninja to check if the timestamp actually changed to know if downstream + # dependencies should be recompiled. + restat = true + + # Tell GN about the output files. It will link to the sofile but use the + # tocfile for dependency management. + outputs = [ + sofile, + tocfile, + ] + + link_output = sofile + depend_output = tocfile + } + + tool("link") { + exename = "{{target_output_name}}{{output_extension}}" + outfile = "{{root_out_dir}}/$exename" + rspfile = "$outfile.rsp" + unstripped_outfile = outfile + command = "$ld $target_triple_flags $sysroot_flags {{ldflags}} -o $unstripped_outfile $custom_lib_flags -Wl,--build-id -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}" + description = "LINK $outfile" + rspfile_content = "{{inputs}}" + outputs = [ + outfile, + ] + if (outfile != unstripped_outfile) { + outputs += [ unstripped_outfile ] + } + } + + tool("stamp") { + command = "touch {{output}}" + description = "STAMP {{output}}" + } + + tool("copy") { + command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} && cp -af {{source}} {{output}})" + description = "COPY {{source}} {{output}}" + } + + # 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 = { + current_cpu = target_cpu + current_os = target_os + + # These values need to be passed through unchanged. + target_os = target_os + target_cpu = target_cpu + + is_clang = true + } +} diff --git a/build/toolchain/custom/custom.gni b/build/toolchain/custom/custom.gni new file mode 100644 index 0000000000..6d7bc6c5ef --- /dev/null +++ b/build/toolchain/custom/custom.gni @@ -0,0 +1,17 @@ +# Copyright 2018 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +declare_args() { + # Path to a custom toolchain containing the compilers, linkers and associated + # tools to build native executables. + custom_toolchain = "" + + # Path to the sysroot containing the system libraries and associated headers + # on the target. Binaries generated on the host will be able to link against + # these libraries. + custom_sysroot = "" + + # The target triple. For example: arm-linux-gnueabihf. + custom_target_triple = "" +} diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn index 27d7bbd973..2ac6755585 100644 --- a/third_party/libpng/BUILD.gn +++ b/third_party/libpng/BUILD.gn @@ -30,8 +30,7 @@ source_set("libpng") { ] if ((is_ios && !use_ios_simulator) || - (is_android && (current_cpu == "arm" || current_cpu == "arm64")) || - (is_linux && (current_cpu == "arm64"))) { + ((is_android || is_linux) && (current_cpu == "arm" || current_cpu == "arm64"))) { if (is_android) { import("//build/config/android/config.gni")