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")
15
16template("rust_bindgen") {
17  assert(defined(invoker.header),
18         "Must specify the C header file to make bindings for.")
19  _target_name = target_name
20  if (defined(invoker.visibility)) {
21    _visibility = invoker.visibility
22  }
23  _testonly = false
24  if (defined(invoker.testonly)) {
25    _testonly = invoker.testonly
26  }
27  _deps = []
28  if (defined(invoker.deps)) {
29    _deps += invoker.deps
30  }
31  action(_target_name) {
32    sources = [ invoker.header ]
33    configs = default_compiler_configs
34    if (defined(invoker.configs)) {
35      configs += invoker.configs
36    }
37    testonly = _testonly
38    if (defined(_visibility)) {
39      visibility = _visibility
40    }
41
42    if (defined(invoker.subsystem_name) && defined(invoker.part_name)) {
43      subsystem_name = invoker.subsystem_name
44      part_name = invoker.part_name
45    } else if (defined(invoker.part_name)) {
46      part_name = invoker.part_name
47      _part_subsystem_info_file =
48          "$root_build_dir/build_configs/parts_info/part_subsystem.json"
49      _arguments = [
50        "--part-name",
51        part_name,
52        "--part-subsystem-info-file",
53        rebase_path(_part_subsystem_info_file, root_build_dir),
54      ]
55      get_subsystem_script = "//build/templates/common/get_subsystem_name.py"
56      subsystem_name =
57          exec_script(get_subsystem_script, _arguments, "trim string")
58    } else if (defined(invoker.subsystem_name)) {
59      subsystem_name = invoker.subsystem_name
60      part_name = subsystem_name
61    } else {
62      subsystem_name = "build"
63      part_name = "build_framework"
64    }
65
66    ohos_bindgen_target =
67        "//third_party/rust/crates/bindgen/bindgen-cli:bindgen($host_toolchain)"
68    ohos_bindgen_obj_dir = get_label_info(ohos_bindgen_target, "root_out_dir")
69    ohos_bindgen_executable =
70        "${ohos_bindgen_obj_dir}/${subsystem_name}/${part_name}/bindgen"
71    llvm_config_path = "$default_clang_base_path/bin/llvm-config"
72    clang_path = "$default_clang_base_path/bin/clang"
73
74    output_dir = "$target_gen_dir"
75    out_gen_rs = "$output_dir/${target_name}.rs"
76    script = rebase_path("//build/templates/rust/rust_bindgen.py")
77    inputs = [ ohos_bindgen_executable ]
78    depfile = "$target_out_dir/${target_name}.d"
79    outputs = [ out_gen_rs ]
80    deps = [ ohos_bindgen_target ]
81
82    deps += _deps
83    args = [
84      "--exe",
85      rebase_path(ohos_bindgen_executable),
86      "--llvm-config-path",
87      rebase_path(llvm_config_path),
88      "--clang-path",
89      rebase_path(clang_path),
90      "--header",
91      rebase_path(invoker.header, root_build_dir),
92      "--ld-library-path",
93      rebase_path(clang_base_path + "/lib", root_build_dir),
94      "--depfile",
95      rebase_path(depfile, root_build_dir),
96      "--output",
97      rebase_path(out_gen_rs, root_build_dir),
98    ]
99    args += [
100      "--",
101      "{{cflags}}",
102      "{{cflags_c}}",
103      "{{defines}}",
104      "{{include_dirs}}",
105      "-fvisibility=default",
106      "-fparse-all-comments",
107    ]
108    if (defined(invoker.enable_c_plus_plus) &&
109        invoker.enable_c_plus_plus == true) {
110      args += [ "-x" ]
111      args += [ "c++" ]
112    }
113  }
114}
115