| # Copyright 2018 The Fuchsia 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/build_id.gni") |
| import("//build/config/clang/clang.gni") |
| import("//build/fidl/toolchain.gni") |
| import("//build/rust/config.gni") # for rust_config |
| import("//build/rust/toolchain.gni") |
| import("//build/sdk/sdk_atom.gni") |
| import("//build/testing/test_spec.gni") |
| |
| # Copies a binary or shared object file, linking to it in the .build-id |
| # directory if it is an ELF file. Strips fuchsia binaries and shared objects. |
| # |
| # Parameters |
| # |
| # sources |
| # Required: A single source file to copy. This is only a list for |
| # consistency with other target types. This file should NOT have been |
| # copied prior to this target, or we may waste space. |
| # |
| # outputs |
| # Required: A single destination to copy the file to. This is only a list |
| # for consistency with other target types. |
| # |
| # override_os: |
| # Optional: Override the OS that the file is assumed to be built for. By |
| # default, we use the current_os. |
| template("copy_with_build_id") { |
| forward_variables_from(invoker, |
| [ |
| "visibility", |
| "override_os", |
| ]) |
| |
| srcs = invoker.sources |
| outs = invoker.outputs |
| assert(srcs == [ srcs[0] ], "Must specify exactly one source") |
| assert(outs == [ outs[0] ], "Must specify exactly one output") |
| |
| os = current_os |
| if (defined(override_os)) { |
| os = override_os |
| } |
| group_deps = [] |
| |
| copy_target_name = "${target_name}_copy" |
| group_deps += [ ":${copy_target_name}" ] |
| |
| # TODO(TC-481): Right now we only strip and add to .build-id for |
| # Fuchsia. There are no direct blockers to this but extra decisions and |
| # care has to be taken to make sure that everything functions properly. |
| if (os == "fuchsia") { |
| action(copy_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| |
| # clang_prefix is a root_build_dir-relative path and `script =` expects a |
| # GN path. To avoid a path like "garnet/public/buildtools/..." we have to |
| # rebase the path like this. |
| script = rebase_path("${clang_prefix}/llvm-objcopy", "", root_build_dir) |
| sources = srcs |
| outputs = outs |
| args = [ |
| # TODO(tmandry): If we start producing .so's, |
| # we need to use --strip-all here for them. |
| "--strip-sections", |
| rebase_path(srcs[0]), |
| rebase_path(outs[0]), |
| ] |
| } |
| |
| build_id_target_name = "${target_name}_build_id" |
| group_deps += [ ":${build_id_target_name}" ] |
| build_id_entry(build_id_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| deps += [ ":${copy_target_name}" ] |
| debug = srcs[0] |
| stripped = outs[0] |
| } |
| } else { |
| copy(copy_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "testonly", |
| ]) |
| sources = srcs |
| outputs = outs |
| } |
| } |
| group(target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| public_deps = group_deps |
| } |
| } |
| |
| template("rustc_third_party_artifact") { |
| forward_variables_from(invoker, [ "visibility" ]) |
| |
| # Dummy build target to match the one in rustc_artifact |
| build_target_name = "${target_name}_build" |
| group(build_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| } |
| |
| # Dummy target to write target info |
| info_target_name = "${target_name}_info" |
| generated_file(info_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "crate_name", |
| "crate_type", |
| "package_name", |
| "testonly", |
| ]) |
| |
| outputs = [ |
| "${target_out_dir}/${info_target_name}.json", |
| ] |
| contents = { |
| crate_name = crate_name |
| crate_type = crate_type |
| package_name = package_name |
| third_party = true |
| } |
| output_conversion = "json" |
| } |
| |
| group(target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| public_deps = [ |
| ":${build_target_name}", |
| ":${info_target_name}", |
| ] |
| } |
| } |
| |
| # Defines a Rust artifact to be built directly with rustc (rather than using cargo) |
| # |
| # Only for internal use, supporting rustc_{binary,library,macro,staticlib,test}. |
| # |
| # The arguments are the same as for rustc_library and rustc_binary, with the exception |
| # of `type`, which must be one of bin/lib/staticlib/proc-macro. This is used to determine |
| # the kind of artifact that is produced by rustc. |
| # |
| template("rustc_artifact") { |
| forward_variables_from(invoker, [ "visibility" ]) |
| |
| assert(defined(invoker.type), |
| "Must specify an artifact type (bin/lib/staticlib/proc-macro)") |
| type = invoker.type |
| |
| # bin: executable binary application |
| # lib: intermediate artifact to be used in other Rust programs |
| # staticlib: a statically-linked system library, generally used for linking Rust into C |
| # proc-macro: a procedural macro (such as a custom-derive) |
| assert( |
| type == "bin" || type == "lib" || type == "staticlib" || |
| type == "proc-macro", |
| "Artifact type must be one of: \"bin\", \"lib\", \"staticlib\", or \"proc-macro\"") |
| if (type == "lib") { |
| # For now, lib == rlib, but this could change in future versions of rustc. |
| # If/when this changes, we will likely want to transition manually rather |
| # than being automatically changed as a result of a toolchain upgrade. |
| type = "rlib" |
| } |
| |
| if (defined(invoker.name)) { |
| package_name = invoker.name |
| } else { |
| package_name = target_name |
| } |
| |
| crate_name = string_replace(package_name, "-", "_") |
| |
| if (defined(invoker.version)) { |
| version = invoker.version |
| } else { |
| version = "0.1.0" |
| } |
| |
| assert(defined(invoker.edition), "Must specify an edition. Preferably 2018") |
| edition = invoker.edition |
| |
| group_deps = [] |
| |
| if (rust_override_opt != "") { |
| rust_opt_level = rust_override_opt |
| if (defined(invoker.force_opt)) { |
| not_needed(invoker, [ "force_opt" ]) |
| } |
| } else if (defined(invoker.force_opt)) { |
| rust_opt_level = invoker.force_opt |
| } else { |
| if (is_debug) { |
| rust_opt_level = "0" |
| } else { |
| rust_opt_level = "z" |
| } |
| } |
| |
| if (type == "bin") { |
| if (rust_override_lto != "") { |
| with_lto = rust_override_lto |
| if (defined(invoker.with_lto)) { |
| not_needed(invoker, [ "with_lto" ]) |
| } |
| } else if (defined(invoker.with_lto)) { |
| with_lto = invoker.with_lto |
| } else if (rust_lto != "") { |
| with_lto = rust_lto |
| } else if (is_debug) { |
| with_lto = "none" |
| } else { |
| # Release builds default to "thin" lto |
| with_lto = "thin" |
| } |
| } else { |
| with_lto = "none" |
| } |
| assert(with_lto == "none" || with_lto == "thin" || with_lto == "fat", |
| "with_lto was neither none, thin, or fat") |
| |
| # Determine the prefix and extension for the output file based on the crate type |
| if (type == "bin") { |
| prefix = "" |
| extension = "" |
| root_file = "src/main.rs" |
| } else if (type == "rlib") { |
| prefix = "lib" |
| extension = ".rlib" |
| root_file = "src/lib.rs" |
| } else if (type == "staticlib") { |
| prefix = "staticlib" |
| extension = ".a" |
| root_file = "src/lib.rs" |
| } else if (type == "proc-macro") { |
| prefix = "lib" |
| root_file = "src/lib.rs" |
| } |
| |
| only_unit_tests = defined(invoker.only_unit_tests) && invoker.only_unit_tests |
| |
| third_party_build = "//third_party/rust_crates:build-third-party" |
| third_party_deps_data = |
| "${root_out_dir}/rust_third_party_crates/deps_data.json" |
| first_party_crate_root = "${root_out_dir}/rust_crates" |
| third_party_crate_root = "${root_out_dir}/rust_third_party_crates" |
| unstripped_output_dir = "${root_out_dir}/exe.unstripped" |
| not_needed([ "unstripped_output_dir" ]) |
| if (defined(invoker.output_file_override)) { |
| output_filename = invoker.output_file_override |
| } else { |
| output_filename = "${prefix}${crate_name}${extension}" |
| } |
| if (type == "bin") { |
| output_dir = unstripped_output_dir |
| } else if (type == "staticlib") { |
| output_dir = root_out_dir |
| } else { |
| output_dir = first_party_crate_root |
| } |
| output_file = "${output_dir}/$output_filename" |
| if (!only_unit_tests) { |
| if (type == "bin" && !only_unit_tests) { |
| output_path = "${root_out_dir}/${output_filename}" |
| } |
| output_depfile = "${output_dir}/${prefix}${crate_name}.d" |
| |
| build_target_name = "${target_name}_build" |
| group_deps += [ ":${build_target_name}" ] |
| } |
| |
| with_unit_tests = only_unit_tests || (defined(invoker.with_unit_tests) && |
| invoker.with_unit_tests) |
| if (with_unit_tests) { |
| if (only_unit_tests) { |
| test_filename = crate_name |
| } else { |
| test_filename = "${crate_name}_${invoker.type}_test" |
| } |
| test_output_file = "${unstripped_output_dir}/${test_filename}" |
| test_output_path = "${root_out_dir}/${test_filename}" |
| test_depfile = "${test_output_file}.d" |
| |
| build_test_target_name = "${target_name}_test_build" |
| test_group_deps = [ ":${build_test_target_name}" ] |
| } |
| |
| # Test specs are used for linux and mac tests to record metadata for testing |
| # instruction; this happens within package.gni for fuchsia tests. |
| test_spec_target_name = "${target_name}_spec" |
| if (with_unit_tests && (is_linux || is_mac)) { |
| test_spec(test_spec_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| name = invoker.target_name |
| install_path = test_output_path |
| deps = [] |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| if (defined(invoker.non_rust_deps)) { |
| deps += invoker.non_rust_deps |
| } |
| if (defined(invoker.test_environments)) { |
| environments = invoker.test_environments |
| } |
| } |
| } else { |
| not_needed([ "test_spec_target_name" ]) |
| if (defined(invoker.test_environments)) { |
| assert(with_unit_tests, |
| "test_environments may only be set when with_unit_tests is true") |
| not_needed(invoker, [ "test_environments" ]) |
| } |
| } |
| |
| # Iterate through the deps collecting a list of the outputs |
| # of their build targets, which will be passed to rustc as |
| # `--extern` crates. |
| # Note: keep this code in sync with "Iterate through..." below. |
| dep_info_paths = [] |
| dep_info_sources = [] |
| if (defined(invoker.deps)) { |
| foreach(dep, invoker.deps) { |
| dep_target_name = get_label_info(dep, "name") |
| dep_dir = get_label_info(dep, "dir") |
| dep_build_target = "${dep_dir}:${dep_target_name}_build" |
| dep_out_dir = get_label_info(dep_build_target, "target_out_dir") |
| dep_info_path = "${dep_out_dir}/${dep_target_name}_info.json" |
| dep_info_paths += [ |
| "--dep-data", |
| rebase_path(dep_info_path), |
| ] |
| dep_info_sources += [ rebase_path(dep_info_path) ] |
| } |
| } |
| |
| if (defined(invoker.source_root)) { |
| root_file = invoker.source_root |
| } |
| root_file = rebase_path(root_file) |
| |
| cargo_toml_dir = "$target_gen_dir/$target_name" |
| |
| # Collect the lib_dirs we should be getting from //zircon/public/lib deps. |
| zircon_lib_dirs_file = "$target_gen_dir/${target_name}_build_zircon_libs" |
| extra_args = [ |
| "--lib-dir-file", |
| rebase_path(zircon_lib_dirs_file), |
| ] |
| extra_deps = [ ":${target_name}_build_zircon_libs" ] |
| extra_inputs = [ zircon_lib_dirs_file ] |
| generated_file("${target_name}_build_zircon_libs") { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| # Clear possibly inherited visibility before setting our own. |
| visibility = [] |
| if (!only_unit_tests) { |
| visibility += [ ":$build_target_name" ] |
| } |
| if (with_unit_tests) { |
| visibility += [ ":$build_test_target_name" ] |
| } |
| deps = [ |
| third_party_build, |
| ] |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| if (defined(invoker.non_rust_deps)) { |
| deps += invoker.non_rust_deps |
| } |
| outputs = [ |
| zircon_lib_dirs_file, |
| ] |
| data_keys = [ "zircon_lib_dirs" ] |
| output_conversion = "list lines" |
| } |
| |
| # Declare the action targets that perform the build itself |
| rustc_target_script = "//build/rust/build_rustc_target.py" |
| rustc_target_pool = "//build/rust:pool($default_toolchain)" |
| |
| rustc_target_deps = [] |
| if (defined(invoker.deps)) { |
| rustc_target_deps += invoker.deps |
| } |
| rustc_target_deps += [ third_party_build ] |
| rustc_target_inputs = [ root_file ] |
| |
| rustc_target_public_deps = [] |
| if (defined(invoker.non_rust_deps)) { |
| rustc_target_public_deps += invoker.non_rust_deps |
| } |
| |
| # The set of unstable features permitted as per |
| # https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/docs/development/languages/rust/unstable.md |
| unstable_rust_features = [] |
| |
| # Specifically enable specialization for use in netstack3. |
| # This flag is not allowed to be introduced in new code. |
| if (defined(invoker.__unstable_netstack3_only_specialization_bypass)) { |
| unstable_rust_features += |
| invoker.__unstable_netstack3_only_specialization_bypass |
| } |
| |
| # Make builds independent of absolute file path. The file names |
| # embedded in debugging information will be expressed as relative to |
| # the build directory, e.g. "../.." for an "out/subdir" under //. |
| absolute_path = rebase_path("//.") |
| relative_path = rebase_path("//.", root_build_dir) |
| |
| rustc_target_args = [ |
| "--crate-root", |
| rebase_path(root_file), |
| "--crate-type", |
| type, |
| "--crate-name", |
| crate_name, |
| "--root-out-dir", |
| rebase_path(root_out_dir), |
| "--first-party-crate-root", |
| rebase_path(first_party_crate_root), |
| "--third-party-crate-root", |
| rebase_path(third_party_crate_root), |
| "--edition", |
| edition, |
| "--cap-lints", |
| rust_cap_lints, |
| "--remap-path-prefix", |
| "$absolute_path=$relative_path", |
| "--opt-level", |
| rust_opt_level, |
| ] |
| |
| if (host_os == "mac") { |
| rustc_target_args += [ "--mac-host" ] |
| } |
| |
| if (defined(invoker.features)) { |
| foreach(feature, invoker.features) { |
| rustc_target_args += [ |
| "--feature", |
| feature, |
| ] |
| } |
| } |
| |
| foreach(unstable_rust_feature, unstable_rust_features) { |
| rustc_target_args += [ |
| "--unstable-rust-feature", |
| unstable_rust_feature, |
| ] |
| } |
| |
| rustc_target_args += rust_build_args + extra_args |
| rustc_target_deps += rust_build_deps + extra_deps |
| rustc_target_inputs += rust_build_inputs + extra_inputs |
| |
| if (with_lto != "none") { |
| rustc_target_args += [ |
| "--lto", |
| with_lto, |
| ] |
| } |
| |
| if (defined(invoker.non_rust_deps)) { |
| foreach(dep, invoker.non_rust_deps) { |
| rustc_target_args += [ |
| "--lib-dir", |
| rebase_path(get_label_info(dep, "target_out_dir")), |
| ] |
| } |
| } |
| |
| rustc_target_args += dep_info_paths |
| |
| info_target_name = "${target_name}_info" |
| generated_file(info_target_name) { |
| # Write out static information about the target to be used by |
| # reverse-dependencies to determine the content of their Cargo.toml |
| # files and --extern invocations. |
| outputs = [ |
| "${target_out_dir}/${target_name}.json", |
| ] |
| contents = { |
| cargo_toml_dir = rebase_path(cargo_toml_dir) |
| crate_name = crate_name |
| lib_path = rebase_path(output_file) |
| package_name = package_name |
| third_party = false |
| version = version |
| } |
| output_conversion = "json" |
| } |
| group_deps += [ ":${info_target_name}" ] |
| |
| if (!only_unit_tests) { |
| action(build_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| script = rustc_target_script |
| pool = rustc_target_pool |
| |
| args = rustc_target_args |
| args += [ |
| "--output-file", |
| rebase_path(output_file), |
| "--depfile", |
| rebase_path(output_depfile), |
| ] |
| |
| inputs = rustc_target_inputs |
| outputs = [ |
| output_file, |
| ] |
| |
| depfile = output_depfile |
| deps = rustc_target_deps |
| public_deps = rustc_target_public_deps |
| |
| if (type == "bin") { |
| metadata = { |
| binaries = [ |
| { |
| type = "executable" |
| label = |
| get_label_info(":$build_target_name", "label_with_toolchain") |
| cpu = current_cpu |
| os = current_os |
| debug = rebase_path(output_file, root_build_dir) |
| dist = rebase_path(output_path, root_build_dir) |
| if (current_os != "mac" && current_os != "win") { |
| elf_build_id = |
| rebase_path("$output_path.build-id.stamp", root_build_dir) |
| } |
| }, |
| ] |
| if (is_host) { |
| tool_paths = [ |
| { |
| cpu = current_cpu |
| label = get_label_info(":$build_target_name", |
| "label_with_toolchain") |
| name = output_filename |
| os = current_os |
| path = rebase_path(output_path, root_build_dir) |
| }, |
| ] |
| } |
| } |
| } |
| } |
| } |
| |
| test_dep_info_paths = [] |
| if (with_unit_tests) { |
| test_deps = [] |
| test_dep_args = [] |
| |
| # Note: keep this code in sync with "Iterate through..." above. |
| # Iterate through test-only dependencies and add them to flags and deps. |
| if (defined(invoker.test_deps)) { |
| test_deps = invoker.test_deps |
| foreach(dep, invoker.test_deps) { |
| dep_target_name = get_label_info(dep, "name") |
| dep_dir = get_label_info(dep, "dir") |
| dep_build_target = "${dep_dir}:${dep_target_name}_build" |
| dep_out_dir = get_label_info(dep_build_target, "target_out_dir") |
| dep_info_path = "${dep_out_dir}/${dep_target_name}_info.json" |
| test_dep_args += [ |
| "--dep-data", |
| rebase_path(dep_info_path), |
| ] |
| test_dep_info_paths += [ |
| "--test-only-dep-data", |
| rebase_path(dep_info_path), |
| ] |
| dep_info_sources += [ rebase_path(dep_info_path) ] |
| } |
| } |
| |
| action(build_test_target_name) { |
| script = rustc_target_script |
| pool = rustc_target_pool |
| |
| args = rustc_target_args + test_dep_args |
| args += [ |
| "--test", |
| "--output-file", |
| rebase_path(test_output_file), |
| "--depfile", |
| rebase_path(test_depfile), |
| ] |
| |
| inputs = rustc_target_inputs |
| outputs = [ |
| test_output_file, |
| ] |
| |
| testonly = true |
| depfile = test_depfile |
| deps = rustc_target_deps + test_deps |
| if (is_linux || is_mac) { |
| deps += [ ":$test_spec_target_name" ] |
| } |
| if (defined(invoker.test_deps)) { |
| deps += invoker.test_deps |
| } |
| public_deps = rustc_target_public_deps |
| |
| metadata = { |
| binaries = [ |
| { |
| type = "executable" |
| label = get_label_info(":$build_test_target_name", |
| "label_with_toolchain") |
| cpu = current_cpu |
| os = current_os |
| debug = rebase_path(test_output_file, root_build_dir) |
| dist = rebase_path(test_output_path, root_build_dir) |
| if (current_os != "mac" && current_os != "win") { |
| elf_build_id = rebase_path("$test_output_path.build-id.stamp", |
| root_build_dir) |
| } |
| }, |
| ] |
| } |
| } |
| } |
| |
| if (type == "bin" && !only_unit_tests) { |
| # strip staticlibs and binaries from "exe.unstripped" and put the results |
| # in the root_out_dir |
| strip_target_name = "${target_name}_strip" |
| group_deps += [ ":${strip_target_name}" ] |
| copy_with_build_id(strip_target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| deps = [ |
| ":${build_target_name}", |
| ] |
| sources = [ |
| output_file, |
| ] |
| outputs = [ |
| output_path, |
| ] |
| } |
| |
| # if appropriate, create an SDK atom for the binary that we just stripped |
| if (defined(invoker.sdk_category) && invoker.sdk_category != "excluded" && |
| !is_fuchsia && !(defined(invoker.test) && invoker.test)) { |
| output_name = target_name |
| file_base = "tools/$output_name" |
| |
| sdk_atom("${target_name}_sdk") { |
| id = "sdk://tools/${output_name}" |
| |
| category = invoker.sdk_category |
| |
| meta = { |
| dest = "${file_base}-meta.json" |
| schema = "host_tool" |
| value = { |
| type = "host_tool" |
| name = output_name |
| root = "tools" |
| files = [ file_base ] |
| } |
| } |
| |
| files = [ |
| { |
| source = output_path |
| dest = file_base |
| }, |
| ] |
| |
| if (defined(invoker.sdk_deps)) { |
| deps = invoker.sdk_deps |
| } |
| |
| non_sdk_deps = [ ":$strip_target_name" ] |
| } |
| } |
| } |
| |
| if (with_unit_tests) { |
| strip_test_target_name = "${target_name}_test_strip" |
| test_group_deps += [ ":${strip_test_target_name}" ] |
| |
| copy_with_build_id(strip_test_target_name) { |
| testonly = true |
| deps = [ |
| ":${build_test_target_name}", |
| ] |
| sources = [ |
| test_output_file, |
| ] |
| outputs = [ |
| test_output_path, |
| ] |
| } |
| } |
| |
| # proc macros are stripped and copied inside `rustc_macro.gni`. |
| |
| cargo_toml_target_name = "${target_name}_cargo" |
| group_deps += [ ":${cargo_toml_target_name}" ] |
| action(cargo_toml_target_name) { |
| script = "//build/rust/write_cargo_toml.py" |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| deps = [ |
| third_party_build, |
| ] |
| if (defined(invoker.deps)) { |
| foreach(dep, invoker.deps) { |
| dep_info_name = get_label_info(dep, "label_no_toolchain") + "_info" |
| dep_info_name += "(" + get_label_info(dep, "toolchain") + ")" |
| deps += [ dep_info_name ] |
| } |
| } |
| if (defined(invoker.test_deps)) { |
| foreach(test_dep, invoker.test_deps) { |
| dep_info_name = get_label_info(test_dep, "label_no_toolchain") + "_info" |
| dep_info_name += "(" + get_label_info(test_dep, "toolchain") + ")" |
| deps += [ dep_info_name ] |
| } |
| } |
| |
| args = [ |
| "--out-dir", |
| rebase_path(cargo_toml_dir), |
| "--source-root", |
| root_file, |
| "--package-name", |
| package_name, |
| "--crate-name", |
| crate_name, |
| "--crate-type", |
| type, |
| "--version", |
| version, |
| "--edition", |
| edition, |
| "--third-party-deps-data", |
| rebase_path(third_party_deps_data), |
| ] |
| |
| if (defined(invoker.features)) { |
| foreach(feature, invoker.features) { |
| args += [ |
| "--feature", |
| feature, |
| ] |
| } |
| } |
| |
| if (with_lto != "none") { |
| args += [ |
| "--lto", |
| with_lto, |
| ] |
| } |
| |
| # list of paths to info about crate dependencies |
| args += dep_info_paths |
| args += test_dep_info_paths |
| sources = dep_info_sources |
| outputs = [ |
| "${cargo_toml_dir}/Cargo.toml", |
| ] |
| } |
| |
| if (with_unit_tests) { |
| test_target_name = "${target_name}_test" |
| group(test_target_name) { |
| testonly = true |
| public_deps = test_group_deps |
| } |
| |
| if (only_unit_tests) { |
| group_deps += [ ":${test_target_name}" ] |
| } |
| } |
| |
| group(target_name) { |
| forward_variables_from(invoker, [ "testonly" ]) |
| public_deps = group_deps |
| } |
| } |