• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
17declare_args() {
18  # Additional build targets to add as dependencies for pw_executable,
19  # pw_static_library, and pw_shared_library targets. The
20  # $dir_pw_build:link_deps target pulls in these libraries.
21  #
22  # pw_build_LINK_DEPS can be used to break circular dependencies for low-level
23  # libraries such as pw_assert.
24  pw_build_LINK_DEPS = []
25
26  # The name of the GN target type used to build Pigweed executables.
27  #
28  # If this is a custom template, the .gni file containing the template must
29  # be imported at the top of the target configuration file to make it globally
30  # available.
31  pw_build_EXECUTABLE_TARGET_TYPE = "executable"
32
33  # The path to the .gni file that defines pw_build_EXECUTABLE_TARGET_TYPE.
34  #
35  # If pw_build_EXECUTABLE_TARGET_TYPE is not the default of `executable`, this
36  # .gni file is imported to provide the template definition.
37  pw_build_EXECUTABLE_TARGET_TYPE_FILE = ""
38}
39
40# This template is the underlying implementation that defines what makes
41# pw_source_set, pw_executable, pw_shared_library, and pw_static_library unique.
42# For more information, see the documentation at
43# https://pigweed.dev/pw_build/?highlight=pw_executable#target-types
44#
45# In addition to the arguments supported by the underlying native target types,
46# this template introduces the following arguments:
47#
48#  add_global_link_deps: (required) If true, adds global link dependencies as
49#    specified by the current toolchain via pw_build_LINK_DEPS as dependencies
50#    to all instantiations of the current target type.
51#  underlying_target_type: (required) The underlying target type to use for this
52#    template. This is done so different C/C++ build target types can share the
53#    same underlying wrapper implementation.
54#  target_type_file: (optional) If the underlying target type is not one of GN's
55#    builtin types, the path to the .gni file that defines the template
56#    referenced by underlying_target_type. This is exclusively to support
57#    pw_exeuctable's behavior that allows a pw_executable to be essentially
58#    aliased to a custom target type.
59#  remove_configs: (optional) A list of configs to remove from the set of
60#    default configs specified by the current toolchain configuration.
61#  remove_public_deps: (optional) A list of targets to remove from the set of
62#    default public_deps specified by the current toolchain configuration.
63template("pw_internal_build_target") {
64  assert(defined(invoker.underlying_target_type),
65         "Build targets using this template must specify a target type")
66  _pw_source_files = []
67  _supported_toolchain_defaults = [
68    "configs",
69    "public_deps",
70  ]
71
72  # Boilerplate for tracking target sources.  For more information see
73  # https://pigweed.dev/pw_build/#target-types
74  if (defined(invoker.sources)) {
75    foreach(path, invoker.sources) {
76      _pw_source_files += [ path ]
77    }
78  }
79  if (defined(invoker.public)) {
80    foreach(path, invoker.public) {
81      _pw_source_files += [ path ]
82    }
83  }
84
85  _builtin_target_types = [
86    "executable",
87    "rust_library",
88    "shared_library",
89    "source_set",
90    "static_library",
91  ]
92  if (filter_include(_builtin_target_types,
93                     [ invoker.underlying_target_type ]) == []) {
94    assert(
95        defined(invoker.target_type_file) && invoker.target_type_file != "",
96        string_join(
97            ", ",
98            [
99              "Unknown target type ${invoker.underlying_target_type}",
100              "set target_type_file to the .gni file that defines this type.",
101            ]))
102    import(invoker.target_type_file)
103  }
104
105  target(invoker.underlying_target_type, target_name) {
106    # TODO(b/260111641): This import is terrible, and breaks typical Pigweed GN
107    # build arg naming patterns.
108    import("$dir_pw_build/defaults.gni")
109    forward_variables_from(
110        invoker,
111        "*",
112        _supported_toolchain_defaults + [ "target_type_file" ])
113
114    # Ensure that we don't overwrite metadata forwarded from the invoker above.
115    if (defined(metadata)) {
116      metadata.pw_source_files = _pw_source_files
117    } else {
118      metadata = {
119        pw_source_files = _pw_source_files
120      }
121    }
122
123    if (!defined(configs)) {
124      configs = []
125    }
126    if (defined(pw_build_defaults.configs)) {
127      configs += pw_build_defaults.configs
128    }
129    if (defined(remove_configs)) {
130      if (remove_configs != [] && remove_configs[0] == "*") {
131        configs = []
132      } else {
133        configs -= filter_include(configs, remove_configs)
134      }
135    }
136    if (defined(invoker.configs)) {
137      configs += invoker.configs
138    }
139
140    if (defined(pw_build_defaults.public_deps)) {
141      public_deps = pw_build_defaults.public_deps
142    } else {
143      public_deps = []
144    }
145    if (defined(remove_public_deps)) {
146      if (remove_public_deps != [] && remove_public_deps[0] == "*") {
147        public_deps = []
148      } else {
149        public_deps += remove_public_deps
150        public_deps -= remove_public_deps
151      }
152    }
153    if (defined(invoker.public_deps)) {
154      public_deps += invoker.public_deps
155    }
156
157    assert(defined(add_global_link_deps),
158           "All targets MUST specify whether or not to include link deps")
159    if (!defined(deps)) {
160      deps = []
161    }
162    if (add_global_link_deps) {
163      deps += [ "$dir_pw_build:link_deps" ]
164    }
165
166    if (defined(pw_build_defaults.visibility) && !defined(visibility)) {
167      visibility = pw_build_defaults.visibility
168    }
169  }
170}
171