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/templates/rust/rust_template.gni") 15template("ohos_cargo_crate") { 16 orig_target_name = target_name 17 18 _crate_name = orig_target_name 19 if (defined(invoker.crate_name)) { 20 _crate_name = invoker.crate_name 21 } 22 assert(_crate_name != "") 23 24 _rustenv = [] 25 if (defined(invoker.rustenv)) { 26 _rustenv = invoker.rustenv 27 } 28 if (defined(invoker.cargo_pkg_authors)) { 29 _rustenv += [ string_join("", 30 [ 31 "CARGO_PKG_AUTHORS=", 32 invoker.cargo_pkg_authors, 33 ]) ] 34 } 35 if (defined(invoker.cargo_pkg_version)) { 36 _rustenv += [ string_join("", 37 [ 38 "CARGO_PKG_VERSION=", 39 invoker.cargo_pkg_version, 40 ]) ] 41 } 42 if (defined(invoker.cargo_pkg_name)) { 43 _rustenv += [ string_join("", 44 [ 45 "CARGO_PKG_NAME=", 46 invoker.cargo_pkg_name, 47 ]) ] 48 } 49 if (defined(invoker.cargo_pkg_description)) { 50 _rustenv += [ string_join("", 51 [ 52 "CARGO_PKG_DESCRIPTION=", 53 invoker.cargo_pkg_description, 54 ]) ] 55 } 56 57 if (defined(invoker.build_root)) { 58 _epochlabel = "unknown" 59 if (defined(invoker.epoch)) { 60 _tempepoch = string_replace(invoker.epoch, ".", "_") 61 _epochlabel = "${_tempepoch}" 62 } 63 build_script_name = 64 "${_crate_name}_${target_name}_${_epochlabel}_build_script" 65 } 66 _rustflags = [] 67 rust_target(target_name) { 68 forward_variables_from(invoker, 69 "*", 70 [ 71 "testonly", 72 "visibility", 73 "build_root", 74 "build_sources", 75 "build_deps", 76 "build_script_inputs", 77 "build_script_outputs", 78 "output_dir", 79 "target_type", 80 "configs", 81 "rustenv", 82 ]) 83 84 if (defined(invoker.subsystem_name) && defined(invoker.part_name)) { 85 subsystem_name = invoker.subsystem_name 86 part_name = invoker.part_name 87 } else if (defined(invoker.part_name)) { 88 part_name = invoker.part_name 89 _part_subsystem_info_file = 90 "$root_build_dir/build_configs/parts_info/part_subsystem.json" 91 _arguments = [ 92 "--part-name", 93 part_name, 94 "--part-subsystem-info-file", 95 rebase_path(_part_subsystem_info_file, root_build_dir), 96 ] 97 get_subsystem_script = "//build/templates/common/get_subsystem_name.py" 98 subsystem_name = 99 exec_script(get_subsystem_script, _arguments, "trim string") 100 } else if (defined(invoker.subsystem_name)) { 101 subsystem_name = invoker.subsystem_name 102 part_name = subsystem_name 103 } else { 104 subsystem_name = "build" 105 part_name = "build_framework" 106 } 107 assert(subsystem_name != "") 108 assert(part_name != "") 109 110 if (defined(invoker.install_enable)) { 111 install_enable = invoker.install_enable 112 } 113 114 rustenv = _rustenv 115 if (defined(invoker.rustc_lints)) { 116 rustc_lints = invoker.rustc_lints 117 } 118 if (defined(invoker.clippy_lints)) { 119 clippy_lints = invoker.clippy_lints 120 } 121 122 if (!defined(rustc_lints) && !defined(clippy_lints)) { 123 file_path = 124 get_path_info(get_path_info(invoker.sources, "dir"), "abspath") 125 file_path_split = string_split(file_path[0], "/") 126 source_dir_begin = file_path_split[2] 127 128 if (source_dir_begin == "third_party") { 129 _rustflags += allowAllLints 130 } else if (source_dir_begin == "prebuilts") { 131 _rustflags += allowAllLints 132 } else if (source_dir_begin == "vendor" && 133 file_path_split[3] == "open_source") { 134 _rustflags += allowAllLints 135 } else if (source_dir_begin == "vendor") { 136 _rustflags += rustcVendorLints 137 _rustflags += clippyVendorLints 138 } else if (source_dir_begin == "device") { 139 _rustflags += rustcVendorLints 140 _rustflags += clippyVendorLints 141 } else { 142 _rustflags += rustcOhosLints 143 _rustflags += clippyOhosLints 144 } 145 } 146 147 if (defined(rustc_lints)) { 148 if (invoker.rustc_lints == "openharmony") { 149 _rustflags += rustcOhosLints 150 } else if (rustc_lints == "vendor") { 151 _rustflags += rustcVendorLints 152 } else if (rustc_lints == "none") { 153 _rustflags += allowAllLints 154 } 155 } 156 if (defined(clippy_lints)) { 157 if (invoker.clippy_lints == "openharmony") { 158 _rustflags += clippyOhosLints 159 } else if (clippy_lints == "vendor") { 160 _rustflags += clippyVendorLints 161 } else if (clippy_lints == "none") { 162 _rustflags += allowAllLints 163 } 164 } 165 if (!defined(rustflags)) { 166 rustflags = _rustflags 167 } else { 168 rustflags += _rustflags 169 } 170 171 crate_type = "rlib" 172 if (defined(invoker.crate_type)) { 173 crate_type = invoker.crate_type 174 } 175 if (crate_type == "bin") { 176 target_type = "ohos_executable" 177 assert(!defined(invoker.epoch)) 178 } else if (crate_type == "proc-macro") { 179 target_type = "rust_proc_macro" 180 } else { 181 assert(crate_type == "rlib" || crate_type == "dylib") 182 target_type = "ohos_rust_library" 183 } 184 185 if (is_standard_system && defined(invoker.subsystem_name) && 186 defined(invoker.part_name)) { 187 output_dir = "${root_out_dir}/${subsystem_name}/${part_name}" 188 } else { 189 output_dir = "${target_out_dir}/${orig_target_name}" 190 } 191 192 if (defined(invoker.build_root)) { 193 if (!defined(deps)) { 194 deps = [] 195 } 196 if (!defined(sources)) { 197 sources = [] 198 } 199 200 _build_script_target_out_dir = 201 get_label_info(":${build_script_name}_output", "target_out_dir") 202 _build_script_out_dir = "$_build_script_target_out_dir/$orig_target_name" 203 204 flags_file = "$_build_script_out_dir/cargo_flags.rs" 205 rustflags += [ "@" + rebase_path(flags_file, root_build_dir) ] 206 sources += [ flags_file ] 207 if (defined(invoker.build_script_outputs)) { 208 inputs = [] 209 foreach(extra_source, 210 filter_exclude(invoker.build_script_outputs, [ "*.rs" ])) { 211 inputs += [ "$_build_script_out_dir/$extra_source" ] 212 } 213 214 foreach(extra_source, 215 filter_include(invoker.build_script_outputs, [ "*.rs" ])) { 216 sources += [ "$_build_script_out_dir/$extra_source" ] 217 } 218 } 219 deps += [ ":${build_script_name}_output" ] 220 } else { 221 not_needed([ "orig_target_name" ]) 222 } 223 } 224 225 if (defined(invoker.build_root)) { 226 action("${build_script_name}_output") { 227 script = rebase_path("//build/templates/rust/run_build_script.py") 228 build_script_target = ":${build_script_name}($host_toolchain)" 229 deps = [ build_script_target ] 230 231 if (defined(invoker.subsystem_name) && defined(invoker.part_name)) { 232 subsystem_name = invoker.subsystem_name 233 part_name = invoker.part_name 234 } else if (defined(invoker.part_name)) { 235 part_name = invoker.part_name 236 _part_subsystem_info_file = 237 "$root_build_dir/build_configs/parts_info/part_subsystem.json" 238 _arguments = [ 239 "--part-name", 240 part_name, 241 "--part-subsystem-info-file", 242 rebase_path(_part_subsystem_info_file, root_build_dir), 243 ] 244 get_subsystem_script = "//build/templates/common/get_subsystem_name.py" 245 subsystem_name = 246 exec_script(get_subsystem_script, _arguments, "trim string") 247 } else if (defined(invoker.subsystem_name)) { 248 subsystem_name = invoker.subsystem_name 249 part_name = subsystem_name 250 } else { 251 subsystem_name = "build" 252 part_name = "build_framework" 253 } 254 assert(subsystem_name != "") 255 assert(part_name != "") 256 257 if (current_toolchain == host_toolchain) { 258 _build_script_build_dir = "${root_out_dir}" 259 } else if (is_mingw) { 260 _build_script_build_dir = "${root_out_dir}/../clang_x64" 261 } else { 262 if (host_cpu == "arm64") { 263 _build_script_build_dir = "${root_out_dir}/clang_arm64" 264 } else { 265 _build_script_build_dir = "${root_out_dir}/clang_x64" 266 } 267 } 268 269 if (is_standard_system) { 270 _build_script_exe_dir = 271 "${_build_script_build_dir}/${subsystem_name}/${part_name}" 272 } else { 273 _build_script_exe_dir = "${_build_script_build_dir}" 274 } 275 build_script = "$_build_script_exe_dir/${build_script_name}" 276 277 if (is_win) { 278 build_script = "$_build_script_exe_dir/${build_script_name}.exe" 279 } 280 281 _build_script_out_dir = "$target_out_dir/$orig_target_name" 282 flags_file = "$_build_script_out_dir/cargo_flags.rs" 283 284 args = [ 285 "--build-script", 286 rebase_path(build_script, root_build_dir), 287 "--rust-prefix", 288 rebase_path( 289 "//prebuilts/rustc/${host_platform_dir}/${rust_version}/bin", 290 root_build_dir), 291 "--output", 292 rebase_path(flags_file, root_build_dir), 293 "--src-dir", 294 rebase_path(get_path_info(invoker.build_root, "dir"), root_build_dir), 295 "--out-dir", 296 rebase_path(_build_script_out_dir, root_build_dir), 297 ] 298 if (defined(rust_abi_target) && rust_abi_target != "") { 299 args += [ 300 "--target", 301 rust_abi_target, 302 ] 303 } 304 305 if (_rustenv != []) { 306 args += [ "--env" ] 307 args += _rustenv 308 } 309 310 if (defined(invoker.features)) { 311 args += [ "--features" ] 312 args += invoker.features 313 } 314 outputs = [ flags_file ] 315 inputs = [ build_script ] 316 if (defined(invoker.build_script_outputs)) { 317 foreach(generated_file, invoker.build_script_outputs) { 318 outputs += [ "$_build_script_out_dir/$generated_file" ] 319 } 320 args += [ "--generated-files" ] 321 args += invoker.build_script_outputs 322 } 323 324 if (defined(invoker.build_script_inputs)) { 325 inputs += invoker.build_script_inputs 326 } 327 } 328 329 rust_target(build_script_name) { 330 target_type = "ohos_executable" 331 sources = invoker.build_sources 332 crate_root = invoker.build_root 333 if (defined(invoker.build_deps)) { 334 deps = invoker.build_deps 335 } 336 rustenv = _rustenv 337 forward_variables_from(invoker, 338 [ 339 "features", 340 "edition", 341 "rustflags", 342 "subsystem_name", 343 "part_name", 344 ]) 345 } 346 } 347} 348