Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_unit_test / test.gni
1 # Copyright 2019 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
15 import("//build_overrides/pigweed.gni")
16
17 import("$dir_pw_build/python_action.gni")
18 import("$dir_pw_build/target_types.gni")
19
20 declare_args() {
21   # Path to a test runner to automatically run unit tests after they are built.
22   #
23   # If set, the pw_test() template creates an action that invokes the test runner
24   # on each test executable. If unset, the pw_test() template only creates a test
25   # executable target.
26   #
27   # This should only be enabled for targets which support parallelized running of
28   # unit tests, such as desktops with multiple cores.
29   pw_unit_test_AUTOMATIC_RUNNER = ""
30
31   # Additional dependencies required by all unit test targets. (For example, if
32   # using a different test library like Googletest.)
33   pw_unit_test_PUBLIC_DEPS = []
34
35   # Implementation of a main function for "pw_test" unit test binaries.
36   pw_unit_test_MAIN = "$dir_pw_unit_test:simple_printing_main"
37 }
38
39 # Defines a target if enable_if is true. Otherwise, it defines that target as
40 # <target_name>.DISABLED and creates an empty <target_name> group. This can be
41 # used to conditionally create targets without having to conditionally add them
42 # to groups. This results in simpler BUILD.gn files.
43 template("_pw_disableable_target") {
44   assert(defined(invoker.enable_if),
45          "`enable_if` is required for _pw_disableable_target")
46   assert(defined(invoker.target_type),
47          "`target_type` is required for _pw_disableable_target")
48
49   if (invoker.enable_if) {
50     _actual_target_name = target_name
51   } else {
52     _actual_target_name = target_name + ".DISABLED"
53
54     # If the target is disabled, create an empty target in its place. Use an
55     # action with the original target's sources as inputs to ensure that
56     # the source files exist (even if they don't compile).
57     pw_python_action(target_name) {
58       script = "$dir_pw_build/py/pw_build/nop.py"
59       stamp = true
60
61       inputs = []
62       if (defined(invoker.sources)) {
63         inputs += invoker.sources
64       }
65       if (defined(invoker.public)) {
66         inputs += invoker.public
67       }
68     }
69   }
70
71   target(invoker.target_type, _actual_target_name) {
72     forward_variables_from(invoker,
73                            "*",
74                            [
75                              "enable_if",
76                              "target_type",
77                            ])
78
79     # Remove "" from dependencies. This allows disabling targets if a variable
80     # (e.g. a backend) is empty.
81     if (defined(public_deps)) {
82       public_deps += [ "" ]
83       public_deps -= [ "" ]
84     }
85     if (defined(deps)) {
86       deps += [ "" ]
87       deps -= [ "" ]
88     }
89   }
90 }
91
92 # Creates a library and an executable target for a unit test.
93 #
94 # <target_name>.lib contains the provided test sources as a library, which can
95 # then be linked into a test executable.
96 # <target_name> is a standalone executable which contains only the test sources
97 # specified in the pw_unit_test_template.
98 #
99 # If the pw_unit_test_AUTOMATIC_RUNNER variable is set, this template also creates a
100 # "${test_name}.run" target which runs the unit test executable after building
101 # it.
102 #
103 # Args:
104 #   - enable_if: (optional) Conditionally enables or disables this test. The test
105 #         target and *.run target do nothing when the test is disabled. The
106 #         disabled test can still be built and run with the
107 #         <target_name>.DISABLED and <target_name>.DISABLED.run targets.
108 #         Defaults to true (enable_if).
109 #   - All of the regular "executable" target args are accepted.
110 template("pw_test") {
111   # This is required in order to reference the pw_test template's target name
112   # within the test_metadata of the metadata group below. The group() definition
113   # creates a new scope where the "target_name" variable is set to its target,
114   # shadowing the one in this scope.
115   _test_target_name = target_name
116
117   _test_is_enabled = !defined(invoker.enable_if) || invoker.enable_if
118
119   # Always set the output_dir as pigweed is not compatible with shared
120   # bin directories for tests.
121   _test_output_dir = "${target_out_dir}/test"
122   if (defined(invoker.output_dir)) {
123     _test_output_dir = invoker.output_dir
124   }
125
126   _test_main = pw_unit_test_MAIN
127   if (defined(invoker.test_main)) {
128     _test_main = invoker.test_main
129   }
130
131   # The unit test code as a source_set.
132   _pw_disableable_target("$target_name.lib") {
133     target_type = "pw_source_set"
134     enable_if = _test_is_enabled
135     forward_variables_from(invoker, "*", [ "metadata" ])
136
137     if (!defined(public_deps)) {
138       public_deps = []
139     }
140     public_deps += pw_unit_test_PUBLIC_DEPS + [ dir_pw_unit_test ]
141   }
142
143   _pw_disableable_target(_test_target_name) {
144     target_type = "pw_executable"
145     enable_if = _test_is_enabled
146
147     # Metadata for this test when used as part of a pw_test_group target.
148     metadata = {
149       tests = [
150         {
151           type = "test"
152           test_name = _test_target_name
153           test_directory = rebase_path(_test_output_dir, root_build_dir)
154         },
155       ]
156     }
157
158     deps = [ ":$_test_target_name.lib" ]
159     if (_test_main != "") {
160       deps += [ _test_main ]
161     }
162
163     output_dir = _test_output_dir
164   }
165
166   if (pw_unit_test_AUTOMATIC_RUNNER != "") {
167     # When the automatic runner is set, create an action which runs the unit
168     # test executable using the test runner script.
169     if (_test_is_enabled) {
170       _test_to_run = _test_target_name
171     } else {
172       # Create a run target for the .DISABLED version of the test.
173       _test_to_run = _test_target_name + ".DISABLED"
174
175       # Create a dummy _run target for the regular version of the test.
176       group(_test_target_name + ".run") {
177         deps = [ ":$_test_target_name" ]
178       }
179     }
180
181     pw_python_action(_test_to_run + ".run") {
182       deps = [ ":$_test_target_name" ]
183       inputs = [ pw_unit_test_AUTOMATIC_RUNNER ]
184       script = "$dir_pw_unit_test/py/pw_unit_test/test_runner.py"
185       python_deps = [ "$dir_pw_cli/py" ]
186       args = [
187         "--runner",
188         rebase_path(pw_unit_test_AUTOMATIC_RUNNER),
189         "--test",
190         "<TARGET_FILE(:$_test_to_run)>",
191       ]
192       stamp = true
193     }
194
195     # TODO(frolv): Alias for the deprecated _run target. Remove when projects
196     # are migrated.
197     group(_test_to_run + "_run") {
198       public_deps = [ ":$_test_to_run.run" ]
199     }
200   } else {
201     group(_test_target_name + ".run") {
202     }
203   }
204 }
205
206 # Defines a related collection of unit tests.
207 #
208 # pw_test_group targets output a JSON metadata file for the Pigweed test runner.
209 #
210 # Args:
211 #   - tests: List of pw_test targets for each of the tests in the group.
212 #   - group_deps: (optional) pw_test_group targets on which this group depends.
213 #   - enable_if: (optional) Conditionally enables or disables this test group.
214 #         If false, an empty group is created. Defaults to true.
215 template("pw_test_group") {
216   _group_target = target_name
217   _group_deps_metadata = []
218   if (defined(invoker.tests)) {
219     _deps = invoker.tests
220   } else {
221     _deps = []
222   }
223
224   _group_is_enabled = !defined(invoker.enable_if) || invoker.enable_if
225
226   if (_group_is_enabled) {
227     if (defined(invoker.group_deps)) {
228       # If the group specified any other group dependencies, create a metadata
229       # entry for each of them indicating that they are another group and a
230       # group target to collect that metadata.
231       foreach(dep, invoker.group_deps) {
232         _group_deps_metadata += [
233           {
234             type = "dep"
235             group = get_label_info(dep, "label_no_toolchain")
236           },
237         ]
238       }
239
240       _deps += invoker.group_deps
241     }
242
243     group(_group_target + ".lib") {
244       deps = []
245       foreach(_target, _deps) {
246         _dep_target = get_label_info(_target, "label_no_toolchain")
247         _dep_toolchain = get_label_info(_target, "toolchain")
248         deps += [ "$_dep_target.lib($_dep_toolchain)" ]
249       }
250     }
251
252     _metadata_group_target = "${target_name}_pw_test_group_metadata"
253     group(_metadata_group_target) {
254       metadata = {
255         group_deps = _group_deps_metadata
256         self = [
257           {
258             type = "self"
259             name = get_label_info(":$_group_target", "label_no_toolchain")
260           },
261         ]
262
263         # Metadata from the group's own unit test targets is forwarded through
264         # the group dependencies group. This entry is listed as a "walk_key" in
265         # the generated file so that only test targets' metadata (not group
266         # targets) appear in the output.
267         if (defined(invoker.tests)) {
268           propagate_metadata_from = invoker.tests
269         }
270       }
271       deps = _deps
272     }
273
274     _test_group_deps = [ ":$_metadata_group_target" ]
275
276     generated_file(_group_target) {
277       outputs = [ "$target_out_dir/$target_name.testinfo.json" ]
278       data_keys = [
279         "group_deps",
280         "self",
281         "tests",
282       ]
283       walk_keys = [ "propagate_metadata_from" ]
284       output_conversion = "json"
285       deps = _test_group_deps
286     }
287
288     # If automatic test running is enabled, create a *.run group that collects
289     # all of the individual *.run targets and groups.
290     if (pw_unit_test_AUTOMATIC_RUNNER != "") {
291       group(_group_target + ".run") {
292         deps = [ ":$_group_target" ]
293         foreach(_target, _deps) {
294           _dep_target = get_label_info(_target, "label_no_toolchain")
295           _dep_toolchain = get_label_info(_target, "toolchain")
296           deps += [ "$_dep_target.run($_dep_toolchain)" ]
297         }
298       }
299
300       # TODO(frolv): Remove this deprecated alias.
301       group(_group_target + "_run") {
302         deps = [ ":$_group_target.run" ]
303       }
304     }
305   } else {  # _group_is_enabled
306     # Create empty groups for the tests to avoid pulling in any dependencies.
307     group(_group_target) {
308     }
309     group(_group_target + ".lib") {
310     }
311
312     if (pw_unit_test_AUTOMATIC_RUNNER != "") {
313       group(_group_target + ".run") {
314       }
315
316       # TODO(frolv): Remove this deprecated alias.
317       group(_group_target + "_run") {
318       }
319     }
320
321     not_needed("*")
322     not_needed(invoker, "*")
323   }
324
325   # All of the tests in this group and its dependencies bundled into a single
326   # test binary.
327   pw_test(_group_target + ".bundle") {
328     deps = [ ":$_group_target.lib" ]
329     enable_if = _group_is_enabled
330   }
331 }