| # Copyright 2023 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/config/compiler.gni") |
| import("//build/python/python_action.gni") |
| import("//build/sdk/config.gni") |
| import("//build/toolchain/rbe.gni") |
| import("//sdk/config.gni") |
| |
| # Create a GN directory, and build an `sdk_collection` target for a particular |
| # target_cpu and api_level by calling `gn gen` and then `ninja` in that |
| # directory. |
| template("_subbuild") { |
| assert(defined(invoker.sdk_collection)) |
| assert(defined(invoker.target_cpu)) |
| assert(defined(invoker.api_level)) |
| assert(defined(invoker.extra_deps)) |
| |
| _build_dir = root_build_dir + "/build-${target_name}" |
| _build_dir_stamp = _build_dir + ".stamp" |
| |
| _sdk_collection_dir = get_label_info(invoker.sdk_collection, "dir") |
| _sdk_collection_name = get_label_info(invoker.sdk_collection, "name") |
| _sdk_collection = "${_sdk_collection_dir}:${_sdk_collection_name}" |
| |
| _collection_dir = _build_dir + "/sdk/exported/${_sdk_collection_name}" |
| _collection_dir_manifest = "${_collection_dir}/meta/manifest.json" |
| |
| action(target_name) { |
| script = "//build/sdk/subbuild.py" |
| outputs = [ |
| _build_dir_stamp, |
| _collection_dir_manifest, |
| ] |
| |
| # //sdk:idk_build_tools contains the host tools that must be used in the |
| # subbuilds. Make sure those (and any extra deps) are built first. |
| deps = [ "//sdk:idk_build_tools" ] + invoker.extra_deps |
| |
| args = [ |
| "--stamp-file", |
| rebase_path(_build_dir_stamp, root_build_dir), |
| "--sdk-id", |
| sdk_id, |
| "--output-build-dir", |
| rebase_path(_build_dir, root_build_dir), |
| |
| "--sdk-collection-label", |
| _sdk_collection, |
| "--target-cpu", |
| invoker.target_cpu, |
| "--api-level", |
| invoker.api_level, |
| |
| "--fuchsia-dir", |
| rebase_path("//", root_build_dir), |
| "--prebuilt-host-tools-dir", |
| rebase_path("$root_build_dir/sdk/idk_build_tools", _build_dir), |
| "--compress-debuginfo", |
| compress_debuginfo, |
| ] |
| |
| if (sdk_sub_build_parallelism != "") { |
| args += [ |
| "--parallelism", |
| "${sdk_sub_build_parallelism}", |
| ] |
| } |
| if (sdk_sub_build_max_load_average != "") { |
| args += [ |
| "--max-load-average", |
| "${sdk_sub_build_max_load_average}", |
| ] |
| } |
| if (sdk_sub_build_verbose) { |
| args += [ "--verbose" ] |
| } |
| |
| if (cxx_rbe_enable) { |
| args += [ "--cxx-rbe-enable" ] |
| } |
| if (rust_rbe_enable) { |
| args += [ "--rust-rbe-enable" ] |
| } |
| |
| pool = "//sdk:subbuild_pool" |
| |
| # This script cannot be hermetic. |
| hermetic_deps = false |
| |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| } |
| } |
| |
| # Generate a IDK directory, which combines outputs from different arch-specific |
| # sub-builds into a single one. The generated directory will include prebuilts |
| # for all the given `target_cpus`. On a host Linux machine, the generated |
| # archive will have host tools for both Linux/x64 and Linux/arm64. |
| # |
| # The generated directory will go into |
| # $root_build_dir/sdk/exported/{output_name} |
| # |
| # Arguments: |
| # target_cpus: (required) |
| # List of target cpu names. This must include the default target_cpu |
| # value for the current build configuration. |
| # |
| # api_levels: (required) |
| # List of API levels, as integers, to build prebuilts for, in addition to |
| # the current (HEAD) one. |
| # |
| # sdk_collection_label: (required) |
| # A single label for an sdk_collection() GN target that will be built |
| # multiple times and merged into the final directory. |
| # |
| # output_name: (optional) |
| # Name of the directory. Default is target_name |
| # |
| # testonly, visibility |
| # Usual GN meaning. |
| # |
| template("idk") { |
| assert(defined(invoker.target_cpus), |
| "target_cpus must be defined for $target_name") |
| assert(defined(invoker.api_levels), |
| "api_levels must be defined for $target_name") |
| assert(defined(invoker.sdk_collection_label), |
| "sdk_collection_label must be defined for $target_name") |
| |
| # Default output name. |
| _output_name = target_name |
| if (defined(invoker.output_name)) { |
| _output_name = invoker.output_name |
| } |
| |
| _non_current_cpus = invoker.target_cpus + [ current_cpu ] - [ current_cpu ] |
| |
| assert( |
| invoker.target_cpus != _non_current_cpus, |
| "The target_cpus argument must include the current target_cpu ($target_cpu): ${invoker.target_cpus}") |
| |
| # Do the current CPU first. This may not be necessary, but it's what the old |
| # script did and I want a null-diff. |
| _target_cpus = [ current_cpu ] + _non_current_cpus |
| |
| _exported_dir = root_build_dir + "/sdk/exported/${_output_name}" |
| _exported_dir_manifest = "${_exported_dir}/meta/manifest.json" |
| _exported_dir_stamp = _exported_dir + ".stamp" |
| |
| _sdk_collection_name = get_label_info(invoker.sdk_collection_label, "name") |
| _relative_collection_build_manifest = "sdk/manifest/${_sdk_collection_name}" |
| |
| # Targets that must be built before producing the final IDK. |
| _subbuild_targets = [] |
| |
| # Build directories for each subbuilds that contribute to the IDK, including |
| # the main build. Note that the contents of the IDK are sensitive to the order |
| # of this list. |
| _subbuild_dirs = [] |
| |
| # First, do subbuilds for the default API level. |
| foreach(target_cpu, _target_cpus) { |
| if (target_cpu == current_cpu) { |
| # Don't do a subbuild for the current CPU - just depend on the |
| # `sdk_collection` in the current build. |
| _subbuild_targets += [ invoker.sdk_collection_label ] |
| _subbuild_dirs += [ root_build_dir ] |
| } else { |
| _subbuild_name = "${target_name}.subbuild-${target_cpu}" |
| |
| _subbuild(_subbuild_name) { |
| sdk_collection = invoker.sdk_collection_label |
| target_cpu = target_cpu |
| api_level = "PLATFORM" |
| |
| # Each subbuild depends on the `sdk_collection` in the main build, so |
| # that when a change happens that would cause the `sdk_collection` to be |
| # rebuilt, that also triggers the subbuilds to be rerun. |
| extra_deps = [ invoker.sdk_collection_label ] |
| |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| } |
| _subbuild_targets += [ ":$_subbuild_name" ] |
| _subbuild_dirs += [ "${root_build_dir}/build-${_subbuild_name}" ] |
| } |
| } |
| |
| # Now do them for individual API levels. |
| foreach(api_level, invoker.api_levels) { |
| foreach(target_cpu, _target_cpus) { |
| _subbuild_name = "${target_name}.subbuild-api${api_level}-${target_cpu}" |
| |
| _subbuild(_subbuild_name) { |
| sdk_collection = invoker.sdk_collection_label |
| target_cpu = target_cpu |
| api_level = "$api_level" |
| |
| # Each subbuild depends on the `sdk_collection` in the main build, so |
| # that when a change happens that would cause the `sdk_collection` to be |
| # rebuilt, that also triggers the subbuilds to be rerun. |
| extra_deps = [ invoker.sdk_collection_label ] |
| |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| } |
| |
| _subbuild_targets += [ ":$_subbuild_name" ] |
| _subbuild_dirs += [ "${root_build_dir}/build-${_subbuild_name}" ] |
| } |
| } |
| |
| if (host_cpu == "x64") { |
| host_triple_cpu = "x86_64" |
| } else if (host_cpu == "arm64") { |
| host_triple_cpu = "aarch64" |
| } else { |
| assert(false, "Unrecognized host CPU: $host_cpu") |
| } |
| if (host_os == "linux") { |
| host_triple_os = "linux-gnu" |
| } else if (host_os == "mac") { |
| host_triple_os = "apple-darwin" |
| } else if (host_os == "fuchsia") { |
| host_triple_os = "fuchsia" |
| } else { |
| assert(false, "Unrecognized host OS: $host_os") |
| } |
| host_triple = "$host_triple_cpu-$host_triple_os" |
| |
| # Combine all the individual sdk_collection subbuilds and put the result in |
| # the exported directory. |
| python_action(target_name) { |
| binary_label = "//build/sdk/generate_idk" |
| |
| deps = _subbuild_targets |
| outputs = [ |
| _exported_dir_manifest, |
| _exported_dir_stamp, |
| ] |
| |
| # The exported dir is fully under our control and gets deleted by every |
| # invocation of this build rule. |
| hermetic_action_ignored_prefixes = [ _exported_dir ] |
| |
| depfile = "${target_gen_dir}/${target_name}.d" |
| |
| args = [] |
| |
| foreach(dir, _subbuild_dirs) { |
| args += [ |
| "--subbuild-directory", |
| rebase_path(dir, root_build_dir), |
| ] |
| } |
| args += [ |
| "--relative-manifest", |
| _relative_collection_build_manifest, |
| "--output-directory", |
| rebase_path(_exported_dir, root_build_dir), |
| "--stamp-file", |
| rebase_path(_exported_dir_stamp, root_build_dir), |
| "--depfile", |
| rebase_path(depfile, root_build_dir), |
| "--host-arch", |
| host_triple, |
| "--release-version", |
| sdk_id, |
| ] |
| |
| foreach(cpu, invoker.target_cpus) { |
| args += [ |
| "--target-arch", |
| cpu, |
| ] |
| } |
| |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| } |
| } |