| # 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/idk_subbuilds.gni") |
| import("//build/toolchain/rbe.gni") |
| import("//sdk/config.gni") |
| |
| # Generate an IDK directory, which combines outputs from different arch- and API |
| # level-specific sub-builds into a single one. The generated directory will |
| # include prebuilts for all the given `target_cpus` and `api_levels` plus |
| # "PLATFORM". On a host Linux machine, the generated archive will have host |
| # tools for both Linux/x64 and Linux/arm64 if `sdk_cross_compile_host_tools` is |
| # true. |
| # |
| # It is recommended to use `idk_subbuilds_label_prefix` in order to |
| # be able to share the sub-builds for the same collection with other idk() |
| # instances. |
| # |
| # 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 strings, for which to include prebuilts, in |
| # addition to the current (PLATFORM) one. |
| # |
| # sdk_collection_label: (required) |
| # A single label for an sdk_collection() GN target. |
| # |
| # idk_subbuilds_label_prefix: (optional) |
| # The common GN label prefix shared by targets generated by an |
| # `idk_subbuilds()` instance. This should match the full label of the |
| # `idk_subbuilds()` target. The `sdk_collection_name` of the sub-builds |
| # must match the name of the `sdk_collection_label`. The available |
| # sub-builds must at least include all combinations of `target_cpus` x |
| # (`api_levels` plus "PLATFORM"). That is, the `target_cpus` and |
| # `api_levels` parameters passed to `idk_subbuilds()` must at least include |
| # the values used here. |
| # |
| # If provided, these sub-builds will be used. |
| # |
| # Otherwise, this template will generate an implicit idk_subbuilds() set |
| # of targets, but doing so will prevent sharing the sub-build directories |
| # between different idk() instances that build the same collection for |
| # different sets of target_cpu / api_level combinations. |
| # |
| # idk_subbuilds_dir_prefix: (optional) |
| # A build directory prefix. Only used when `idk_subbuilds_label_prefix` is provided. |
| # If provided, this must match the `subbuild_prefix` argument used to define |
| # the idk_subbuilds_target. |
| # |
| # 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") |
| assert(defined(invoker.idk_subbuilds_label_prefix) || |
| !defined(invoker.idk_subbuilds_dir_prefix)) |
| |
| # 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 ($current_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") |
| |
| if (defined(invoker.idk_subbuilds_label_prefix)) { |
| _subbuilds_target_prefix = invoker.idk_subbuilds_label_prefix |
| if (defined(invoker.idk_subbuilds_dir_prefix)) { |
| _subbuilds_dir_prefix = invoker.idk_subbuilds_dir_prefix |
| } else { |
| # Same default as idk_subbuilds() |
| _subbuilds_dir_prefix = "idk_subbuild.${_sdk_collection_name}" |
| } |
| } else { |
| # Generate actions for all possible sub-builds. |
| # Only the ones matching invoker.api_levels and invoker.target_cpus will be used though. |
| _subbuilds_target = "idk_subbuild_${target_name}" |
| _subbuilds_dir_prefix = "idk_subbuild.${target_name}" |
| |
| idk_subbuilds(_subbuilds_target) { |
| sdk_collection_label = invoker.sdk_collection_label |
| subbuild_prefix = _subbuilds_dir_prefix |
| api_levels = invoker.api_levels |
| target_cpus = invoker.target_cpus |
| forward_variables_from(invoker, |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| } |
| |
| _subbuilds_target_prefix = ":${_subbuilds_target}" |
| } |
| |
| _collection_relative_path = "sdk/exported/${_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) { |
| # There is no subbuild for the current CPU - just use the |
| # `sdk_collection` in the current build. |
| _subbuild_targets += [ invoker.sdk_collection_label ] |
| _subbuild_dirs += [ root_build_dir ] |
| } else { |
| _subbuild_targets += [ "${_subbuilds_target_prefix}-${target_cpu}" ] |
| _subbuild_dirs += |
| [ "${root_build_dir}/${_subbuilds_dir_prefix}-${target_cpu}" ] |
| } |
| } |
| |
| # Now do them for individual API levels. |
| foreach(api_level, invoker.api_levels) { |
| foreach(target_cpu, _target_cpus) { |
| _subbuild_targets += |
| [ "${_subbuilds_target_prefix}-api${api_level}-${target_cpu}" ] |
| _subbuild_dirs += [ "${root_build_dir}/${_subbuilds_dir_prefix}-api${api_level}-${target_cpu}" ] |
| } |
| } |
| |
| if (target_cpu == current_cpu && invoker.api_levels == []) { |
| not_needed([ |
| "_subbuilds_dir_prefix", |
| "_subbuilds_target_prefix", |
| ]) |
| } |
| |
| 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_vendor_os = "unknown-linux-gnu" |
| } else if (host_os == "fuchsia") { |
| host_triple_vendor_os = "unknown-fuchsia" |
| } else { |
| assert(false, "Unrecognized host OS: ${host_os}") |
| } |
| host_triple = "${host_triple_cpu}-${host_triple_vendor_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" |
| |
| _schema_validator_tool = "//build/bazel/host:bazel_root_host_tools.json_validator_valico($host_toolchain)" |
| |
| # Get the path to the schema validator executable. |
| host_executable = "${host_out_dir}/json_validator_valico" |
| |
| inputs = [ host_executable ] |
| |
| deps = _subbuild_targets + [ _schema_validator_tool ] |
| 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 += [ |
| "--collection-relative-path", |
| _collection_relative_path, |
| "--output-directory", |
| rebase_path(_exported_dir, root_build_dir), |
| "--schema-directory", |
| rebase_path("//build/sdk/meta", root_build_dir), |
| "--json-validator-path", |
| rebase_path(host_executable, 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, |
| [ |
| "assert_no_deps", |
| "testonly", |
| "visibility", |
| ]) |
| } |
| } |