[M120 Migration] Implement ewk_view_is_video_playing api
[platform/framework/web/chromium-efl.git] / build / rust / rust_target.gni
1 # Copyright 2021 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 import("//build/config/rust.gni")
6 import("//build/rust/rust_unit_test.gni")
7
8 # The //build directory is re-used for non-Chromium products. We do not support
9 # cxx bindings in such contexts, because //third_party may be missing.
10 if (build_with_chromium) {
11   import("//third_party/rust/cxx/chromium_integration/rust_cxx.gni")
12 }
13
14 # Creates a Rust target (rlib, executable, proc macro etc.) with ability to
15 # understand some handy variables such as "edition" and "features" and also to
16 # build any associated unit tests.
17 #
18 # Normally, you should not use this directly. Use either
19 # - cargo_crate.gni - for 3p crates only
20 # - rust_static_library.gni - for 1p Rust code
21 #
22 # Because the common use of this is rust_static_library, all the documentation
23 # for the supported options is given in rust_static_library.gni. Please refer
24 # over there.
25 #
26 # If you're using rust_target directly, you will also need to specify:
27 # target_type executable, rust_library etc. per GN norms
28 #
29 # There is one area where this differs from `rust_static_library`: configs.
30 # Here, you must specify `executable_configs` or `library_configs` depending on
31 # the type of thing you're generating. This is so that different defaults can
32 # be provided.
33
34 template("rust_target") {
35   _target_name = target_name
36   _crate_name = target_name
37   if (defined(invoker.crate_name)) {
38     _crate_name = invoker.crate_name
39   }
40   _generate_crate_root =
41       defined(invoker.generate_crate_root) && invoker.generate_crate_root
42
43   # Only one of `crate_root` or `generate_crate_root` can be specified, or
44   # neither.
45   assert(!defined(invoker.crate_root) || !_generate_crate_root)
46
47   if (defined(invoker.output_dir) && invoker.output_dir != "") {
48     # This is where the build target (.exe, .rlib, etc) goes.
49     _output_dir = invoker.output_dir
50   }
51
52   # This is where the OUT_DIR environment variable points to when running a
53   # build script and when compiling the build target, for consuming generated
54   # files.
55   _env_out_dir = "$target_gen_dir/$_target_name"
56
57   _allow_unsafe = false
58   if (defined(invoker.allow_unsafe)) {
59     _allow_unsafe = invoker.allow_unsafe
60   }
61
62   if (_generate_crate_root) {
63     generated_file("${_target_name}_crate_root") {
64       outputs = [ "${target_gen_dir}/${target_name}.rs" ]
65       contents = [
66         "// Generated crate root for ${_target_name}.",
67         "// @generated",
68         "",
69       ]
70       foreach(rs, invoker.sources) {
71         rs_path_from_root = rebase_path(rs, target_gen_dir)
72         contents += [ "#[path = \"${rs_path_from_root}\"]" ]
73
74         # Drop the file extension from the module name.
75         rs_modname = string_replace(rs, ".rs", "")
76
77         # Replace invalid "/" chars in the source file path.
78         rs_modname = string_replace(rs_modname, "/", "_")
79
80         # Since source files are specified relative to the BUILD.gn they may
81         # also have ".." path components.
82         rs_modname = string_replace(rs_modname, "..", "dotdot")
83         contents += [
84           "mod ${rs_modname};",
85           "",
86         ]
87       }
88     }
89     _generated_crate_root = get_target_outputs(":${_target_name}_crate_root")
90     _crate_root = _generated_crate_root[0]
91   } else if (defined(invoker.crate_root)) {
92     _crate_root = invoker.crate_root
93   } else if (invoker.target_type == "executable") {
94     _crate_root = "src/main.rs"
95   } else {
96     _crate_root = "src/lib.rs"
97   }
98
99   _testonly = false
100   if (defined(invoker.testonly)) {
101     _testonly = invoker.testonly
102   }
103   if (defined(invoker.visibility)) {
104     _visibility = invoker.visibility
105   }
106
107   _rustflags = []
108   if (defined(invoker.rustflags)) {
109     _rustflags += invoker.rustflags
110   }
111   if (defined(invoker.features)) {
112     foreach(i, invoker.features) {
113       _rustflags += [ "--cfg=feature=\"${i}\"" ]
114     }
115   }
116   _edition = "2021"
117   if (defined(invoker.edition)) {
118     _edition = invoker.edition
119   }
120
121   assert(!defined(configs))
122   _configs = [ "//build/rust:edition_${_edition}" ]
123   _test_configs = []
124   if (invoker.target_type == "executable") {
125     _configs += invoker.executable_configs
126   } else if (invoker.target_type == "rust_proc_macro") {
127     _configs += invoker.proc_macro_configs
128     _test_configs += [ "//build/rust:proc_macro_extern" ]
129   } else if (invoker.target_type == "shared_library") {
130     _configs += invoker.shared_library_configs
131   } else {
132     _configs += invoker.library_configs
133   }
134
135   if (invoker.target_type == "rust_proc_macro") {
136     _main_target_suffix = "${target_name}__proc_macro"
137   } else {
138     _main_target_suffix = "__rlib"
139   }
140
141   _deps = []
142   if (defined(invoker.deps)) {
143     _deps += invoker.deps
144   }
145   _public_deps = []
146   if (defined(invoker.public_deps)) {
147     _public_deps += invoker.public_deps
148   }
149   if (defined(invoker.aliased_deps)) {
150     _aliased_deps = invoker.aliased_deps
151   } else {
152     _aliased_deps = {
153     }
154   }
155
156   _is_data_dep = defined(invoker.is_data_dep) && invoker.is_data_dep
157
158   _build_unit_tests = false
159   if (defined(invoker.build_native_rust_unit_tests)) {
160     _build_unit_tests =
161         invoker.build_native_rust_unit_tests && can_build_rust_unit_tests
162   }
163
164   # Declares that the Rust crate generates bindings between C++ and Rust via the
165   # Cxx crate. It may generate C++ headers and/or use the cxx crate macros to
166   # generate Rust code internally, depending on what bindings are declared. If
167   # set, it's a set of rust files that include Cxx bindings declarations.
168   _cxx_bindings = []
169   assert(!defined(invoker.cxx_bindings) || enable_cxx,
170          "cxx bindings are not supported when building rust targets " +
171              "outside the Chromium build.")
172   if (defined(invoker.cxx_bindings)) {
173     _cxx_bindings = invoker.cxx_bindings
174   }
175   _rustenv = [ "OUT_DIR=" +
176                rebase_path(_env_out_dir, get_path_info(_crate_root, "dir")) ]
177   if (defined(invoker.rustenv)) {
178     _rustenv += invoker.rustenv
179   }
180
181   # We require that all source files are listed, even though this is
182   # not a requirement for rustc. The reason is to ensure that tools
183   # such as `gn deps` give the correct answer, and thus we trigger
184   # the right test suites etc. on code change.
185   # TODO(crbug.com/1256930) - verify this is correct
186   assert(defined(invoker.sources), "sources must be listed")
187
188   if (invoker.target_type == "rust_proc_macro" &&
189       !toolchain_for_rust_host_build_tools) {
190     # Redirect to the proc macro toolchain, which uses prebuilt stdlib libraries
191     # that are not built with panic=abort.
192     group(_target_name) {
193       testonly = _testonly
194       if (defined(_visibility)) {
195         visibility = _visibility
196       }
197       public_deps =
198           [ ":${_target_name}${_main_target_suffix}($rust_macro_toolchain)" ]
199     }
200
201     not_needed(invoker, "*")
202     not_needed([
203                  "_allow_unsafe",
204                  "_build_unit_tests",
205                  "_crate_root",
206                  "_crate_name",
207                  "_cxx_bindings",
208                  "_deps",
209                  "_aliased_deps",
210                  "_is_data_dep",
211                  "_rustc_metadata",
212                  "_out_dir",
213                  "_public_deps",
214                  "_rustenv",
215                  "_rustflags",
216                  "_support_use_from_cpp",
217                  "_testonly",
218                  "_visibility",
219                ])
220   } else {
221     _rustc_metadata = ""
222     if (defined(invoker.rustc_metadata)) {
223       _rustc_metadata = invoker.rustc_metadata
224     }
225
226     # Add a metadata-influenced suffix to the output name for libraries only.
227     _output_suffix = ""
228     if (invoker.target_type == "rust_library" && _rustc_metadata != "") {
229       _output_suffix = "-${_rustc_metadata}"
230     }
231
232     group(_target_name) {
233       testonly = _testonly
234       if (defined(_visibility)) {
235         visibility = _visibility
236       }
237
238       # Both the C++ bindings (if present) and the Rust crate should be treated
239       # like direct dependencies, so we expose them both in public_deps.
240       public_deps = [ ":${_target_name}${_main_target_suffix}" ]
241
242       # TODO(danakj): This would not be needed if we stopped forwarding through
243       # a group in the common (non-procmacro) case.
244       if (_is_data_dep) {
245         data_deps = [ ":${_target_name}${_main_target_suffix}" ]
246       }
247
248       if (_cxx_bindings != []) {
249         public_deps += [ ":${_target_name}_cxx_generated" ]
250
251         # Additionally, C++ bindings generated by Cxx can include C++ types
252         # that come from the Cxx library, such as `rust::Str`. So any C++
253         # target that depends on a rust target directly may need access to Cxx
254         # as well, which means it must appear in public_deps.
255         public_deps += [ "//build/rust:cxx_cppdeps" ]
256       } else if (!defined(invoker.no_std) || !invoker.no_std) {
257         # If C++ depends on and links in the library, we need to make sure C++
258         # links in the Rust stdlib. This is orthogonal to if the library exports
259         # bindings for C++ to use.
260         deps = [ "//build/rust/std:stdlib_for_clang" ]
261       }
262     }
263
264     _rust_deps = _deps
265     _rust_aliased_deps = _aliased_deps
266     _rust_public_deps = _public_deps
267     _cxx_deps = _deps
268
269     # The Rust target (and unit tests) need the Cxx crate when using it to
270     # generate bindings.
271     if (_cxx_bindings != []) {
272       _rust_deps += [ "//build/rust:cxx_rustdeps" ]
273
274       # C++ targets can depend on the Rust target from the BUILD.gn file to
275       # access the headers generated from it
276       _rust_public_deps += [ ":${_target_name}_cxx_generated" ]
277     }
278
279     if (!defined(invoker.no_std) || !invoker.no_std) {
280       _rust_deps += [ "//build/rust/std:stdlib_for_rustc" ]
281     }
282
283     # You must go through the groups above to get to these targets.
284     _visibility = []
285     _visibility = [ ":${_target_name}" ]
286
287     if (_build_unit_tests) {
288       _unit_test_target = "${_target_name}_unittests"
289       if (defined(invoker.unit_test_target)) {
290         _unit_test_target = invoker.unit_test_target
291       }
292
293       rust_unit_test(_unit_test_target) {
294         testonly = true
295         crate_root = _crate_root
296         sources = invoker.sources + [ crate_root ]
297         rustflags = _rustflags
298         env_out_dir = _env_out_dir
299         if (defined(invoker.unit_test_output_dir)) {
300           output_dir = invoker.unit_test_output_dir
301         }
302         deps = _rust_deps + _public_deps
303         aliased_deps = _rust_aliased_deps
304         public_deps = [ ":${_target_name}" ]
305         if (defined(invoker.test_deps)) {
306           deps += invoker.test_deps
307         }
308         inputs = []
309         if (defined(invoker.inputs)) {
310           inputs += invoker.inputs
311         }
312         if (defined(invoker.test_inputs)) {
313           inputs += invoker.test_inputs
314         }
315         if (defined(invoker.executable_configs)) {
316           configs = []
317           configs += invoker.executable_configs
318         }
319         configs += _test_configs
320         rustenv = _rustenv
321
322         if (!_allow_unsafe) {
323           configs += [ "//build/rust:forbid_unsafe" ]
324         }
325       }
326     } else {
327       not_needed([
328                    "_crate_root",
329                    "_crate_name",
330                    "_rustc_metadata",
331                    "_test_configs",
332                  ])
333       not_needed(invoker, [ "executable_configs" ])
334     }
335
336     target(invoker.target_type, "${_target_name}${_main_target_suffix}") {
337       forward_variables_from(invoker,
338                              "*",
339                              TESTONLY_AND_VISIBILITY + [
340                                    "features",
341                                    "deps",
342                                    "aliased_deps",
343                                    "public_deps",
344                                    "rustflags",
345                                    "rustenv",
346                                    "configs",
347                                    "unit_test_output_dir",
348                                    "unit_test_target",
349                                    "test_inputs",
350                                  ])
351
352       testonly = _testonly
353       visibility = _visibility
354       crate_name = _crate_name
355       crate_root = _crate_root
356       configs = []
357       configs = _configs
358       deps = _rust_deps
359       aliased_deps = _rust_aliased_deps
360       public_deps = _rust_public_deps
361       rustflags = _rustflags
362       if (_rustc_metadata != "") {
363         rustflags += [ "-Cmetadata=${_rustc_metadata}" ]
364       }
365       rustenv = _rustenv
366
367       if (_generate_crate_root) {
368         deps += [ ":${_target_name}_crate_root" ]
369         sources += [ _crate_root ]
370       }
371
372       # The Rust tool() declarations, like C++ ones, use the output_name and
373       # output_dir, so that GN targets can override these if needed. Here we
374       # give them their default values, or allow them to be overridden.
375       if (defined(_output_dir)) {
376         output_dir = _output_dir
377       }
378       if (!defined(output_name) || output_name == "") {
379         output_name = "${crate_name}${_output_suffix}"
380       }
381
382       if (!_allow_unsafe) {
383         configs += [ "//build/rust:forbid_unsafe" ]
384       }
385     }
386
387     if (_cxx_bindings != []) {
388       rust_cxx("${_target_name}_cxx_generated") {
389         testonly = _testonly
390         visibility = [ ":${_target_name}${_main_target_suffix}" ]
391         if (defined(_visibility)) {
392           visibility += _visibility
393         }
394         sources = _cxx_bindings
395         deps = _cxx_deps + _public_deps
396         configs = _configs
397
398         if (is_component_build) {
399           # In a component_build the cxx bindings may be linked into a shared
400           # library at any point up the dependency tree, so always export.
401           export_symbols = true
402         } else if (invoker.target_type == "shared_library") {
403           export_symbols = true
404         } else {
405           export_symbols = false
406         }
407       }
408     } else {
409       not_needed([ "_cxx_deps" ])
410     }
411   }
412 }