1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (c) 2023 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import tempfile 17import re 18import subprocess 19import io 20import argparse 21import os 22import sys 23import stat 24 25 26sys.path.append( 27 os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))) 28from scripts.util import build_utils 29 30 31def host_triple(rustc_path): 32 known_vars = dict() 33 args = [rustc_path, "-vV"] 34 proc = subprocess.Popen(args, stdout=subprocess.PIPE) 35 for lines in io.TextIOWrapper(proc.stdout, encoding="utf-8"): 36 rustc_version = re.compile(r"(\w+): (.*)") 37 match = rustc_version.match(lines.rstrip()) 38 if match: 39 known_vars[match.group(1)] = match.group(2) 40 return known_vars.get("host") 41 42 43def run_build_script(args, env, tempdir): 44 process = subprocess.run([os.path.abspath(args.build_script)], 45 env=env, 46 cwd=args.src_dir, 47 encoding='utf8', 48 capture_output=True) 49 50 if process.stderr.rstrip(): 51 print(process.stderr.rstrip(), file=sys.stderr) 52 process.check_returncode() 53 54 flags = "" 55 for line in process.stdout.split("\n"): 56 rustc_cfg = re.compile("cargo:rustc-cfg=(.*)") 57 match = rustc_cfg.match(line.rstrip()) 58 if match: 59 flags = "%s--cfg\n%s\n" % (flags, match.group(1)) 60 61 with build_utils.atomic_output(args.output) as output: 62 output.write(flags.encode("utf-8")) 63 64 if args.generated_files: 65 for generated_file in args.generated_files: 66 input_path = os.path.join(tempdir, generated_file) 67 output_path = os.path.join(args.out_dir, generated_file) 68 out_dir = os.path.dirname(output_path) 69 if not os.path.exists(out_dir): 70 os.makedirs(out_dir, exist_ok=True) 71 with os.fdopen(os.open(input_path, 72 os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 73 'rb') as inputs: 74 with build_utils.atomic_output(output_path) as output: 75 content = inputs.read() 76 output.write(content) 77 78 79def set_env(args, rustc_path, tempdir): 80 rustc_abs_path = os.path.abspath(rustc_path) 81 src_dir_abs_path = os.path.abspath(args.src_dir) 82 83 env = { 84 "RUSTC": rustc_abs_path, 85 "HOST": host_triple(rustc_abs_path), 86 "CARGO_MANIFEST_DIR": src_dir_abs_path, 87 "OUT_DIR": tempdir, 88 } 89 if args.target: 90 env["TARGET"] = args.target 91 else: 92 env["TARGET"] = env.get("HOST") 93 94 env["CARGO_CFG_TARGET_ARCH"], *_ = env.get("TARGET").split("-") 95 if args.env: 96 env.update({key: val for key, val in (e.split('=') for e in args.env)}) 97 if args.features: 98 for feature in args.features: 99 feature_name = feature.replace("-", "_").upper() 100 env[f"CARGO_FEATURE_{feature_name}"] = "1" 101 102 rust_log = os.environ.get("RUST_LOG") 103 rust_bt = os.environ.get("RUST_BACKTRACE") 104 105 if rust_log: 106 env["RUST_LOG"] = rust_log 107 if rust_bt: 108 env["RUST_BACKTRACE"] = rust_bt 109 110 return env 111 112 113def main(): 114 parser = argparse.ArgumentParser() 115 parser.add_argument('--build-script', 116 required=True, 117 help='build script needed to run') 118 parser.add_argument('--target', help='rust target triple') 119 parser.add_argument('--features', help='features', nargs='+') 120 parser.add_argument('--env', help='environment variable', nargs='+') 121 parser.add_argument('--output', 122 required=True, 123 help='where to write output rustc flags') 124 parser.add_argument('--rust-prefix', required=True, 125 help='rust path prefix') 126 parser.add_argument('--generated-files', nargs='+', 127 help='any generated file') 128 parser.add_argument('--out-dir', required=True, help='ohos target out dir') 129 parser.add_argument('--src-dir', required=True, 130 help='ohos target source dir') 131 132 args = parser.parse_args() 133 rustc_path = os.path.join(args.rust_prefix, "rustc") 134 with tempfile.TemporaryDirectory() as tempdir: 135 env = set_env(args, rustc_path, tempdir) 136 run_build_script(args, env, tempdir) 137 138 139if __name__ == '__main__': 140 sys.exit(main()) 141