1# Copyright (c) 2023 Huawei Device Co., Ltd.
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
5#
6#     http://www.apache.org/licenses/LICENSE-2.0
7#
8# Unless required by applicable law or agreed to in writing, software
9# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14import("//build/config/clang/clang.gni")
15import("//build/config/ohos/config.gni")
16import("//build/ohos/notice/notice.gni")
17import("//build/ohos_var.gni")
18import("//build/templates/common/check_target.gni")
19import("//build/templates/common/collect_target.gni")
20import("//build/templates/metadata/module_info.gni")
21
22template("ohos_rust_library") {
23  assert(!defined(invoker.output_dir),
24         "output_dir is not allowed to be defined.")
25  _test_target = defined(invoker.testonly) && invoker.testonly
26  if (defined(invoker.subsystem_name) && defined(invoker.part_name)) {
27    subsystem_name = invoker.subsystem_name
28    part_name = invoker.part_name
29  } else if (defined(invoker.part_name)) {
30    part_name = invoker.part_name
31    _part_subsystem_info_file =
32        "$root_build_dir/build_configs/parts_info/part_subsystem.json"
33    _arguments = [
34      "--part-name",
35      part_name,
36      "--part-subsystem-info-file",
37      rebase_path(_part_subsystem_info_file, root_build_dir),
38    ]
39    get_subsystem_script = "//build/templates/common/get_subsystem_name.py"
40    subsystem_name =
41        exec_script(get_subsystem_script, _arguments, "trim string")
42    if (is_use_check_deps && !_test_target) {
43      skip_check_subsystem = true
44    }
45  } else if (defined(invoker.subsystem_name)) {
46    subsystem_name = invoker.subsystem_name
47    part_name = subsystem_name
48  } else {
49    subsystem_name = "build"
50    part_name = "build_framework"
51  }
52  assert(subsystem_name != "")
53  assert(part_name != "")
54  if (is_use_check_deps && !_test_target) {
55    _check_target = "${target_name}__check"
56    target_path = get_label_info(":${target_name}", "label_no_toolchain")
57    check_target(_check_target) {
58      module_deps = []
59      if (defined(invoker.deps)) {
60        module_deps += invoker.deps
61      }
62      if (defined(invoker.public_deps)) {
63        module_deps += invoker.public_deps
64      }
65      if (defined(invoker.external_deps)) {
66        module_ex_deps = invoker.external_deps
67      }
68    }
69  }
70
71  if (check_deps) {
72    deps_data = {
73    }
74    module_label = get_label_info(":${target_name}", "label_with_toolchain")
75    module_deps = []
76    if (defined(invoker.deps)) {
77      foreach(dep, invoker.deps) {
78        module_deps += [ get_label_info(dep, "label_no_toolchain") ]
79      }
80    }
81    module_ex_deps = []
82    if (defined(invoker.external_deps) && invoker.external_deps != []) {
83      module_ex_deps = invoker.external_deps
84    }
85    deps_data = {
86      part_name = part_name
87      module_label = module_label
88      deps = module_deps
89      external_deps = module_ex_deps
90    }
91    write_file("${root_out_dir}/deps_files/${part_name}__${target_name}.json",
92               deps_data,
93               "json")
94  }
95
96  if (is_standard_system) {
97    output_dir = "${root_out_dir}/${subsystem_name}/${part_name}"
98  } else {
99    output_dir = "${root_out_dir}"
100  }
101
102  if (!_test_target) {
103    module_label = get_label_info(":${target_name}", "label_with_toolchain")
104    _collect_target = "${target_name}__collect"
105    collect_module_target(_collect_target) {
106      forward_variables_from(invoker, [ "install_images" ])
107    }
108
109    _notice_target = "${target_name}__notice"
110    _main_target_name = target_name
111    collect_notice(_notice_target) {
112      forward_variables_from(invoker,
113                             [
114                               "testonly",
115                               "license_as_sources",
116                               "license_file",
117                             ])
118      module_type = "rust_library"
119
120      module_name = _main_target_name
121      if (defined(invoker.crate_name)) {
122        module_name = invoker.crate_name
123      }
124      module_source_dir = get_label_info(":${_main_target_name}", "dir")
125    }
126  }
127
128  target_label = get_label_info(":${target_name}", "label_with_toolchain")
129  target_toolchain = get_label_info(target_label, "toolchain")
130
131  if (target_toolchain == "${current_toolchain}") {
132    ohos_module_name = target_name
133    _module_info_target = "${target_name}_info"
134    generate_module_info(_module_info_target) {
135      module_name = ohos_module_name
136      module_type = "lib"
137      module_source_dir = "$root_out_dir"
138      if (defined(output_dir)) {
139        module_source_dir = output_dir
140      }
141
142      module_install_name = ohos_module_name
143      if (defined(invoker.output_name)) {
144        module_install_name = invoker.output_name
145      }
146
147      module_install_images = [ "system" ]
148      if (defined(invoker.install_images)) {
149        module_install_images = []
150        module_install_images += invoker.install_images
151      }
152
153      module_output_extension = shlib_extension
154      if (defined(invoker.module_output_extension)) {
155        module_output_extension = invoker.module_output_extension
156      }
157
158      install_enable = true
159      if (defined(invoker.install_enable)) {
160        install_enable = invoker.install_enable
161      }
162
163      if (defined(invoker.module_install_dir)) {
164        module_install_dir = invoker.module_install_dir
165      }
166
167      if (defined(invoker.relative_install_dir)) {
168        relative_install_dir = invoker.relative_install_dir
169      }
170
171      if (defined(invoker.symlink_target_name)) {
172        symlink_target_name = invoker.symlink_target_name
173      }
174
175      if (defined(invoker.output_prefix_override)) {
176        output_prefix_override = invoker.output_prefix_override
177      }
178      notice = "$target_out_dir/$ohos_module_name.notice.txt"
179    }
180  }
181
182  rust_library("${target_name}") {
183    forward_variables_from(invoker,
184                           "*",
185                           [
186                             "configs",
187                             "remove_configs",
188                             "no_default_deps",
189                             "install_images",
190                             "module_install_dir",
191                             "relative_install_dir",
192                             "symlink_target_name",
193                             "output_dir",
194                             "install_enable",
195                             "version_script",
196                             "license_file",
197                             "license_as_sources",
198                             "use_exceptions",
199                             "stl",
200
201                             # Sanitizer variables
202                             "sanitize",
203                           ])
204    output_dir = output_dir
205
206    if (!defined(inputs)) {
207      inputs = []
208    }
209
210    if (!defined(ldflags)) {
211      ldflags = []
212    }
213
214    if (defined(invoker.configs)) {
215      configs += invoker.configs
216    }
217    if (defined(invoker.remove_configs)) {
218      configs -= invoker.remove_configs
219    }
220
221    if (!defined(output_name)) {
222      output_name = target_name
223    }
224
225    if (defined(invoker.no_default_deps)) {
226      no_default_deps = invoker.no_default_deps
227    }
228
229    if (!defined(ldflags)) {
230      ldflags = []
231    }
232    if (!defined(libs)) {
233      libs = []
234    }
235    if (!defined(cflags_cc)) {
236      cflags_cc = []
237    }
238    if (!defined(deps)) {
239      deps = []
240    }
241    if (is_use_check_deps && !_test_target) {
242      deps += [ ":$_check_target" ]
243    }
244    if (target_toolchain == "${current_toolchain}" && !skip_gen_module_info) {
245      deps += [ ":$_module_info_target" ]
246    }
247
248    if (is_ohos) {
249      if (defined(invoker.stl)) {
250        cflags_cc += [
251          "-nostdinc++",
252          "-I" + rebase_path(
253                  "${}toolchains_dir/${host_platform_dir}/llvm_ndk/include/c++/v1",
254                  root_build_dir),
255        ]
256        ldflags += [
257          "-nostdlib++",
258          "-L" + rebase_path("${clang_stl_path}/${abi_target}/c++",
259                             root_build_dir),
260        ]
261
262        libs += [ invoker.stl ]
263      } else {
264        if (current_cpu == "arm" || current_cpu == "arm64") {
265          libs += [ "unwind" ]
266        }
267        ldflags += [ "-L" + rebase_path("${clang_stl_path}/${abi_target}/c++",
268                                        root_build_dir) ]
269
270        libs += [ "c++" ]
271      }
272    }
273
274    if (defined(visibility) && visibility != []) {
275      visibility += [ "//build/*" ]
276      if (defined(build_ext_path)) {
277        visibility += [ "${build_ext_path}/*" ]
278      }
279    }
280
281    if (!_test_target) {
282      deps += [
283        ":$_notice_target",
284        ":${_collect_target}",
285      ]
286    }
287    if (!defined(include_dirs)) {
288      include_dirs = []
289    }
290
291    install_module_info = {
292      module_def = target_label
293      module_info_file =
294          rebase_path(get_label_info(module_def, "target_out_dir"),
295                      root_build_dir) + "/${target_name}_module_info.json"
296      subsystem_name = subsystem_name
297      part_name = part_name
298      toolchain = current_toolchain
299      toolchain_out_dir = rebase_path(root_out_dir, root_build_dir)
300    }
301    metadata = {
302      install_modules = [ install_module_info ]
303    }
304    if (defined(is_debug) && !is_debug && enable_debug_components != "") {
305      foreach(component_name, debug_components) {
306        if (part_name == component_name) {
307          configs -= default_opt_configs
308          configs += debug_level_configs
309        }
310      }
311    }
312  }
313}
314