xref: /aosp_15_r20/external/pigweed/pw_build/gn_internal/build_target.gni (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1# Copyright 2022 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
15import("//build_overrides/pigweed.gni")
16
17import("$dir_pw_build/defaults.gni")
18
19declare_args() {
20  # Additional build targets to add as dependencies for pw_executable,
21  # pw_static_library, and pw_shared_library targets. The
22  # $dir_pw_build:link_deps target pulls in these libraries.
23  #
24  # pw_build_LINK_DEPS can be used to break circular dependencies for low-level
25  # libraries such as pw_assert.
26  pw_build_LINK_DEPS = []
27
28  # pw_build_TOOLCHAIN_LINK_DEPS is used by pw_toolchain module to set default
29  # libary dependencies. Generally, this is not intended to be user-facing, but
30  # if something is introduced here that you need to remove, you can do so by
31  # overriding this variable in your own toolchain.
32  pw_build_TOOLCHAIN_LINK_DEPS = []
33
34  # The name of the GN target type used to build Pigweed executables.
35  #
36  # If this is a custom template, the .gni file containing the template must
37  # be imported at the top of the target configuration file to make it globally
38  # available.
39  pw_build_EXECUTABLE_TARGET_TYPE = "executable"
40
41  # The path to the .gni file that defines pw_build_EXECUTABLE_TARGET_TYPE.
42  #
43  # If pw_build_EXECUTABLE_TARGET_TYPE is not the default of `executable`, this
44  # .gni file is imported to provide the template definition.
45  pw_build_EXECUTABLE_TARGET_TYPE_FILE = ""
46}
47
48# This template is the underlying implementation that defines what makes
49# pw_source_set, pw_executable, pw_shared_library, and pw_static_library unique.
50# For more information, see the documentation at
51# https://pigweed.dev/pw_build/?highlight=pw_executable#target-types
52#
53# In addition to the arguments supported by the underlying native target types,
54# this template introduces the following arguments:
55#
56#  add_global_link_deps: (required) If true, adds global link dependencies as
57#    specified by the current toolchain via pw_build_LINK_DEPS as dependencies
58#    to all instantiations of the current target type.
59#  underlying_target_type: (required) The underlying target type to use for this
60#    template. This is done so different C/C++ build target types can share the
61#    same underlying wrapper implementation.
62#  target_type_file: (optional) If the underlying target type is not one of GN's
63#    builtin types, the path to the .gni file that defines the template
64#    referenced by underlying_target_type. This is exclusively to support
65#    pw_exeuctable's behavior that allows a pw_executable to be essentially
66#    aliased to a custom target type.
67#  remove_configs: (optional) A list of configs to remove from the set of
68#    default configs specified by the current toolchain configuration.
69#  remove_public_deps: (optional) A list of targets to remove from the set of
70#    default public_deps specified by the current toolchain configuration.
71template("pw_internal_build_target") {
72  assert(defined(invoker.underlying_target_type),
73         "Build targets using this template must specify a target type")
74  _pw_source_files = []
75  _supported_toolchain_defaults = [
76    "configs",
77    "public_deps",
78  ]
79
80  # Boilerplate for tracking target sources.  For more information see
81  # https://pigweed.dev/pw_build/#target-types
82  if (defined(invoker.sources)) {
83    foreach(path, invoker.sources) {
84      _pw_source_files += [ path ]
85    }
86  }
87  if (defined(invoker.public)) {
88    foreach(path, invoker.public) {
89      _pw_source_files += [ path ]
90    }
91  }
92
93  _builtin_target_types = [
94    "executable",
95    "rust_library",
96    "rust_proc_macro",
97    "shared_library",
98    "source_set",
99    "static_library",
100  ]
101  if (filter_include(_builtin_target_types,
102                     [ invoker.underlying_target_type ]) == []) {
103    assert(
104        defined(invoker.target_type_file) && invoker.target_type_file != "",
105        string_join(
106            ", ",
107            [
108              "Unknown target type ${invoker.underlying_target_type}",
109              "set target_type_file to the .gni file that defines this type.",
110            ]))
111    import(invoker.target_type_file)
112  }
113
114  target(invoker.underlying_target_type, target_name) {
115    forward_variables_from(
116        invoker,
117        "*",
118        _supported_toolchain_defaults + [ "target_type_file" ])
119
120    # Ensure that we don't overwrite metadata forwarded from the invoker above.
121    if (defined(metadata)) {
122      metadata.pw_source_files = _pw_source_files
123    } else {
124      metadata = {
125        pw_source_files = _pw_source_files
126      }
127    }
128
129    _default_configs =
130        filter_exclude(pw_build_INTERNAL_DEFAULTS.default_configs,
131                       pw_build_INTERNAL_DEFAULTS.remove_default_configs)
132    if (!defined(remove_configs)) {
133      remove_configs = []
134    }
135
136    # Check if configs is already defined.
137    # configs will already exist if set_defaults() is used.
138    if (!defined(configs)) {
139      configs = []
140    }
141
142    # `configs` was not forwarded initially to support flag ordering.
143    configs += filter_exclude(_default_configs, remove_configs)
144
145    # Add the public_deps from the actual target last so they are prioritized.
146    # This set of public_deps MUST be added last because it affects flag
147    # ordering. If this list is added later, flags from the default list will
148    # take precedence.
149    if (defined(invoker.configs)) {
150      configs += invoker.configs
151    }
152
153    _default_public_deps =
154        filter_exclude(pw_build_INTERNAL_DEFAULTS.default_public_deps,
155                       pw_build_INTERNAL_DEFAULTS.remove_default_public_deps)
156    if (!defined(remove_public_deps)) {
157      remove_public_deps = []
158    }
159
160    # `public_deps` was not forwarded initially to support flag ordering.
161    public_deps = filter_exclude(_default_public_deps, remove_public_deps)
162
163    # Add the public_deps from the actual target last so they are prioritized.
164    # This set of public_deps MUST be added last because it affects flag
165    # ordering. If this list is added later, flags from the default list will
166    # take precedence.
167    if (defined(invoker.public_deps)) {
168      public_deps += invoker.public_deps
169    }
170
171    assert(defined(add_global_link_deps),
172           "All targets MUST specify whether or not to include link deps")
173    if (!defined(deps)) {
174      deps = []
175    }
176    if (add_global_link_deps) {
177      deps += [ "$dir_pw_build:link_deps" ]
178    }
179
180    if (!defined(visibility)) {
181      visibility = pw_build_DEFAULT_VISIBILITY
182    }
183  }
184}
185