From a999cec6941b2b472b1e7fccc92d8b73150a1040 Mon Sep 17 00:00:00 2001 From: Ivan Inozemtsev Date: Tue, 26 Nov 2024 11:48:51 +0000 Subject: [PATCH] Separate toolchains for shared libraries 1. Added `toolchain_suite` template and switched toolchain definitions to it, so now each toolchain definition defines a regular and `_shared` toolchain, with different values for `is_shared_library` argument. 2. Changed the logic of choosing between `fPIC` and `fPIE` based on `is_shared_library` arg. 3. Changed `shared_library` template to define a group, depending on the same target in a shared toolchain, and a copy of an output artifact. 4. Made a copy of `runtime:dart_shared_lib` config and add it automatically to all shared libraries. 5. Removed `runtime:dart_shared_lib` config and `DART_SHARED_LIB` define from existing `shared_library` targets. This CL should be a no-op refactoring to enable https://dart-review.googlesource.com/c/sdk/+/394102. TEST=ci Change-Id: I6c044254d8e74b6b3ddadbf784e58d5f641fbcf3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392661 Commit-Queue: Ivan Inozemtsev Reviewed-by: Ryan Macnak --- build/config/BUILDCONFIG.gn | 134 ++++++++- build/config/compiler/BUILD.gn | 12 +- build/config/sysroot.gni | 8 +- build/toolchain/android/BUILD.gn | 92 +----- build/toolchain/android/android_toolchain.gni | 86 ++++++ build/toolchain/fuchsia/BUILD.gn | 179 +---------- build/toolchain/fuchsia/fuchsia_toolchain.gni | 191 ++++++++++++ build/toolchain/gcc_toolchain.gni | 4 + build/toolchain/linux/BUILD.gn | 32 +- build/toolchain/mac/BUILD.gn | 283 +----------------- build/toolchain/mac/mac_toolchain.gni | 275 +++++++++++++++++ build/toolchain/toolchain_suite.gni | 52 ++++ build/toolchain/win/BUILD.gn | 260 +--------------- build/toolchain/win/msvc_toolchain.gni | 259 ++++++++++++++++ runtime/BUILD.gn | 5 +- runtime/bin/BUILD.gn | 13 +- 16 files changed, 1061 insertions(+), 824 deletions(-) create mode 100644 build/toolchain/android/android_toolchain.gni create mode 100644 build/toolchain/fuchsia/fuchsia_toolchain.gni create mode 100644 build/toolchain/mac/mac_toolchain.gni create mode 100644 build/toolchain/toolchain_suite.gni create mode 100644 build/toolchain/win/msvc_toolchain.gni diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 768391439a3..baede0fc65e 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -140,6 +140,10 @@ declare_args() { # protobuf-gn fails to build if this argument isn't defined. This should never # be set to true, becuase we never build within the Fuchsia tree. is_fuchsia_tree = false + + # Set to true when compiling in a _shared toolchain, used for + # building shared libraries. + is_shared_library = false } # ============================================================================= @@ -258,6 +262,11 @@ if (use_flutter_cxx) { ] } +if (is_shared_library) { + # Always enable DART_EXPORT in shared toolchain. + _native_compiler_configs += [ "//build/config/compiler:dart_shared_lib" ] +} + if (is_win) { _native_compiler_configs += [ "//build/config/win:lean_and_mean", @@ -456,7 +465,7 @@ if (is_win) { } } -# Sets default dependencies for executable and shared_library targets. +# Sets default dependencies for executable and loadable_module targets. # # Variables # no_default_deps: If true, no standard dependencies will be added. @@ -464,7 +473,6 @@ foreach(_target_type, [ "executable", "loadable_module", - "shared_library", ]) { template(_target_type) { target(_target_type, target_name) { @@ -487,6 +495,128 @@ foreach(_target_type, } } +if (!is_shared_library) { + # In the main toolchain, shared_library defined as a group with two targets: + # + # - same library in the _shared toolcahin + # - copy of the built library from a toolchain output folder into + # the main output folder + template("shared_library") { + original_target_name = target_name + copy_target_name = "${target_name}_copy" + shared_toolchain_target_name = + "${original_target_name}(${current_toolchain}_shared)" + + copy(copy_target_name) { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + if (defined(visibility)) { + visibility += [ ":$original_target_name" ] + } + + deps = [ ":$shared_toolchain_target_name" ] + + # Calculate an output file name produced by an shared library. + # Inspired by Fuchsia build config + # https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILDCONFIG.gn;l=3183;drc=86dcff138700c76441db8592b39de7b3997a0050 + output_name = original_target_name + if (defined(invoker.output_name)) { + output_name = invoker.output_name + } + + output_prefix = "lib" + if (!defined(output_extension)) { + if (current_os == "mac" || current_os == "ios") { + output_extension = "dylib" + } else if (current_os == "win") { + output_extension = "dll" + output_prefix = "" + } else if (current_os == "unknown" && current_cpu == "wasm32") { + output_extension = "wasm" + } else { + output_extension = "so" + } + } + + output_file_name = "$output_prefix$output_name" + if (output_extension != "") { + output_file_name += ".$output_extension" + } + + local_out_dir = root_out_dir + shared_out_dir = get_label_info(deps[0], "root_out_dir") + if (defined(invoker.output_dir)) { + local_out_dir = invoker.output_dir + + # If invoker.output_dir is not root_build_dir, assume it is a + # sub-directory of root_out_dir, and adjust the source path accordingly + # (e.g. "/foo" -> "-/foo"). + if (local_out_dir != root_build_dir) { + relative_dir = + rebase_path(local_out_dir, root_out_dir, root_build_dir) + shared_out_dir = "$shared_out_dir/$relative_dir" + } + } + + sources = [ "$shared_out_dir/$output_file_name" ] + outputs = [ "$local_out_dir/$output_file_name" ] + } + + group(target_name) { + public_deps = [ + ":$copy_target_name", + ":$shared_toolchain_target_name", + ] + } + not_needed(invoker, "*") + } +} else { + # In the -shared toolchain, shared_library is just its normal self, + # but if the invoker constrained the visibility, we must make sure + # the dependency from the main toolchain is still allowed. + template("shared_library") { + shared_library(target_name) { + # original_target_name = target_name + forward_variables_from(invoker, [ "visibility" ]) + forward_variables_from(invoker, + "*", + [ + "no_default_deps", + "visibility", + ]) + if (!defined(output_dir)) { + output_dir = root_out_dir + } + if (!defined(output_name)) { + output_name = target_name + } + + # target_name = original_target_name + if (defined(visibility)) { + visibility += [ ":$target_name" ] + } + if (!defined(invoker.no_default_deps) || !invoker.no_default_deps) { + if (!defined(deps)) { + deps = [] + } + + if (use_flutter_cxx) { + deps += [ "//third_party/libcxx" ] + } + if (is_fuchsia) { + deps += [ + "//build/fuchsia/config/clang:c++-runtime-deps", + "//third_party/fuchsia/gn-sdk/src/config:runtime_library_group", + ] + } + } + } + } +} + # ============================================================================== # COMPONENT SETUP # ============================================================================== diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index ec354b66edd..b77bab8676c 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -250,13 +250,7 @@ config("compiler") { } if (is_android || is_linux || is_mac || is_ios || is_fuchsia) { - if (use_flutter_cxx) { - # shared_library_config isn't transitive, so we don't automatically get - # another versions of libcxx with and without -fPIC. Properly setting this - # up so only shard libraries pay the extra cost fPIC over fPIE means - # something like separate GN toolchains like in the Fuchsia GN build. For - # now, globally enabling fPIC is okay because it is limited to test-only - # builds. + if (is_shared_library) { cflags += [ "-fPIC" ] ldflags += [ "-fPIC" ] } else { @@ -916,3 +910,7 @@ config("symbols") { ] } } + +config("dart_shared_lib") { + defines = [ "DART_SHARED_LIB" ] +} diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni index 2a6cab96af9..a2e91adcdea 100644 --- a/build/config/sysroot.gni +++ b/build/config/sysroot.gni @@ -24,8 +24,8 @@ if (is_linux) { target_sysroot = rebase_path("//buildtools/sysroot/alpine-linux-x86_64", root_build_dir) } else if (current_cpu == "arm") { - target_sysroot = rebase_path("//buildtools/sysroot/alpine-linux-armv7", - root_build_dir) + target_sysroot = + rebase_path("//buildtools/sysroot/alpine-linux-armv7", root_build_dir) } else if (current_cpu == "arm64") { target_sysroot = rebase_path("//buildtools/sysroot/alpine-linux-aarch64", root_build_dir) @@ -50,7 +50,9 @@ if (is_linux) { } if ((current_toolchain == host_toolchain || - current_toolchain == default_toolchain) && target_sysroot != "") { + current_toolchain == default_toolchain || + current_toolchain == "${default_toolchain}_shared") && + target_sysroot != "") { sysroot = target_sysroot } else if (is_android) { import("//build/config/android/config.gni") diff --git a/build/toolchain/android/BUILD.gn b/build/toolchain/android/BUILD.gn index 76d957e94f5..216a1973c13 100644 --- a/build/toolchain/android/BUILD.gn +++ b/build/toolchain/android/BUILD.gn @@ -2,103 +2,31 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/sysroot.gni") # Imports android/config.gni. -import("//build/toolchain/ccache.gni") -import("//build/toolchain/gcc_toolchain.gni") -import("//build/toolchain/rbe.gni") +import("//build/toolchain/toolchain_suite.gni") -# The Android GCC toolchains share most of the same parameters, so we have this -# wrapper around gcc_toolchain to avoid duplication of logic. -# -# Parameters: -# - android_ndk_lib_dir -# Libraries for this architecture -# - tool_prefix -# Prefix to be added to the tool names. -# - toolchain_cpu -# Same as gcc_toolchain -template("android_toolchain") { - gcc_toolchain(target_name) { - if (use_rbe) { - compiler_args = - rewrapper_args + [ "--labels=type=compile,compiler=clang,lang=cpp" ] - - # TODO: Unfortunately I see no way to get build_arch reliably. - if (rbe_os != host_os) { - compiler_args += [ - "--inputs=build/rbe,buildtools/$rbe_os-$rbe_cpu/clang/bin/llvm", - "--remote_wrapper=../../build/rbe/llvm.sh", - ] - } - assembler_prefix = "" - compiler_prefix = string_join(" ", compiler_args) + " " - link_prefix = "" - } else if (use_ccache) { - assembler_prefix = "ccache " - compiler_prefix = "ccache " - link_prefix = "ccache " - } else { - assembler_prefix = "" - compiler_prefix = "" - link_prefix = "" - } - - is_clang = true - prefix = rebase_path( - "${android_ndk_root}/toolchains/llvm/prebuilt/${android_host_os}-${android_host_arch}/bin", - root_build_dir) - - cc = "${compiler_prefix}${prefix}/clang" - cxx = "${compiler_prefix}${prefix}/clang++" - asm = "${assembler_prefix}${prefix}/clang" - ar = prefix + "/llvm-ar" - ld = "${link_prefix}${prefix}/clang++" - readelf = prefix + "/llvm-readelf" - nm = prefix + "/llvm-nm" - android_strip = prefix + "/llvm-strip" - - toolchain_os = "android" - toolchain_cpu = invoker.toolchain_cpu - - # We make the assumption that the gcc_toolchain will produce a soname with - # the following definition. - soname = "{{target_output_name}}{{output_extension}}" - - stripped_soname = "lib.stripped/${soname}" - temp_stripped_soname = "${stripped_soname}.tmp" - - strip_command = - "$android_strip --strip-unneeded -o $temp_stripped_soname $soname" - replace_command = "if ! cmp -s $temp_stripped_soname $stripped_soname; then mv $temp_stripped_soname $stripped_soname; fi" - postsolink = "$strip_command && $replace_command" - solink_outputs = [ stripped_soname ] - default_output_extension = android_product_extension - - # We make the assumption that the gcc_toolchain will produce an exe with - # the following definition. - exe = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" - stripped_exe = "exe.stripped/$exe" - postlink = "$android_strip --strip-unneeded -o $stripped_exe $exe" - link_outputs = [ stripped_exe ] +template("android_toolchain_suite") { + toolchain_suite(target_name) { + toolchain_template = "android_toolchain" + forward_variables_from(invoker, "*") } } -android_toolchain("clang_x86") { +android_toolchain_suite("clang_x86") { toolchain_cpu = "x86" } -android_toolchain("clang_arm") { +android_toolchain_suite("clang_arm") { toolchain_cpu = "arm" } -android_toolchain("clang_x64") { +android_toolchain_suite("clang_x64") { toolchain_cpu = "x86_64" } -android_toolchain("clang_arm64") { +android_toolchain_suite("clang_arm64") { toolchain_cpu = "arm64" } -android_toolchain("clang_riscv64") { +android_toolchain_suite("clang_riscv64") { toolchain_cpu = "riscv64" } diff --git a/build/toolchain/android/android_toolchain.gni b/build/toolchain/android/android_toolchain.gni new file mode 100644 index 00000000000..9a3e39bf900 --- /dev/null +++ b/build/toolchain/android/android_toolchain.gni @@ -0,0 +1,86 @@ +import("//build/config/sysroot.gni") # Imports android/config.gni. +import("//build/toolchain/ccache.gni") +import("//build/toolchain/gcc_toolchain.gni") +import("//build/toolchain/rbe.gni") + +# The Android GCC toolchains share most of the same parameters, so we have this +# wrapper around gcc_toolchain to avoid duplication of logic. +# +# Parameters: +# - android_ndk_lib_dir +# Libraries for this architecture +# - tool_prefix +# Prefix to be added to the tool names. +# - toolchain_cpu +# Same as gcc_toolchain +template("android_toolchain") { + gcc_toolchain(target_name) { + if (use_rbe) { + compiler_args = + rewrapper_args + [ "--labels=type=compile,compiler=clang,lang=cpp" ] + + # TODO: Unfortunately I see no way to get build_arch reliably. + if (rbe_os != host_os) { + compiler_args += [ + "--inputs=build/rbe,buildtools/$rbe_os-$rbe_cpu/clang/bin/llvm", + "--remote_wrapper=../../build/rbe/llvm.sh", + ] + } + assembler_prefix = "" + compiler_prefix = string_join(" ", compiler_args) + " " + link_prefix = "" + } else if (use_ccache) { + assembler_prefix = "ccache " + compiler_prefix = "ccache " + link_prefix = "ccache " + } else { + assembler_prefix = "" + compiler_prefix = "" + link_prefix = "" + } + + is_clang = true + prefix = rebase_path( + "${android_ndk_root}/toolchains/llvm/prebuilt/${android_host_os}-${android_host_arch}/bin", + root_build_dir) + + cc = "${compiler_prefix}${prefix}/clang" + cxx = "${compiler_prefix}${prefix}/clang++" + asm = "${assembler_prefix}${prefix}/clang" + ar = prefix + "/llvm-ar" + ld = "${link_prefix}${prefix}/clang++" + readelf = prefix + "/llvm-readelf" + nm = prefix + "/llvm-nm" + android_strip = prefix + "/llvm-strip" + + toolchain_os = "android" + toolchain_cpu = invoker.toolchain_cpu + + # We make the assumption that the gcc_toolchain will produce a soname with + # the following definition. + soname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + + stripped_soname = "lib.stripped/${soname}" + temp_stripped_soname = "${stripped_soname}.tmp" + + strip_command = + "$android_strip --strip-unneeded -o $temp_stripped_soname $soname" + replace_command = "if ! cmp -s $temp_stripped_soname $stripped_soname; then mv $temp_stripped_soname $stripped_soname; fi" + postsolink = "$strip_command && $replace_command" + solink_outputs = [ stripped_soname ] + default_output_extension = android_product_extension + + # We make the assumption that the gcc_toolchain will produce an exe with + # the following definition. + exe = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + stripped_exe = "exe.stripped/$exe" + postlink = "$android_strip --strip-unneeded -o $stripped_exe $exe" + link_outputs = [ stripped_exe ] + + toolchain_args = { + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + } + } +} diff --git a/build/toolchain/fuchsia/BUILD.gn b/build/toolchain/fuchsia/BUILD.gn index 2ddee0326ca..5e8d1ecf7ec 100644 --- a/build/toolchain/fuchsia/BUILD.gn +++ b/build/toolchain/fuchsia/BUILD.gn @@ -2,181 +2,8 @@ # for details. 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/config/sysroot.gni") -import("//build/toolchain/ccache.gni") -import("//build/toolchain/gcc_toolchain.gni") -import("//build/toolchain/rbe.gni") +import("//build/toolchain/toolchain_suite.gni") -if (use_ccache) { - assembler_prefix = "ccache " - compiler_prefix = "ccache " - link_prefix = "ccache " -} else { - assembler_prefix = "" - compiler_prefix = "" - link_prefix = "" -} - -toolchain("fuchsia") { - toolchain_bin = - rebase_path("//buildtools/$host_os-x64/clang/bin", root_out_dir) - fuchsia_sdk = rebase_path("//third_party/fuchsia/sdk/$host_os", root_out_dir) - - # 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 = "${compiler_prefix}${toolchain_bin}/clang" - cxx = "${compiler_prefix}${toolchain_bin}/clang++" - asm = "${assembler_prefix}${toolchain_bin}/clang" - ar = "${toolchain_bin}/llvm-ar" - ld = "${link_prefix}${toolchain_bin}/clang++" - readelf = "${toolchain_bin}/llvm-readelf" - nm = "${toolchain_bin}/llvm-nm" - strip = "${toolchain_bin}/llvm-strip" - - if (target_cpu == "x64") { - target_triple_flags = "--target=x86_64-fuchsia" - } else if (target_cpu == "arm64") { - target_triple_flags = "--target=aarch64-fuchsia" - } else if (target_cpu == "riscv64") { - target_triple_flags = "--target=riscv64-fuchsia" - } else { - assert(false, "Unsupported target_cpu: $target_cpu") - } - - sysroot_flags = "--sysroot ${fuchsia_sdk}/arch/${target_cpu}/sysroot" - lto_flags = "" - - # These library switches can apply to all tools below. - lib_switch = "-l" - lib_dir_switch = "-L" - - tool("cc") { - depfile = "{{output}}.d" - command = "$cc -MD -MF $depfile $target_triple_flags $sysroot_flags $lto_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 -MD -MF $depfile $target_triple_flags $sysroot_flags $lto_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 = "$asm -MD -MF $depfile $target_triple_flags $sysroot_flags $lto_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. - unstripped_sofile = - "{{root_out_dir}}/so.unstripped/$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 $lto_flags -shared {{ldflags}} -o $unstripped_sofile -Wl,--build-id -Wl,-soname=$soname @$rspfile" - toc_command = "{ $readelf -d $unstripped_sofile | grep SONAME ; $nm -gD -f posix $unstripped_sofile | cut -f1-2 -d' '; } > $temporary_tocname" - replace_command = "if ! cmp -s $temporary_tocname $tocfile; then mv $temporary_tocname $tocfile; fi" - strip_command = "$strip -o $sofile $unstripped_sofile" - - command = - "$link_command && $toc_command && $replace_command && $strip_command" - rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}" - - description = "SOLINK $sofile" - - 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, - unstripped_sofile, - tocfile, - ] - - link_output = sofile - depend_output = tocfile - } - - tool("link") { - exename = "{{target_output_name}}{{output_extension}}" - outfile = "{{root_out_dir}}/$exename" - rspfile = "$outfile.rsp" - symfile = "$outfile.sym" - symbolizer_script = rebase_path("//runtime/tools/dart_profiler_symbols.py") - - # Note that the unstripped_outfile is in the exe.stripped folder. - # We should probably clean this up, but changing this and dart.cmx - # to point ./dart instead of ./exe.stripped/dart makes the build - # fail because ./dart does not end up in the manifest file. - unstripped_outfile = "{{root_out_dir}}/exe.stripped/$exename" - command = "$ld $target_triple_flags $sysroot_flags $lto_flags {{ldflags}} -o $unstripped_outfile -Wl,--build-id -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}} && ${strip} -o $outfile $unstripped_outfile && $symbolizer_script --nm $nm --output $symfile --binary $unstripped_outfile" - description = "LINK $outfile" - rspfile_content = "{{inputs}}" - outputs = [ - unstripped_outfile, - outfile, - symfile, - ] - } - - 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 - } +toolchain_suite("fuchsia") { + toolchain_template = "fuchsia_toolchain" } diff --git a/build/toolchain/fuchsia/fuchsia_toolchain.gni b/build/toolchain/fuchsia/fuchsia_toolchain.gni new file mode 100644 index 00000000000..368314c77dc --- /dev/null +++ b/build/toolchain/fuchsia/fuchsia_toolchain.gni @@ -0,0 +1,191 @@ +# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +# for details. 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/config/sysroot.gni") +import("//build/toolchain/ccache.gni") +import("//build/toolchain/gcc_toolchain.gni") +import("//build/toolchain/rbe.gni") + +if (use_ccache) { + assembler_prefix = "ccache " + compiler_prefix = "ccache " + link_prefix = "ccache " +} else { + assembler_prefix = "" + compiler_prefix = "" + link_prefix = "" +} + +template("fuchsia_toolchain") { + toolchain(target_name) { + toolchain_bin = + rebase_path("//buildtools/$host_os-x64/clang/bin", root_out_dir) + fuchsia_sdk = + rebase_path("//third_party/fuchsia/sdk/$host_os", root_out_dir) + + # 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 = "${compiler_prefix}${toolchain_bin}/clang" + cxx = "${compiler_prefix}${toolchain_bin}/clang++" + asm = "${assembler_prefix}${toolchain_bin}/clang" + ar = "${toolchain_bin}/llvm-ar" + ld = "${link_prefix}${toolchain_bin}/clang++" + readelf = "${toolchain_bin}/llvm-readelf" + nm = "${toolchain_bin}/llvm-nm" + strip = "${toolchain_bin}/llvm-strip" + + if (target_cpu == "x64") { + target_triple_flags = "--target=x86_64-fuchsia" + } else if (target_cpu == "arm64") { + target_triple_flags = "--target=aarch64-fuchsia" + } else if (target_cpu == "riscv64") { + target_triple_flags = "--target=riscv64-fuchsia" + } else { + assert(false, "Unsupported target_cpu: $target_cpu") + } + + sysroot_flags = "--sysroot ${fuchsia_sdk}/arch/${target_cpu}/sysroot" + lto_flags = "" + + # These library switches can apply to all tools below. + lib_switch = "-l" + lib_dir_switch = "-L" + + tool("cc") { + depfile = "{{output}}.d" + command = "$cc -MD -MF $depfile $target_triple_flags $sysroot_flags $lto_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 -MD -MF $depfile $target_triple_flags $sysroot_flags $lto_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 = "$asm -MD -MF $depfile $target_triple_flags $sysroot_flags $lto_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. + unstripped_sofile = + "{{root_out_dir}}/so.unstripped/$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 $lto_flags -shared {{ldflags}} -o $unstripped_sofile -Wl,--build-id -Wl,-soname=$soname @$rspfile" + toc_command = "{ $readelf -d $unstripped_sofile | grep SONAME ; $nm -gD -f posix $unstripped_sofile | cut -f1-2 -d' '; } > $temporary_tocname" + replace_command = "if ! cmp -s $temporary_tocname $tocfile; then mv $temporary_tocname $tocfile; fi" + strip_command = "$strip -o $sofile $unstripped_sofile" + + command = + "$link_command && $toc_command && $replace_command && $strip_command" + rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}" + + description = "SOLINK $sofile" + + 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, + unstripped_sofile, + tocfile, + ] + + link_output = sofile + depend_output = tocfile + } + + tool("link") { + exename = "{{target_output_name}}{{output_extension}}" + outfile = "{{root_out_dir}}/$exename" + rspfile = "$outfile.rsp" + symfile = "$outfile.sym" + symbolizer_script = + rebase_path("//runtime/tools/dart_profiler_symbols.py") + + # Note that the unstripped_outfile is in the exe.stripped folder. + # We should probably clean this up, but changing this and dart.cmx + # to point ./dart instead of ./exe.stripped/dart makes the build + # fail because ./dart does not end up in the manifest file. + unstripped_outfile = "{{root_out_dir}}/exe.stripped/$exename" + command = "$ld $target_triple_flags $sysroot_flags $lto_flags {{ldflags}} -o $unstripped_outfile -Wl,--build-id -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}} && ${strip} -o $outfile $unstripped_outfile && $symbolizer_script --nm $nm --output $symfile --binary $unstripped_outfile" + description = "LINK $outfile" + rspfile_content = "{{inputs}}" + outputs = [ + unstripped_outfile, + outfile, + symfile, + ] + } + + 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 + + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + } + } +} diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni index c8ecd82c1d8..63b44a0a385 100644 --- a/build/toolchain/gcc_toolchain.gni +++ b/build/toolchain/gcc_toolchain.gni @@ -257,6 +257,10 @@ template("gcc_toolchain") { if (defined(invoker.is_clang)) { is_clang = invoker.is_clang } + + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } } if (defined(invoker.deps)) { diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn index 22054c51a78..07f09b63e42 100644 --- a/build/toolchain/linux/BUILD.gn +++ b/build/toolchain/linux/BUILD.gn @@ -6,6 +6,7 @@ import("//build/config/sysroot.gni") import("//build/toolchain/ccache.gni") import("//build/toolchain/gcc_toolchain.gni") import("//build/toolchain/rbe.gni") +import("//build/toolchain/toolchain_suite.gni") declare_args() { ia32_toolchain_prefix = "" @@ -54,7 +55,14 @@ if (dart_sysroot == "alpine") { rebase_path("//buildtools/linux-x64/clang/bin", root_build_dir) } -gcc_toolchain("arm") { +template("gcc_toolchain_suite") { + toolchain_suite(target_name) { + toolchain_template = "gcc_toolchain" + forward_variables_from(invoker, "*") + } +} + +gcc_toolchain_suite("arm") { prefix = "arm-linux-gnueabihf-" if (arm_toolchain_prefix != "") { prefix = arm_toolchain_prefix @@ -75,7 +83,7 @@ gcc_toolchain("arm") { is_clang = false } -gcc_toolchain("clang_arm") { +gcc_toolchain_suite("clang_arm") { prefix = rebased_clang_dir cc = "${compiler_prefix}${prefix}/clang" cxx = "${compiler_prefix}${prefix}/clang++" @@ -97,7 +105,7 @@ gcc_toolchain("clang_arm") { is_clang = true } -gcc_toolchain("arm64") { +gcc_toolchain_suite("arm64") { prefix = "aarch64-linux-gnu-" if (arm64_toolchain_prefix != "") { prefix = arm64_toolchain_prefix @@ -118,7 +126,7 @@ gcc_toolchain("arm64") { is_clang = false } -gcc_toolchain("clang_arm64") { +gcc_toolchain_suite("clang_arm64") { prefix = rebased_clang_dir cc = "${compiler_prefix}${prefix}/clang" cxx = "${compiler_prefix}${prefix}/clang++" @@ -140,7 +148,7 @@ gcc_toolchain("clang_arm64") { is_clang = true } -gcc_toolchain("clang_x86") { +gcc_toolchain_suite("clang_x86") { prefix = rebased_clang_dir cc = "${compiler_prefix}${prefix}/clang" cxx = "${compiler_prefix}${prefix}/clang++" @@ -162,7 +170,7 @@ gcc_toolchain("clang_x86") { is_clang = true } -gcc_toolchain("x86") { +gcc_toolchain_suite("x86") { prefix = "i686-linux-gnu-" if (ia32_toolchain_prefix != "") { prefix = ia32_toolchain_prefix @@ -182,7 +190,7 @@ gcc_toolchain("x86") { is_clang = false } -gcc_toolchain("clang_x64") { +gcc_toolchain_suite("clang_x64") { prefix = rebased_clang_dir cc = "${compiler_prefix}${prefix}/clang" cxx = "${compiler_prefix}${prefix}/clang++" @@ -204,7 +212,7 @@ gcc_toolchain("clang_x64") { is_clang = true } -gcc_toolchain("x64") { +gcc_toolchain_suite("x64") { prefix = "x86_64-linux-gnu-" if (x64_toolchain_prefix != "") { prefix = x64_toolchain_prefix @@ -224,7 +232,7 @@ gcc_toolchain("x64") { is_clang = false } -gcc_toolchain("riscv32") { +gcc_toolchain_suite("riscv32") { prefix = "riscv32-linux-gnu-" if (riscv32_toolchain_prefix != "") { prefix = riscv32_toolchain_prefix @@ -245,7 +253,7 @@ gcc_toolchain("riscv32") { is_clang = false } -gcc_toolchain("clang_riscv32") { +gcc_toolchain_suite("clang_riscv32") { prefix = rebased_clang_dir cc = "${compiler_prefix}${prefix}/clang" cxx = "${compiler_prefix}${prefix}/clang++" @@ -267,7 +275,7 @@ gcc_toolchain("clang_riscv32") { is_clang = true } -gcc_toolchain("riscv64") { +gcc_toolchain_suite("riscv64") { prefix = "riscv64-linux-gnu-" if (riscv64_toolchain_prefix != "") { prefix = riscv64_toolchain_prefix @@ -288,7 +296,7 @@ gcc_toolchain("riscv64") { is_clang = false } -gcc_toolchain("clang_riscv64") { +gcc_toolchain_suite("clang_riscv64") { prefix = rebased_clang_dir cc = "${compiler_prefix}${prefix}/clang" cxx = "${compiler_prefix}${prefix}/clang++" diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn index 02a0e43bac3..24f4755f51f 100644 --- a/build/toolchain/mac/BUILD.gn +++ b/build/toolchain/mac/BUILD.gn @@ -1,277 +1,14 @@ -# Copyright (c) 2013 The Chromium 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/toolchain_suite.gni") -# TODO(brettw) Use "gcc_toolchain.gni" like the Linux toolchains. This requires -# some enhancements since the commands on Mac are slightly different than on -# Linux. - -import("//build/config/ios/ios_sdk.gni") -import("//build/config/mac/mac_sdk.gni") - -assert(host_os == "mac") - -import("//build/config/sysroot.gni") -import("//build/toolchain/rbe.gni") -import("//build/toolchain/signing.gni") - -if (use_rbe) { - compiler_args = - rewrapper_args + [ "--labels=type=compile,compiler=clang,lang=cpp" ] - if (rbe_os != host_os || rbe_cpu != host_cpu) { - compiler_args += [ - "--inputs=build/rbe,buildtools/$rbe_os-$rbe_cpu/clang/bin/llvm", - "--remote_wrapper=../../build/rbe/llvm.sh", - ] - } - assembler_prefix = "" - compiler_prefix = string_join(" ", compiler_args) + " " - link_prefix = "" -} else { - assembler_prefix = "" - compiler_prefix = "" - link_prefix = "" -} - -if (host_cpu == "arm64") { - rebased_clang_dir = - rebase_path("//buildtools/mac-arm64/clang/bin", root_build_dir) -} else { - rebased_clang_dir = - rebase_path("//buildtools/mac-x64/clang/bin", root_build_dir) -} - -# Shared toolchain definition. Invocations should set toolchain_os to set the -# build args in this definition. -template("mac_toolchain") { - toolchain(target_name) { - assert(defined(invoker.asm), "mac_toolchain() must specify a \"asm\" value") - assert(defined(invoker.cc), "mac_toolchain() must specify a \"cc\" value") - assert(defined(invoker.cxx), "mac_toolchain() must specify a \"cxx\" value") - assert(defined(invoker.ar), "mac_toolchain() must specify an \"ar\" value") - assert(defined(invoker.ld), "mac_toolchain() must specify a \"ld\" value") - assert(defined(invoker.toolchain_cpu), - "mac_toolchain() must specify a \"toolchain_cpu\"") - assert(defined(invoker.toolchain_os), - "mac_toolchain() must specify a \"toolchain_os\"") - - # 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. - asm = invoker.asm - cc = invoker.cc - cxx = invoker.cxx - ar = invoker.ar - ld = invoker.ld - nm = invoker.nm - - # Make these apply to all tools below. - lib_switch = "-l" - lib_dir_switch = "-L" - - sysroot_flags = "" - - if (defined(invoker.sysroot_flags)) { - sysroot_flags = invoker.sysroot_flags - } - - toolchain_flags = "" - if (invoker.toolchain_cpu == "i386") { - toolchain_flags = "-m32" - } - - tool("cc") { - depfile = "{{output}}.d" - command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{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 {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{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") { - # For GCC we can just use the C compiler to compile assembly. - depfile = "{{output}}.d" - command = "$asm -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{asmflags}} -c {{source}} -o {{output}}" - depsformat = "gcc" - description = "ASM {{output}}" - outputs = - [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] - } - - tool("objc") { - depfile = "{{output}}.d" - command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{cflags}} {{cflags_c}} {{cflags_objc}} -c {{source}} -o {{output}}" - depsformat = "gcc" - description = "OBJC {{output}}" - outputs = - [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] - } - - tool("objcxx") { - depfile = "{{output}}.d" - command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{cflags}} {{cflags_cc}} {{cflags_objcc}} -c {{source}} -o {{output}}" - depsformat = "gcc" - description = "OBJCXX {{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") { - dylib = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" # eg - # "./libfoo.dylib" - rspfile = dylib + ".rsp" - - # These variables are not build 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. - # - # As a special case, if the library reexports symbols from other dynamic - # libraries, we always update the .TOC and skip the temporary file and - # diffing steps, since that library always needs to be re-linked. - tocname = dylib + ".TOC" - temporary_tocname = dylib + ".tmp" - - does_reexport_command = "[ ! -e $dylib -o ! -e $tocname ] || otool -l $dylib | grep -q LC_REEXPORT_DYLIB" - link_command = "$ld -shared $sysroot_flags $toolchain_flags {{ldflags}} -o $dylib -Wl,-filelist,$rspfile {{solibs}} {{libs}} {{frameworks}}" - replace_command = "if ! cmp -s $temporary_tocname $tocname; then mv $temporary_tocname $tocname" - extract_toc_command = "{ otool -l $dylib | grep LC_ID_DYLIB -A 5; nm -gP $dylib | cut -f1-2 -d' ' | grep -v U\$\$; true; }" - - command = "if $does_reexport_command ; then $link_command && $extract_toc_command > $tocname; else $link_command && $extract_toc_command > $temporary_tocname && $replace_command ; fi; fi" - - rspfile_content = "{{inputs_newline}}" - - description = "SOLINK {{output}}" - - # 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 = ".dylib" - - 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 dylib but use the - # tocname for dependency management. - outputs = [ - dylib, - tocname, - ] - link_output = dylib - depend_output = tocname - } - - tool("link") { - exename = "{{target_output_name}}{{output_extension}}" - outfile = "{{root_out_dir}}/$exename" - rspfile = "$outfile.rsp" - symfile = "$outfile.sym" - - if (defined(invoker.strip)) { - stripped_outfile = "{{root_out_dir}}/exe.stripped/$exename" - } - - commands = [ "$ld $sysroot_flags $toolchain_flags {{ldflags}} -Xlinker -rpath -Xlinker @executable_path/Frameworks -o $outfile -Wl,-filelist,$rspfile {{solibs}} {{libs}} {{frameworks}}" ] - - symbolizer_script = - rebase_path("//runtime/tools/dart_profiler_symbols.py") - commands += - [ "$symbolizer_script --nm $nm --output $symfile --binary $outfile" ] - - if (defined(invoker.strip)) { - strip = invoker.strip - commands += [ "${strip} -x -o $stripped_outfile $outfile" ] - } - - if (codesigning_identity != "") { - # codesign tool performs signing in-place. This does not fit very well - # into the overall build: we would have to produce unsigned binary with - # some suffix (e.g. dart_unsigned), then copy it to the final location - # and sign. To avoid this dance we choose to perform signing here - # at the link step. Unfortunately this also comes with some limitations: - # executable target can't push arbitrary configuration variables down - # to the link step. Which means we can't specify per target - # entitlement files - and instead rely on dart_codesign.py script to - # match binaries to their entitlement files by name. - signing_script = rebase_path("//runtime/tools/dart_codesign.py") - binaries_to_sign = [ - "--binary", - outfile, - ] - if (defined(stripped_outfile)) { - binaries_to_sign += [ - "--binary", - stripped_outfile, - ] - } - commands += [ "$signing_script --identity $codesigning_identity " + - string_join(" ", binaries_to_sign) ] - } - - command = string_join(" && ", commands) - description = "LINK $outfile" - rspfile_content = "{{inputs_newline}}" - outputs = [ - outfile, - symfile, - ] - if (defined(invoker.strip)) { - outputs += [ stripped_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}}" - } - - toolchain_args = { - current_cpu = invoker.toolchain_cpu - current_os = invoker.toolchain_os - - # These values need to be passed through unchanged. - target_os = target_os - target_cpu = target_cpu - - if (defined(invoker.is_clang)) { - is_clang = invoker.is_clang - } - } +template("mac_toolchain_suite") { + toolchain_suite(target_name) { + toolchain_template = "mac_toolchain" + forward_variables_from(invoker, "*") } } # Toolchain used for iOS device targets. -mac_toolchain("ios_clang_arm64") { +mac_toolchain_suite("ios_clang_arm64") { toolchain_cpu = "arm64" toolchain_os = "ios" prefix = rebased_clang_dir @@ -294,7 +31,7 @@ mac_toolchain("ios_clang_arm64") { } # Toolchain used for iOS simulator targets (arm64). -mac_toolchain("ios_clang_arm64_sim") { +mac_toolchain_suite("ios_clang_arm64_sim") { toolchain_cpu = "arm64" toolchain_os = "ios" prefix = rebased_clang_dir @@ -318,7 +55,7 @@ mac_toolchain("ios_clang_arm64_sim") { } # Toolchain used for iOS simulator targets (x64). -mac_toolchain("ios_clang_x64_sim") { +mac_toolchain_suite("ios_clang_x64_sim") { toolchain_cpu = "x64" toolchain_os = "ios" prefix = rebased_clang_dir @@ -341,7 +78,7 @@ mac_toolchain("ios_clang_x64_sim") { "-isysroot $ios_sdk_path -mios-simulator-version-min=$ios_sdk_min" } -mac_toolchain("clang_x64") { +mac_toolchain_suite("clang_x64") { toolchain_cpu = "x64" toolchain_os = "mac" prefix = rebased_clang_dir @@ -363,7 +100,7 @@ mac_toolchain("clang_x64") { sysroot_flags = "-isysroot $mac_sdk_path -mmacosx-version-min=$mac_sdk_min" } -mac_toolchain("clang_arm64") { +mac_toolchain_suite("clang_arm64") { toolchain_cpu = "arm64" toolchain_os = "mac" prefix = rebased_clang_dir diff --git a/build/toolchain/mac/mac_toolchain.gni b/build/toolchain/mac/mac_toolchain.gni new file mode 100644 index 00000000000..e3f7f1eb696 --- /dev/null +++ b/build/toolchain/mac/mac_toolchain.gni @@ -0,0 +1,275 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# TODO(brettw) Use "gcc_toolchain.gni" like the Linux toolchains. This requires +# some enhancements since the commands on Mac are slightly different than on +# Linux. + +import("//build/config/ios/ios_sdk.gni") +import("//build/config/mac/mac_sdk.gni") + +assert(host_os == "mac") + +import("//build/config/sysroot.gni") +import("//build/toolchain/rbe.gni") +import("//build/toolchain/signing.gni") + +if (use_rbe) { + compiler_args = + rewrapper_args + [ "--labels=type=compile,compiler=clang,lang=cpp" ] + if (rbe_os != host_os || rbe_cpu != host_cpu) { + compiler_args += [ + "--inputs=build/rbe,buildtools/$rbe_os-$rbe_cpu/clang/bin/llvm", + "--remote_wrapper=../../build/rbe/llvm.sh", + ] + } + assembler_prefix = "" + compiler_prefix = string_join(" ", compiler_args) + " " + link_prefix = "" +} else { + assembler_prefix = "" + compiler_prefix = "" + link_prefix = "" +} + +if (host_cpu == "arm64") { + rebased_clang_dir = + rebase_path("//buildtools/mac-arm64/clang/bin", root_build_dir) +} else { + rebased_clang_dir = + rebase_path("//buildtools/mac-x64/clang/bin", root_build_dir) +} + +# Shared toolchain definition. Invocations should set toolchain_os to set the +# build args in this definition. +template("mac_toolchain") { + toolchain(target_name) { + assert(defined(invoker.asm), "mac_toolchain() must specify a \"asm\" value") + assert(defined(invoker.cc), "mac_toolchain() must specify a \"cc\" value") + assert(defined(invoker.cxx), "mac_toolchain() must specify a \"cxx\" value") + assert(defined(invoker.ar), "mac_toolchain() must specify an \"ar\" value") + assert(defined(invoker.ld), "mac_toolchain() must specify a \"ld\" value") + assert(defined(invoker.toolchain_cpu), + "mac_toolchain() must specify a \"toolchain_cpu\"") + assert(defined(invoker.toolchain_os), + "mac_toolchain() must specify a \"toolchain_os\"") + + # 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. + asm = invoker.asm + cc = invoker.cc + cxx = invoker.cxx + ar = invoker.ar + ld = invoker.ld + nm = invoker.nm + + # Make these apply to all tools below. + lib_switch = "-l" + lib_dir_switch = "-L" + + sysroot_flags = "" + + if (defined(invoker.sysroot_flags)) { + sysroot_flags = invoker.sysroot_flags + } + + toolchain_flags = "" + if (invoker.toolchain_cpu == "i386") { + toolchain_flags = "-m32" + } + + tool("cc") { + depfile = "{{output}}.d" + command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{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 {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{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") { + # For GCC we can just use the C compiler to compile assembly. + depfile = "{{output}}.d" + command = "$asm -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{asmflags}} -c {{source}} -o {{output}}" + depsformat = "gcc" + description = "ASM {{output}}" + outputs = + [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] + } + + tool("objc") { + depfile = "{{output}}.d" + command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{cflags}} {{cflags_c}} {{cflags_objc}} -c {{source}} -o {{output}}" + depsformat = "gcc" + description = "OBJC {{output}}" + outputs = + [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ] + } + + tool("objcxx") { + depfile = "{{output}}.d" + command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} $sysroot_flags $toolchain_flags {{cflags}} {{cflags_cc}} {{cflags_objcc}} -c {{source}} -o {{output}}" + depsformat = "gcc" + description = "OBJCXX {{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") { + dylib = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" # eg + # "./libfoo.dylib" + rspfile = dylib + ".rsp" + + # These variables are not build 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. + # + # As a special case, if the library reexports symbols from other dynamic + # libraries, we always update the .TOC and skip the temporary file and + # diffing steps, since that library always needs to be re-linked. + tocname = dylib + ".TOC" + temporary_tocname = dylib + ".tmp" + + does_reexport_command = "[ ! -e $dylib -o ! -e $tocname ] || otool -l $dylib | grep -q LC_REEXPORT_DYLIB" + link_command = "$ld -shared $sysroot_flags $toolchain_flags {{ldflags}} -o $dylib -Wl,-filelist,$rspfile {{solibs}} {{libs}} {{frameworks}}" + replace_command = "if ! cmp -s $temporary_tocname $tocname; then mv $temporary_tocname $tocname" + extract_toc_command = "{ otool -l $dylib | grep LC_ID_DYLIB -A 5; nm -gP $dylib | cut -f1-2 -d' ' | grep -v U\$\$; true; }" + + command = "if $does_reexport_command ; then $link_command && $extract_toc_command > $tocname; else $link_command && $extract_toc_command > $temporary_tocname && $replace_command ; fi; fi" + + rspfile_content = "{{inputs_newline}}" + + description = "SOLINK {{output}}" + + # 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 = ".dylib" + + 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 dylib but use the + # tocname for dependency management. + outputs = [ + dylib, + tocname, + ] + link_output = dylib + depend_output = tocname + } + + tool("link") { + exename = "{{target_output_name}}{{output_extension}}" + outfile = "{{root_out_dir}}/$exename" + rspfile = "$outfile.rsp" + symfile = "$outfile.sym" + + if (defined(invoker.strip)) { + stripped_outfile = "{{root_out_dir}}/exe.stripped/$exename" + } + + commands = [ "$ld $sysroot_flags $toolchain_flags {{ldflags}} -Xlinker -rpath -Xlinker @executable_path/Frameworks -o $outfile -Wl,-filelist,$rspfile {{solibs}} {{libs}} {{frameworks}}" ] + + symbolizer_script = + rebase_path("//runtime/tools/dart_profiler_symbols.py") + commands += + [ "$symbolizer_script --nm $nm --output $symfile --binary $outfile" ] + + if (defined(invoker.strip)) { + strip = invoker.strip + commands += [ "${strip} -x -o $stripped_outfile $outfile" ] + } + + if (codesigning_identity != "") { + # codesign tool performs signing in-place. This does not fit very well + # into the overall build: we would have to produce unsigned binary with + # some suffix (e.g. dart_unsigned), then copy it to the final location + # and sign. To avoid this dance we choose to perform signing here + # at the link step. Unfortunately this also comes with some limitations: + # executable target can't push arbitrary configuration variables down + # to the link step. Which means we can't specify per target + # entitlement files - and instead rely on dart_codesign.py script to + # match binaries to their entitlement files by name. + signing_script = rebase_path("//runtime/tools/dart_codesign.py") + binaries_to_sign = [ + "--binary", + outfile, + ] + if (defined(stripped_outfile)) { + binaries_to_sign += [ + "--binary", + stripped_outfile, + ] + } + commands += [ "$signing_script --identity $codesigning_identity " + + string_join(" ", binaries_to_sign) ] + } + + command = string_join(" && ", commands) + description = "LINK $outfile" + rspfile_content = "{{inputs_newline}}" + outputs = [ + outfile, + symfile, + ] + if (defined(invoker.strip)) { + outputs += [ stripped_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}}" + } + + toolchain_args = { + current_cpu = invoker.toolchain_cpu + current_os = invoker.toolchain_os + + # These values need to be passed through unchanged. + target_os = target_os + target_cpu = target_cpu + + if (defined(invoker.is_clang)) { + is_clang = invoker.is_clang + } + + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + } + } +} diff --git a/build/toolchain/toolchain_suite.gni b/build/toolchain/toolchain_suite.gni new file mode 100644 index 00000000000..9c6d0b7b476 --- /dev/null +++ b/build/toolchain/toolchain_suite.gni @@ -0,0 +1,52 @@ +# Converts a single toolchain definition into multple toolchains with +# different toolchain args. + +# Even though these imports aren't used directly, they are required so +# that the template works when it is called. +import("//build/toolchain/android/android_toolchain.gni") +import("//build/toolchain/gcc_toolchain.gni") +if (host_os == "mac") { + import("//build/toolchain/mac/mac_toolchain.gni") +} +if (is_win) { + import("//build/toolchain/win/msvc_toolchain.gni") +} +if (is_fuchsia) { + import("//build/toolchain/fuchsia/fuchsia_toolchain.gni") +} + +_all_toolchains = [ + # default toolchain. + { + suffix = "" + toolchain_args = { + is_shared_library = false + } + }, + + # toolchain for building shared libraries. + { + suffix = "_shared" + toolchain_args = { + is_shared_library = true + } + }, +] + +template("toolchain_suite") { + assert(defined(invoker.toolchain_template), + "tolchain_suite() must specify a \"toolchain_template\" value") + _target_type = invoker.toolchain_template + foreach(conf, _all_toolchains) { + target(_target_type, "${target_name}${conf.suffix}") { + forward_variables_from(invoker, "*", [ "toolchain_args" ]) + + toolchain_args = { + forward_variables_from(conf.toolchain_args, "*") + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + } + } + } +} diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn index cbb9a87c2c4..02871cbc443 100644 --- a/build/toolchain/win/BUILD.gn +++ b/build/toolchain/win/BUILD.gn @@ -2,260 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -declare_args() { - # Path to the clang toolchain. - clang_base_path = "//buildtools/win-x64/clang" -} - import("//build/config/win/visual_studio_version.gni") import("//build/toolchain/rbe.gni") +import("//build/toolchain/toolchain_suite.gni") -# Should only be running on Windows. -assert(is_win) - -# Setup the Visual Studio state. -# -# Its arguments are the VS path and the compiler wrapper tool. It will write -# "environment.x86" and "environment.x64" to the build directory and return a -# list to us. - -# This tool will is used as a wrapper for various commands below. -tool_wrapper_path = rebase_path("tool_wrapper.py", root_build_dir) - -ninja_path = rebase_path("//buildtools/ninja/ninja") - -if (use_rbe) { - compiler_args = - rewrapper_args + [ "--labels=type=compile,compiler=clang-cl,lang=cpp" ] - if (rbe_os != host_os || rbe_cpu != host_cpu) { - compiler_args += [ - "--env_var_allowlist=INCLUDE", - "--inputs=build/rbe,buildtools/$rbe_os-$rbe_cpu/clang/bin/llvm", - "--remote_wrapper=../../build/rbe/llvm.sh", - ] - } - compiler_prefix = string_join(" ", compiler_args) + " " -} else { - compiler_prefix = "" -} - -if (current_toolchain == default_toolchain) { - if (is_debug) { - configuration = "Debug" - } else { - configuration = "Release" - } - exec_script("//build/vs_toolchain.py", - [ - "copy_dlls", - rebase_path(root_build_dir), - configuration, - target_cpu, - ]) -} - -# Parameters: -# toolchain_args: Settings for the toolchain, including at least: -# current_cpu: current_cpu to pass as a build arg -# environment: File name of environment file. -template("msvc_toolchain") { - toolchain(target_name) { - # 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. - assert(defined(invoker.toolchain_args)) - toolchain_args = { - if (defined(invoker.toolchain_args)) { - forward_variables_from(invoker.toolchain_args, "*") - } - } - - env = invoker.environment - - cl = invoker.cl - - # Make these apply to all tools below. - lib_switch = "" - lib_dir_switch = "/LIBPATH:" - - tool("cc") { - rspfile = "{{output}}.rsp" - - # TODO(brettw) enable this when GN support in the binary has been rolled. - #precompiled_header_type = "msvc" - pdbname = "{{target_out_dir}}/{{target_output_name}}_c.pdb" - command = "$ninja_path -t msvc -e $env -- $cl /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} /c {{source}} /Fo{{output}} /Fd$pdbname" - depsformat = "msvc" - description = "CC {{output}}" - outputs = [ - "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", - ] - rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}" - } - - tool("cxx") { - rspfile = "{{output}}.rsp" - - # TODO(brettw) enable this when GN support in the binary has been rolled. - #precompiled_header_type = "msvc" - - # The PDB name needs to be different between C and C++ compiled files. - pdbname = "{{target_out_dir}}/{{target_output_name}}_cc.pdb" - flags = "" - if (is_clang && invoker.current_cpu == "x86") { - flags = "-m32" - } - command = "$ninja_path -t msvc -e $env -- $cl $flags /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} /c {{source}} /Fo{{output}} /Fd$pdbname" - depsformat = "msvc" - description = "CXX {{output}}" - outputs = [ - "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", - ] - rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}" - } - - tool("rc") { - command = "$python_path $tool_wrapper_path rc-wrapper $env rc.exe /nologo {{defines}} {{include_dirs}} /fo{{output}} {{source}}" - depsformat = "msvc" - outputs = [ - "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.res", - ] - description = "RC {{output}}" - } - - tool("asm") { - if (toolchain_args.current_cpu == "x86") { - command = "$python_path $tool_wrapper_path asm-wrapper $env ml.exe {{defines}} {{include_dirs}} {{asmflags}} /c /Fo {{output}} {{source}}" - } else if (toolchain_args.current_cpu == "x64") { - command = "$python_path $tool_wrapper_path asm-wrapper $env ml64.exe -D_ML64_X64 {{defines}} {{include_dirs}} {{asmflags}} /c /Fo {{output}} {{source}}" - } else if (toolchain_args.current_cpu == "arm") { - command = "$python_path $tool_wrapper_path asm-wrapper $env armasm.exe {{include_dirs}} {{asmflags}} -o {{output}} {{source}}" - } else if (toolchain_args.current_cpu == "arm64") { - command = "$python_path $tool_wrapper_path asm-wrapper $env armasm64.exe {{include_dirs}} {{asmflags}} -o {{output}} {{source}}" - } else { - assert(false, "Unknown current_cpu: ${toolchain_args.current_cpu}") - } - description = "ASM {{output}}" - outputs = [ - "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", - ] - } - - if (is_clang) { - prefix = rebase_path("$clang_base_path/bin", root_build_dir) - lib = "$prefix/lld-link.exe /lib" - link = "$prefix/lld-link.exe" - } else { - lib = "lib.exe" - link = "link.exe" - } - - tool("alink") { - rspfile = "{{output}}.rsp" - command = "$python_path $tool_wrapper_path link-wrapper $env False $lib /nologo /ignore:4221 /OUT:{{output}} @$rspfile" - description = "LIB {{output}}" - outputs = [ - # Ignore {{output_extension}} and always use .lib, there's no reason to - # allow targets to override this extension on Windows. - "{{target_out_dir}}/{{target_output_name}}.lib", - ] - default_output_extension = ".lib" - - # The use of inputs_newline is to work around a fixed per-line buffer - # size in the linker. - rspfile_content = "{{inputs_newline}}" - } - - tool("solink") { - dllname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" # e.g. - # foo.dll - libname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib" # e.g. - # foo.dll.lib - rspfile = "${dllname}.rsp" - - link_command = "$python_path $tool_wrapper_path link-wrapper $env False $link /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:${dllname}.pdb @$rspfile" - - # TODO(brettw) support manifests - #manifest_command = "$python_path $tool_wrapper_path manifest-wrapper $env mt.exe -nologo -manifest $manifests -out:${dllname}.manifest" - #command = "cmd /c $link_command && $manifest_command" - command = link_command - - default_output_extension = ".dll" - description = "LINK(DLL) {{output}}" - outputs = [ - dllname, - libname, - ] - link_output = libname - depend_output = libname - - # The use of inputs_newline is to work around a fixed per-line buffer - # size in the linker. - rspfile_content = "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}}" - - restat = true - } - - tool("solink_module") { - dllname = - "{{output_dir}}/{{target_output_name}}{{output_extension}}" # e.g. - # foo.dll - pdbname = "${dllname}.pdb" - rspfile = "${dllname}.rsp" - - command = "$python_path $tool_wrapper_path link-wrapper $env False link.exe /nologo /DLL /OUT:$dllname /PDB:$pdbname @$rspfile" - default_output_extension = ".dll" - default_output_dir = "{{root_out_dir}}" - description = "LINK_MODULE(DLL) {{output}}" - outputs = [ - dllname, - pdbname, - ] - runtime_outputs = outputs - - # The use of inputs_newline is to work around a fixed per-line buffer - # size in the linker. - rspfile_content = "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}}" - - restat = true - } - - tool("link") { - binary_output = - "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" - rspfile = "$binary_output.rsp" - pdbfile = "$binary_output.pdb" - - link_command = "$python_path $tool_wrapper_path link-wrapper $env False $link /nologo /OUT:$binary_output /PDB:$pdbfile @$rspfile" - - # TODO(brettw) support manifests - #manifest_command = "$python_path $tool_wrapper_path manifest-wrapper $env mt.exe -nologo -manifest $manifests -out:{{output}}.manifest" - #command = "cmd /c $link_command && $manifest_command" - command = link_command - - default_output_extension = ".exe" - description = "LINK $binary_output" - outputs = [ - binary_output, - "{{root_out_dir}}/{{target_output_name}}.lib", - pdbfile, - ] - - # The use of inputs_newline is to work around a fixed per-line buffer - # size in the linker. - rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}" - - restat = true - } - - tool("stamp") { - command = "cmd /c type nul > \"{{output}}\"" - description = "STAMP {{output}}" - } - - tool("copy") { - command = "$python_path $tool_wrapper_path recursive-mirror {{source}} {{output}}" - description = "COPY {{source}} {{output}}" - } +template("msvc_toolchain_suite") { + toolchain_suite(target_name) { + toolchain_template = "msvc_toolchain" + forward_variables_from(invoker, "*") } } @@ -274,7 +28,7 @@ template("win_toolchains") { ], "scope") - msvc_toolchain(target_name) { + msvc_toolchain_suite(target_name) { environment = "environment." + toolchain_arch cl = "${compiler_prefix}\"${win_toolchain_data.vc_bin_dir}/cl.exe\"" toolchain_args = { @@ -285,7 +39,7 @@ template("win_toolchains") { is_clang = false } } - msvc_toolchain("clang_" + target_name) { + msvc_toolchain_suite("clang_" + target_name) { environment = "environment." + toolchain_arch prefix = rebase_path("$clang_base_path/bin", root_build_dir) cl = "${compiler_prefix}$prefix/clang-cl.exe" diff --git a/build/toolchain/win/msvc_toolchain.gni b/build/toolchain/win/msvc_toolchain.gni new file mode 100644 index 00000000000..a0448602241 --- /dev/null +++ b/build/toolchain/win/msvc_toolchain.gni @@ -0,0 +1,259 @@ +# Copyright (c) 2013 The Chromium 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 the clang toolchain. + clang_base_path = "//buildtools/win-x64/clang" +} + +import("//build/toolchain/rbe.gni") + +# Should only be running on Windows. +assert(is_win) + +# Setup the Visual Studio state. +# +# Its arguments are the VS path and the compiler wrapper tool. It will write +# "environment.x86" and "environment.x64" to the build directory and return a +# list to us. + +# This tool will is used as a wrapper for various commands below. +tool_wrapper_path = rebase_path("tool_wrapper.py", root_build_dir) + +ninja_path = rebase_path("//buildtools/ninja/ninja") + +if (use_rbe) { + compiler_args = + rewrapper_args + [ "--labels=type=compile,compiler=clang-cl,lang=cpp" ] + if (rbe_os != host_os || rbe_cpu != host_cpu) { + compiler_args += [ + "--env_var_allowlist=INCLUDE", + "--inputs=build/rbe,buildtools/$rbe_os-$rbe_cpu/clang/bin/llvm", + "--remote_wrapper=../../build/rbe/llvm.sh", + ] + } + compiler_prefix = string_join(" ", compiler_args) + " " +} else { + compiler_prefix = "" +} + +if (current_toolchain == default_toolchain) { + if (is_debug) { + configuration = "Debug" + } else { + configuration = "Release" + } + exec_script("//build/vs_toolchain.py", + [ + "copy_dlls", + rebase_path(root_build_dir), + configuration, + target_cpu, + ]) +} + +# Parameters: +# toolchain_args: Settings for the toolchain, including at least: +# current_cpu: current_cpu to pass as a build arg +# environment: File name of environment file. +template("msvc_toolchain") { + toolchain(target_name) { + # 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. + assert(defined(invoker.toolchain_args)) + toolchain_args = { + if (defined(invoker.toolchain_args)) { + forward_variables_from(invoker.toolchain_args, "*") + } + } + + env = invoker.environment + + cl = invoker.cl + + # Make these apply to all tools below. + lib_switch = "" + lib_dir_switch = "/LIBPATH:" + + tool("cc") { + rspfile = "{{output}}.rsp" + + # TODO(brettw) enable this when GN support in the binary has been rolled. + #precompiled_header_type = "msvc" + pdbname = "{{target_out_dir}}/{{target_output_name}}_c.pdb" + command = "$ninja_path -t msvc -e $env -- $cl /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} /c {{source}} /Fo{{output}} /Fd$pdbname" + depsformat = "msvc" + description = "CC {{output}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", + ] + rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}" + } + + tool("cxx") { + rspfile = "{{output}}.rsp" + + # TODO(brettw) enable this when GN support in the binary has been rolled. + #precompiled_header_type = "msvc" + + # The PDB name needs to be different between C and C++ compiled files. + pdbname = "{{target_out_dir}}/{{target_output_name}}_cc.pdb" + flags = "" + if (is_clang && invoker.current_cpu == "x86") { + flags = "-m32" + } + command = "$ninja_path -t msvc -e $env -- $cl $flags /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} /c {{source}} /Fo{{output}} /Fd$pdbname" + depsformat = "msvc" + description = "CXX {{output}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", + ] + rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}" + } + + tool("rc") { + command = "$python_path $tool_wrapper_path rc-wrapper $env rc.exe /nologo {{defines}} {{include_dirs}} /fo{{output}} {{source}}" + depsformat = "msvc" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.res", + ] + description = "RC {{output}}" + } + + tool("asm") { + if (toolchain_args.current_cpu == "x86") { + command = "$python_path $tool_wrapper_path asm-wrapper $env ml.exe {{defines}} {{include_dirs}} {{asmflags}} /c /Fo {{output}} {{source}}" + } else if (toolchain_args.current_cpu == "x64") { + command = "$python_path $tool_wrapper_path asm-wrapper $env ml64.exe -D_ML64_X64 {{defines}} {{include_dirs}} {{asmflags}} /c /Fo {{output}} {{source}}" + } else if (toolchain_args.current_cpu == "arm") { + command = "$python_path $tool_wrapper_path asm-wrapper $env armasm.exe {{include_dirs}} {{asmflags}} -o {{output}} {{source}}" + } else if (toolchain_args.current_cpu == "arm64") { + command = "$python_path $tool_wrapper_path asm-wrapper $env armasm64.exe {{include_dirs}} {{asmflags}} -o {{output}} {{source}}" + } else { + assert(false, "Unknown current_cpu: ${toolchain_args.current_cpu}") + } + description = "ASM {{output}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", + ] + } + + if (is_clang) { + prefix = rebase_path("$clang_base_path/bin", root_build_dir) + lib = "$prefix/lld-link.exe /lib" + link = "$prefix/lld-link.exe" + } else { + lib = "lib.exe" + link = "link.exe" + } + + tool("alink") { + rspfile = "{{output}}.rsp" + command = "$python_path $tool_wrapper_path link-wrapper $env False $lib /nologo /ignore:4221 /OUT:{{output}} @$rspfile" + description = "LIB {{output}}" + outputs = [ + # Ignore {{output_extension}} and always use .lib, there's no reason to + # allow targets to override this extension on Windows. + "{{target_out_dir}}/{{target_output_name}}.lib", + ] + default_output_extension = ".lib" + + # The use of inputs_newline is to work around a fixed per-line buffer + # size in the linker. + rspfile_content = "{{inputs_newline}}" + } + + tool("solink") { + dllname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" # e.g. + # foo.dll + libname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib" # e.g. + # foo.dll.lib + rspfile = "${dllname}.rsp" + + link_command = "$python_path $tool_wrapper_path link-wrapper $env False $link /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:${dllname}.pdb @$rspfile" + + # TODO(brettw) support manifests + #manifest_command = "$python_path $tool_wrapper_path manifest-wrapper $env mt.exe -nologo -manifest $manifests -out:${dllname}.manifest" + #command = "cmd /c $link_command && $manifest_command" + command = link_command + + default_output_extension = ".dll" + description = "LINK(DLL) {{output}}" + outputs = [ + dllname, + libname, + ] + link_output = libname + depend_output = libname + + # The use of inputs_newline is to work around a fixed per-line buffer + # size in the linker. + rspfile_content = "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}}" + + restat = true + } + + tool("solink_module") { + dllname = + "{{output_dir}}/{{target_output_name}}{{output_extension}}" # e.g. + # foo.dll + pdbname = "${dllname}.pdb" + rspfile = "${dllname}.rsp" + + command = "$python_path $tool_wrapper_path link-wrapper $env False link.exe /nologo /DLL /OUT:$dllname /PDB:$pdbname @$rspfile" + default_output_extension = ".dll" + default_output_dir = "{{root_out_dir}}" + description = "LINK_MODULE(DLL) {{output}}" + outputs = [ + dllname, + pdbname, + ] + runtime_outputs = outputs + + # The use of inputs_newline is to work around a fixed per-line buffer + # size in the linker. + rspfile_content = "{{libs}} {{solibs}} {{inputs_newline}} {{ldflags}}" + + restat = true + } + + tool("link") { + binary_output = + "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" + rspfile = "$binary_output.rsp" + pdbfile = "$binary_output.pdb" + + link_command = "$python_path $tool_wrapper_path link-wrapper $env False $link /nologo /OUT:$binary_output /PDB:$pdbfile @$rspfile" + + # TODO(brettw) support manifests + #manifest_command = "$python_path $tool_wrapper_path manifest-wrapper $env mt.exe -nologo -manifest $manifests -out:{{output}}.manifest" + #command = "cmd /c $link_command && $manifest_command" + command = link_command + + default_output_extension = ".exe" + description = "LINK $binary_output" + outputs = [ + binary_output, + "{{root_out_dir}}/{{target_output_name}}.lib", + pdbfile, + ] + + # The use of inputs_newline is to work around a fixed per-line buffer + # size in the linker. + rspfile_content = "{{inputs_newline}} {{libs}} {{solibs}} {{ldflags}}" + + restat = true + } + + tool("stamp") { + command = "cmd /c type nul > \"{{output}}\"" + description = "STAMP {{output}}" + } + + tool("copy") { + command = "$python_path $tool_wrapper_path recursive-mirror {{source}} {{output}}" + description = "COPY {{source}} {{output}}" + } + } +} diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index b29afaf07d0..6636597211f 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -335,10 +335,7 @@ shared_library("dart_jit_library") { ldflags = [ "-Wl,-install_name,@rpath/Dart.framework/Dart" ] public = [ "include/dart_api.h" ] deps = [ ":libdart_jit" ] - public_configs = [ - ":dart_public_config", - ":dart_shared_lib", - ] + public_configs = [ ":dart_public_config" ] } action("generate_version_cc_file") { diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn index 44da6b99ef4..90dc09a0c02 100644 --- a/runtime/bin/BUILD.gn +++ b/runtime/bin/BUILD.gn @@ -1141,20 +1141,12 @@ shared_library("entrypoints_verification_test") { deps = [ ":dart" ] sources = [ "entrypoints_verification_test.cc" ] include_dirs = [ ".." ] - defines = [ - # The only effect of DART_SHARED_LIB is to export the Dart API. - "DART_SHARED_LIB", - ] } shared_library("ffi_test_dynamic_library") { deps = [ ":dart" ] sources = [ "ffi_test/ffi_test_dynamic_library.cc" ] include_dirs = [ ".." ] - defines = [ - # The only effect of DART_SHARED_LIB is to export the Dart API. - "DART_SHARED_LIB", - ] } shared_library("ffi_test_functions") { @@ -1180,10 +1172,7 @@ shared_library("ffi_test_functions") { sources += [ "ffi_test/clobber_$current_cpu.S" ] } include_dirs = [ ".." ] - defines = [ - # The only effect of DART_SHARED_LIB is to export the Dart API. - "DART_SHARED_LIB", - ] + if (is_win) { # TODO(dartbug.com/40579): This wrongly links in dart.exe on precompiled. libs = [ "dart.lib" ]