[M120 Migration] Implement ewk_view_is_video_playing api
[platform/framework/web/chromium-efl.git] / build / nocompile.gni
1 # Copyright 2011 The Chromium Authors
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 # This file is meant to be included into an target to create a unittest that
6 # invokes a set of no-compile tests.  A no-compile test is a test that asserts
7 # a particular construct will not compile.
8 #
9 # Usage:
10 #
11 # 1. Create a GN target:
12 #
13 #    import("//build/nocompile.gni")
14 #
15 #    nocompile_source_set("base_nocompile") {
16 #      sources = [
17 #        "functional/one_not_equal_two_nocompile.nc",
18 #      ]
19 #      deps = [
20 #        ":base"
21 #      ]
22 #    }
23 #
24 #    Note that by convention, nocompile tests use the `.nc` extension rather
25 #    than the standard `.cc` extension: this is because the expectation lines
26 #    often exceed 80 characters, which would make clang-format unhappy.
27 #
28 # 2. Add a dep from a related test binary to the nocompile source set:
29 #
30 #    test("base_unittests") {
31 #      ...
32 #      deps += [ ":base_nocompile_tests" ]
33 #    }
34 #
35 # 3. Populate the .nc file with test cases. Expected compile failures should be
36 #    annotated with a comment of the form:
37 #
38 #    // expected-error {{<expected error string here>}}
39 #
40 #    For example:
41 #
42 #    void OneDoesNotEqualTwo() {
43 #      static_assert(1 == 2);  // expected-error {{static assertion failed due to requirement '1 == 2'}}
44 #    }
45 #
46 #    The verification logic is built as part of clang; full documentation is at
47 #    https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html.
48 #
49 # Also see:
50 #   http://dev.chromium.org/developers/testing/no-compile-tests
51 #
52 import("//build/config/clang/clang.gni")
53 if (is_win) {
54   import("//build/toolchain/win/win_toolchain_data.gni")
55 }
56
57 declare_args() {
58   enable_nocompile_tests = (is_linux || is_chromeos || is_apple || is_win) &&
59                            is_clang && host_cpu == target_cpu
60   enable_nocompile_tests_new = is_clang && !is_nacl && !is_tizen
61 }
62
63 if (enable_nocompile_tests_new) {
64   template("nocompile_source_set") {
65     action_foreach(target_name) {
66       testonly = true
67
68       script = "//tools/nocompile/wrapper.py"
69       sources = invoker.sources
70       deps = invoker.deps
71
72       # An action is not a compiler, so configs is empty until it is explicitly set.
73       configs = default_compiler_configs
74
75       # Disable the checks that the Chrome style plugin normally enforces to
76       # reduce the amount of boilerplate needed in nocompile tests.
77       configs -= [ "//build/config/clang:find_bad_constructs" ]
78
79       if (is_win) {
80         result_path =
81             "$target_out_dir/$target_name/{{source_name_part}}_placeholder.obj"
82       } else {
83         result_path =
84             "$target_out_dir/$target_name/{{source_name_part}}_placeholder.o"
85       }
86       rebased_obj_path = rebase_path(result_path, root_build_dir)
87
88       depfile = "${result_path}.d"
89       rebased_depfile_path = rebase_path(depfile, root_build_dir)
90       outputs = [ result_path ]
91
92       if (is_win) {
93         if (host_os == "win") {
94           cxx = "clang-cl.exe"
95         } else {
96           cxx = "clang-cl"
97         }
98       } else {
99         cxx = "clang++"
100       }
101
102       args = []
103
104       if (is_win) {
105         # ninja normally parses /showIncludes output, but the depsformat
106         # variable can only be set in compiler tools, not for custom actions.
107         # Unfortunately, this means the clang wrapper needs to generate the
108         # depfile itself.
109         args += [ "--generate-depfile" ]
110       }
111
112       args += [
113         rebase_path("$clang_base_path/bin/$cxx", root_build_dir),
114         "{{source}}",
115         rebased_obj_path,
116         rebased_depfile_path,
117         "--",
118         "{{cflags}}",
119         "{{cflags_cc}}",
120         "{{defines}}",
121         "{{include_dirs}}",
122
123         # No need to generate an object file for nocompile tests.
124         "-Xclang",
125         "-fsyntax-only",
126
127         # Enable clang's VerifyDiagnosticConsumer:
128         # https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html
129         "-Xclang",
130         "-verify",
131
132         # But don't require expected-note comments since that is not the
133         # primary point of the nocompile tests.
134         "-Xclang",
135         "-verify-ignore-unexpected=note",
136
137         # Disable the error limit so that nocompile tests do not need to be
138         # arbitrarily split up when they hit the default error limit.
139         "-ferror-limit=0",
140
141         # So funny characters don't show up in error messages.
142         "-fno-color-diagnostics",
143
144         # Always treat warnings as errors.
145         "-Werror",
146       ]
147
148       if (!is_win) {
149         args += [
150           # On non-Windows platforms, clang can generate the depfile.
151           "-MMD",
152           "-MF",
153           rebased_depfile_path,
154           "-MT",
155           rebased_obj_path,
156
157           # Non-Windows clang uses file extensions to determine how to treat
158           # various inputs, so explicitly tell it to treat all inputs (even
159           # those with weird extensions like .nc) as C++ source files.
160           "-x",
161           "c++",
162         ]
163       } else {
164         # For some reason, the Windows includes are not part of the default
165         # compiler configs. Set it explicitly here, since things like libc++
166         # depend on the VC runtime.
167         if (target_cpu == "x86") {
168           win_toolchain_data = win_toolchain_data_x86
169         } else if (target_cpu == "x64") {
170           win_toolchain_data = win_toolchain_data_x64
171         } else if (target_cpu == "arm64") {
172           win_toolchain_data = win_toolchain_data_arm64
173         } else {
174           error("Unsupported target_cpu, add it to win_toolchain_data.gni")
175         }
176         args += win_toolchain_data.include_flags_imsvc_list
177         args += [ "/showIncludes:user" ]
178       }
179
180       # Note: for all platforms, the depfile only lists user includes, and not
181       # system includes. If system includes change, the compiler flags are
182       # expected to artificially change in some way to invalidate and force the
183       # nocompile tests to run again.
184     }
185   }
186 }
187
188 # TODO(https://crbug.com/1480969): this section remains for legacy
189 # documentation. However, nocompile tests using these legacy templates are
190 # migrated to the new-style tests. Please do not add more old-style tests.
191 #
192 # To use this, create a GN target with the following form:
193 #
194 # import("//build/nocompile.gni")
195 # nocompile_test("my_module_nc_unittests") {
196 #   sources = [
197 #     'nc_testset_1.nc',
198 #     'nc_testset_2.nc',
199 #   ]
200 #
201 #   # optional extra include dirs:
202 #   include_dirs = [ ... ]
203 # }
204 #
205 # The tests are invoked by building the target named in the nocompile_test()
206 # macro, for example:
207 #
208 # ninja -C out/Default my_module_nc_unittests
209 #
210 # The .nc files are C++ files that contain code we wish to assert will not
211 # compile. Each individual test case in the file should be put in its own
212 # #if defined(...) section specifying an unique preprocessor symbol beginning
213 # with NCTEST which names the test. The set of tests in a file is automatically
214 # determined by scanning the file for these #if blocks and no other explicit
215 # definition of the symbol is required to register a test.
216 #
217 # The expected complier error message should be appended with a C++-style
218 # comment that has a python list of regular expressions. This will likely be
219 # greater than 80-characters. Giving a solid expected output test is important
220 # so that random compile failures do not cause the test to pass.
221 #
222 # Example .nc file:
223 #
224 #   #if defined(NCTEST_NEEDS_SEMICOLON)  // [r"expected ',' or ';' at end of input"]
225 #
226 #   int a = 1
227 #
228 #   #elif defined(NCTEST_NEEDS_CAST)  // [r"invalid conversion from 'void*' to 'char*'"]
229 #
230 #   void* a = NULL;
231 #   char* b = a;
232 #
233 #   #endif
234 #
235 # If we need to disable NCTEST_NEEDS_SEMICOLON, then change the #if to:
236 #
237 #   #if defined(DISABLED_NCTEST_NEEDS_SEMICOLON)
238 #   ...
239 #   #elif defined(NCTEST_NEEDS_CAST)
240 #   ...
241 #
242 # The lines above are parsed by a regexp so avoid getting creative with the
243 # formatting or ifdef logic; it will likely just not work.
244 #
245 # Implementation notes:
246 # The .nc files are actually processed by a python script which executes the
247 # compiler and generates a .cc file that is empty on success, or will have a
248 # series of #error lines on failure, and a set of trivially passing gunit
249 # TEST() functions on success. This allows us to fail at the compile step when
250 # something goes wrong, and know during the unittest run that the test was at
251 # least processed when things go right.
252
253 if (enable_nocompile_tests) {
254   import("//build/config/c++/c++.gni")
255   import("//build/config/sysroot.gni")
256   import("//testing/test.gni")
257
258   if (is_mac) {
259     import("//build/config/mac/mac_sdk.gni")
260   }
261
262   template("nocompile_test") {
263     nocompile_target = target_name + "_run_nocompile"
264
265     action_foreach(nocompile_target) {
266       testonly = true
267       script = "//tools/nocompile/driver.py"
268       sources = invoker.sources
269       deps = invoker.deps
270       if (defined(invoker.public_deps)) {
271         public_deps = invoker.public_deps
272       }
273
274       result_path = "$target_gen_dir/{{source_name_part}}_nc.cc"
275       outputs = [ result_path ]
276       rebased_result_path = rebase_path(result_path, root_build_dir)
277       if (is_win) {
278         if (host_os == "win") {
279           cxx = "clang-cl.exe"
280           nulldevice = "nul"
281         } else {
282           cxx = "clang-cl"
283
284           # Unfortunately, clang-cl always wants to suffix the output file name
285           # with ".obj", and /dev/null.obj is not a valid file. As a bit of a
286           # hack, simply use the path to the generated .cc file, knowing:
287           # - that clang-cl will append ".obj" to the filename, so it will never
288           #   clash.
289           # - except when the nocompile test unexpectedly passes, the output
290           #   file will never actually be written.
291           nulldevice = rebased_result_path
292         }
293       } else {
294         cxx = "clang++"
295       }
296
297       depfile = "${result_path}.d"
298
299       args = []
300       if (is_win) {
301         args += [
302           "--depfile",
303           rebased_result_path + ".d",
304         ]
305       }
306       args += [
307         rebase_path("$clang_base_path/bin/$cxx", root_build_dir),
308         "4",  # number of compilers to invoke in parallel.
309         "{{source}}",
310         rebased_result_path,
311         "--",
312         "-Werror",
313         "-Wfatal-errors",
314         "-Wthread-safety",
315         "-I" + rebase_path("//", root_build_dir),
316         "-I" + rebase_path("//third_party/abseil-cpp/", root_build_dir),
317         "-I" + rebase_path("//buildtools/third_party/libc++/", root_build_dir),
318         "-I" + rebase_path(root_gen_dir, root_build_dir),
319
320         # TODO(https://crbug.com/989932): Track build/config/compiler/BUILD.gn
321         "-Wno-implicit-int-float-conversion",
322       ]
323       if (is_win) {
324         # On Windows we fall back to using system headers from a sysroot from
325         # depot_tools. This is negotiated by python scripts and the result is
326         # available in //build/toolchain/win/win_toolchain_data.gni. From there
327         # we get the `include_flags_imsvc` which point to the system headers.
328         if (host_cpu == "x86") {
329           win_toolchain_data = win_toolchain_data_x86
330         } else if (host_cpu == "x64") {
331           win_toolchain_data = win_toolchain_data_x64
332         } else if (host_cpu == "arm64") {
333           win_toolchain_data = win_toolchain_data_arm64
334         } else {
335           error("Unsupported host_cpu, add it to win_toolchain_data.gni")
336         }
337         args += win_toolchain_data.include_flags_imsvc_list
338
339         args += [
340           "/W4",
341           "-Wno-unused-parameter",
342           "-I" + rebase_path("$libcxx_prefix/include", root_build_dir),
343           "/std:c++20",
344           "/showIncludes",
345           "/Fo" + nulldevice,
346           "/c",
347           "/Tp",
348         ]
349       } else {
350         args += [
351           "-Wall",
352           "-nostdinc++",
353           "-isystem" + rebase_path("$libcxx_prefix/include", root_build_dir),
354           "-isystem" + rebase_path("$libcxxabi_prefix/include", root_build_dir),
355           "-std=c++20",
356           "-MMD",
357           "-MF",
358           rebased_result_path + ".d",
359           "-MT",
360           rebased_result_path,
361           "-o",
362           "/dev/null",
363           "-c",
364           "-x",
365           "c++",
366         ]
367       }
368       args += [ "{{source}}" ]
369
370       if (is_mac && host_os != "mac") {
371         args += [
372           "--target=x86_64-apple-macos",
373           "-mmacos-version-min=$mac_deployment_target",
374         ]
375       }
376
377       # Iterate over any extra include dirs and append them to the command line.
378       if (defined(invoker.include_dirs)) {
379         foreach(include_dir, invoker.include_dirs) {
380           args += [ "-I" + rebase_path(include_dir, root_build_dir) ]
381         }
382       }
383
384       if (sysroot != "") {
385         assert(!is_win)
386         sysroot_path = rebase_path(sysroot, root_build_dir)
387         args += [
388           "--sysroot",
389           sysroot_path,
390         ]
391       }
392
393       if (!is_nacl) {
394         args += [
395           # TODO(crbug.com/1343975) Evaluate and possibly enable.
396           "-Wno-deprecated-builtins",
397         ]
398       }
399     }
400
401     test(target_name) {
402       deps = invoker.deps + [ ":$nocompile_target" ]
403       sources = get_target_outputs(":$nocompile_target")
404       forward_variables_from(invoker, [ "bundle_deps" ])
405     }
406   }
407 }