blob: cf6b465b143c1c6e0cbc4bdee571c290e2f98cd0 [file] [log] [blame]
# Copyright 2025 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.
assert(current_toolchain == default_toolchain)
import("//build/config/fuchsia/target_api_level.gni")
import("//build/sdk/idk_subbuilds.gni")
import("//build/sdk/sdk_collection.gni")
# Template defining the targets used to build the IDK.
# When the target name is "fuchsia", all atoms will be built. Otherwise,
# the subset needed for in-tree uses of the IDK will be built.
template("generate_idk_targets") {
assert(defined(invoker.atoms_independent_of_api_level_and_cpu_arch))
assert(defined(invoker.atoms_to_include_in_deprecated_arch_directory))
assert(defined(invoker.dart_library))
assert(defined(invoker.docs))
assert(defined(invoker.docs_dependent_on_fidl))
assert(defined(invoker.fidl_libraries))
assert(defined(invoker.host_tests))
assert(defined(invoker.host_tools))
assert(defined(invoker.non_sdk_deps_build_tests_for_all_builds))
assert(defined(invoker.packages))
assert(defined(invoker.prebuilt_libraries))
assert(defined(invoker.source_libraries))
assert(defined(invoker.sysroot))
assert(defined(invoker.vulkan_layers))
main_target_name = "${target_name}_collection"
# The collection that is built by sub-builds. The IDK uses sub-builds
# for each CPU architecture at all supported API levels and at "PLATFORM"
# for CPU architectures other than the target CPU.
# This target will also be built in the main build at "PLATFORM" for the
# target CPU because the sub-build rule depends on it as a way to trigger
# sub-builds to rebuild when needed.
sdk_collection("${main_target_name}_for_subbuilds") {
visibility = []
visibility = [
":*", # Required for "${main_target_name}_idk_subbuilds-api*".
"//:build_only", # Used to specify the target of the sub-builds.
]
category = "partner"
id = sdk_id
# Use the name of the main collection in paths as required to merge the
# sub-builds.
name = main_target_name
if (!sdk_inside_sub_build) {
# The main build builds the `main_target_name` collection and, as
# described above, this sub-build collection. Since some output files are
# based on the collection name rather than the target name, some paths
# could collide. To avoid this, add a suffix. This is acceptable because
# the output from that instance of this target is not actually used for
# anything.
name += "_for_subbuild_deps"
}
deps = [
# Don't add other sdk_molecules here. Add them to the molecule below.
":${main_target_name}.fuchsia_idk_atoms_produced_by_subbuilds",
]
}
# All atoms to be produced by the sub-builds for inclusion in the IDK.
#
# Due to limitations of the build system at the GN/Bazel boundary, this
# cannot contain testonly atoms. See https://fxbug.dev/42070088.
# Libraries and packages for use in tests absolutely belong in the IDK, but
# the `testonly` attribute must be removed before they can be added.
sdk_molecule("${main_target_name}.fuchsia_idk_atoms_produced_by_subbuilds") {
category = "partner"
# Atoms included in the IDK that are not for a specific API level.
if (current_build_target_api_level == "PLATFORM") {
deps = [ ":${main_target_name}.fuchsia_idk_atoms_built_only_at_platform_for_each_cpu_arch" ]
}
# Atoms included in the IDK for each API level.
if (current_build_target_api_level != "PLATFORM") {
deps = [ ":${main_target_name}.fuchsia_idk_atoms_for_each_api_level" ]
} else if (!sdk_inside_sub_build) {
# Add non-SDK deps in the case of the main build to ensure accurate
# dependency change checking for the sub-builds. See the comment for
# "${main_target_name}_for_subbuilds".
non_sdk_deps = [
# While atoms included in the IDK only at specific API levels should not
# be built or included at PLATFORM, the main build must have a deps.
":${main_target_name}.fuchsia_idk_atoms_for_each_api_level",
]
# Though the FIDL artifacts are not produced by sub-builds, changes to
# the FIDL files could affect sub-builds. Take a dependency here in the
# main build so that changes to FIDL files in the IDK will cause the
# sub-builds to be re-evaluated. This is relevant in cases where FIDL
# files are modified in ways that affect individual API levels but not
# the output when fidlc is targeting "PLATFORM".
non_sdk_deps += invoker.fidl_libraries
# For consistency, do not include those FIDL atoms in the prebuild data.
metadata = {
idk_atom_prebuild_info_barrier =
deps + (non_sdk_deps - invoker.fidl_libraries)
}
}
}
# Prebuilt libraries and packages that are built exclusively for the API
# levels that SDK users can target (not "PLATFORM").
# Note: This target can be built at "PLATFORM" as required by the sub-build
# infrastructure.
sdk_molecule("${main_target_name}.fuchsia_idk_atoms_for_each_api_level") {
category = "partner"
# This target should only be built at PLATFORM as part of sub-build deps.
visibility = []
visibility = [
# Dependencies related to template sub-targets.
":${main_target_name}.fuchsia_idk_atoms_for_each_api_level",
":${main_target_name}.fuchsia_idk_atoms_for_each_api_level.validate",
]
if (current_build_target_api_level != "PLATFORM" || !sdk_inside_sub_build) {
visibility += [
":${main_target_name}.fuchsia_idk_atoms_produced_by_subbuilds.manifest",
]
}
non_sdk_deps = invoker.non_sdk_deps_build_tests_for_all_builds
deps = invoker.prebuilt_libraries + invoker.sysroot
# SDK packages cannot be built at "PLATFORM". This only affects the
# sub-build deps.
# TODO(https://fxbug.dev/347094435): Make it possible to cover the
# SDK package deps and remove this condition.
if (current_build_target_api_level != "PLATFORM") {
deps += invoker.packages
} else {
not_needed(invoker, [ "packages" ])
}
}
if (current_build_target_api_level == "PLATFORM" ||
# Handle core.x64-sdk_source_sets_and_shlibs-apiXX-build_only builders.
# TODO(https://fxbug.dev/42082833): Remove this.
override_target_api_level != false) {
# These rules are processed at least once for the primary target CPU,
# which may not match the host_cpu. They may also be processed for
# additional CPU architectures when building the IDK.
sdk_molecule(
"${main_target_name}.fuchsia_idk_atoms_built_only_at_platform_for_each_cpu_arch") {
category = "partner"
non_sdk_deps = invoker.non_sdk_deps_build_tests_for_all_builds
# Do not add more dependencies here. Instead, add new dependencies to
# :fuchsia_idk_atoms_independent_of_api_level_for_one_cpu_arch,
# which verifies there are no API level dependencies.
# Atoms that currently must be generated at "PLATFORM" for backwards
# compatibility with IDK users that do not yet use per-API-level atoms.
deps = invoker.atoms_to_include_in_deprecated_arch_directory
# While the Vulkan layers support being built at individual API levels,
# the SDK atom is not aware of API levels so each sub-build would be
# written to the same path in the IDK, clobbering all but one for each
# CPU architecture.
# TODO(https://fxbug.dev/327223536): Make an SDK atom for loadable
# modules that supports is API level-aware and move this to
# :fuchsia_idk_atoms_for_each_api_level.
deps += invoker.vulkan_layers
}
# The rules below only need to be processed once, during the main build.
# Since sub-builds change the `target_cpu`, this cannot be used as
# a condition. While, `host_cpu` does not change in sub-builds, using that
# would require extra processing and building when it does not match the
# primary target CPU. Therefore, use `sdk_inside_sub_build`.
# TODO(https://fxbug.dev/310006516): Once this and
# https://fxbug.dev/327223536 are addressed sub-builds will never target
# "PLATFORM" and this logic and GN variable can be removed.
if (!sdk_inside_sub_build) {
subbuilds_target_name = "${main_target_name}_subbuilds"
all_subbuilds_for_merge_target_name =
"${main_target_name}_all_subbuilds_for_merge"
# The collection for the IDK.
# This target was historically always named "core".
# Only built in the main build at "PLATFORM" for the target CPU.
# Sub-builds build ":${main_target_name}_for_subbuilds" for this same
# collection.
# Note: idk() expects the collection's manifest to be its target name.
# Hence the short name of this target.
sdk_collection(main_target_name) {
visibility = []
visibility =
invoker.visibility + [ ":${all_subbuilds_for_merge_target_name}" ]
category = "partner"
id = sdk_id
deps = [
# Don't add other sdk_molecules here. Add them to the molecule below.
":${main_target_name}.fuchsia_idk_atoms_produced_by_main_platform_build",
]
}
# The sub-builds.
# Note that the variants (prefixes) do NOT share an output directory
# because this would require plumbing through a stamp file override and,
# more significantly, require adding complexity to support
# //build/scripts/ninjatrace2json.py.
# This should be okay since it should be rare that both variants are built.
idk_subbuilds(subbuilds_target_name) {
visibility = []
visibility = invoker.subbuilds_visibility +
[ ":${all_subbuilds_for_merge_target_name}" ]
sdk_collection_label = ":${main_target_name}_for_subbuilds"
subbuild_prefix = "idk_subbuild.${main_target_name}_for_subbuilds"
# Use the same name as the collection so paths match.
sdk_collection_name = main_target_name
target_cpus = idk_buildable_cpus
api_levels = idk_buildable_api_levels
}
# Ensures all builds to be merged into the final Fuchsia IDK, including
# the main collection and all sub-builds for the current global GN args
# configuration, have been built.
group(all_subbuilds_for_merge_target_name) {
visibility = []
visibility = invoker.subbuilds_visibility
deps = [
":${main_target_name}",
":${subbuilds_target_name}",
]
}
# All atoms to be produced by the main build for inclusion in the IDK.
#
# Due to limitations of the build system at the GN/Bazel boundary, this
# cannot contain testonly atoms. See https://fxbug.dev/42070088.
# Libraries and packages for use in tests absolutely belong in the IDK, but
# the `testonly` attribute must be removed before they can be added.
sdk_molecule(
"${main_target_name}.fuchsia_idk_atoms_produced_by_main_platform_build") {
category = "partner"
deps = [
":${main_target_name}.fuchsia_idk_atoms_built_in_main_platform_build_only",
":${main_target_name}.fuchsia_idk_atoms_built_only_at_platform_for_each_cpu_arch",
]
# Parts of the in-tree build assume that the "core" manifest exists.
# Temporarily ensure that manifest is generated by the same in-tree
# IDK build tree. Use a non_sdk_deps so it is not included in the
# IDK's manifest. This must be here because idk() and sdk_collection()
# do not support non_sdk_deps.
# TODO(https://fxbug.dev/317385989): Burn down these assumptions and
# remove this dependency.
if (main_target_name == "in_tree_collection") {
non_sdk_deps = [ ":core" ]
# Do not include atoms in core in the prebuild data.
metadata = {
idk_atom_prebuild_info_barrier = deps
}
}
}
sdk_molecule(
"${main_target_name}.fuchsia_idk_atoms_built_in_main_platform_build_only") {
# This molecule is a subset of the target above for organization only
# and should thus not be used elsewhere.
visibility = []
visibility = [
":${main_target_name}.fuchsia_idk_atoms_produced_by_main_platform_build.manifest",
# Dependencies related to template sub-targets.
":${main_target_name}.fuchsia_idk_atoms_built_in_main_platform_build_only",
":${main_target_name}.fuchsia_idk_atoms_built_in_main_platform_build_only.validate",
]
category = "partner"
deps = [
":${main_target_name}.fuchsia_idk_atoms_built_only_at_platform_for_one_cpu_arch",
":${main_target_name}.fuchsia_idk_atoms_independent_of_api_level_for_one_cpu_arch",
]
deps += invoker.host_tools + invoker.host_tests
}
# Do not add dependencies to this target without a really good reason.
# Most such dependencies should be verifiably independent of the API level
# and (not verifiable) CPU architecture (add to
# :fuchsia_idk_atoms_independent_of_api_level_for_one_cpu_arch).
#
# IDK atoms that must be built at "PLATFORM" but only once (for one CPU
# architecture).
# The resulting artifacts should be independent of the CPU architecture,
# though that cannot be enforced.
sdk_molecule(
"${main_target_name}.fuchsia_idk_atoms_built_only_at_platform_for_one_cpu_arch") {
category = "partner"
deps =
# This target contains atoms that depend on FIDL libraries, but it
# does not build the underlying libraries.
invoker.source_libraries +
# This target compiles the FIDL files, but the output used in the IDK
# is not specific to any API level or CPU architecture.
invoker.fidl_libraries +
# Some generated documentation depends on FIDL and thus cannot be in
# :fuchsia_idk_atoms_independent_of_api_level_for_one_cpu_arch_...
invoker.docs_dependent_on_fidl
}
# IDK atoms that are independent of a specific API level and only need to
# be built once (for one CPU architecture).
# The former is enforced (as much as practical) by an assert_no_deps.
# The resulting artifacts should be independent of the CPU architecture,
# though that cannot be enforced. The target CPU architecture is used.
sdk_molecule(
"${main_target_name}.fuchsia_idk_atoms_independent_of_api_level_for_one_cpu_arch") {
category = "partner"
# The following serve as a proxy for the building of FIDL files. A
# dependency on these suggests that there is a dependency on FIDL
# interface(s), which would likely mean that the code must be built at
# each API level and should be in a different molecule.
assert_no_deps = [
"//tools/fidl/fidl_api_diff:host",
"//tools/fidl/fidl_api_summarize:fidl_api_summarize($host_toolchain)",
"//tools/fidl/fidlc:fidl-lint.host",
]
deps = invoker.atoms_independent_of_api_level_and_cpu_arch +
invoker.dart_library + invoker.docs
}
} else {
not_needed(invoker, [])
} # end if (!sdk_inside_sub_build)
} else {
not_needed(invoker,
[
"atoms_to_include_in_deprecated_arch_directory",
"vulkan_layers",
])
} # end if (current_build_target_api_level == "PLATFORM")
if (sdk_inside_sub_build) {
not_needed(invoker,
[
"atoms_independent_of_api_level_and_cpu_arch",
"dart_library",
"docs",
"docs_dependent_on_fidl",
"fidl_libraries",
"host_tests",
"host_tools",
"source_libraries",
"subbuilds_visibility",
])
}
} # end template