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 proc.wait() 41 return known_vars.get("host") 42 43 44def run_build_script(args, env, tempdir): 45 process = subprocess.run([os.path.abspath(args.build_script)], 46 env=env, 47 cwd=args.src_dir, 48 encoding='utf8', 49 capture_output=True) 50 51 if process.stderr.rstrip(): 52 print(process.stderr.rstrip(), file=sys.stderr) 53 process.check_returncode() 54 55 flags = "" 56 for line in process.stdout.split("\n"): 57 rustc_cfg = re.compile("cargo:rustc-cfg=(.*)") 58 match = rustc_cfg.match(line.rstrip()) 59 if match: 60 flags = "%s--cfg\n%s\n" % (flags, match.group(1)) 61 62 with build_utils.atomic_output(args.output) as output: 63 output.write(flags.encode("utf-8")) 64 65 if args.generated_files: 66 for generated_file in args.generated_files: 67 input_path = os.path.join(tempdir, generated_file) 68 output_path = os.path.join(args.out_dir, generated_file) 69 out_dir = os.path.dirname(output_path) 70 if not os.path.exists(out_dir): 71 os.makedirs(out_dir, exist_ok=True) 72 with os.fdopen(os.open(input_path, 73 os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 74 'rb') as inputs: 75 with build_utils.atomic_output(output_path) as output: 76 content = inputs.read() 77 output.write(content) 78 79 80def set_env(args, rustc_path, tempdir): 81 rustc_abs_path = os.path.abspath(rustc_path) 82 src_dir_abs_path = os.path.abspath(args.src_dir) 83 84 env = { 85 "RUSTC": rustc_abs_path, 86 "HOST": host_triple(rustc_abs_path), 87 "CARGO_MANIFEST_DIR": src_dir_abs_path, 88 "OUT_DIR": tempdir, 89 } 90 if args.target: 91 env["TARGET"] = args.target 92 else: 93 env["TARGET"] = env.get("HOST") 94 95 env["CARGO_CFG_TARGET_ARCH"], *_ = env.get("TARGET").split("-") 96 if args.env: 97 env.update({key: val for key, val in (e.split('=') for e in args.env)}) 98 if args.features: 99 for feature in args.features: 100 feature_name = feature.replace("-", "_").upper() 101 env[f"CARGO_FEATURE_{feature_name}"] = "1" 102 103 rust_log = os.environ.get("RUST_LOG") 104 rust_bt = os.environ.get("RUST_BACKTRACE") 105 106 if rust_log: 107 env["RUST_LOG"] = rust_log 108 if rust_bt: 109 env["RUST_BACKTRACE"] = rust_bt 110 111 return env 112 113 114def main(): 115 parser = argparse.ArgumentParser() 116 parser.add_argument('--build-script', 117 required=True, 118 help='build script needed to run') 119 parser.add_argument('--target', help='rust target triple') 120 parser.add_argument('--features', help='features', nargs='+') 121 parser.add_argument('--env', help='environment variable', nargs='+') 122 parser.add_argument('--output', 123 required=True, 124 help='where to write output rustc flags') 125 parser.add_argument('--rust-prefix', required=True, 126 help='rust path prefix') 127 parser.add_argument('--generated-files', nargs='+', 128 help='any generated file') 129 parser.add_argument('--out-dir', required=True, help='ohos target out dir') 130 parser.add_argument('--src-dir', required=True, 131 help='ohos target source dir') 132 133 args = parser.parse_args() 134 rustc_path = os.path.join(args.rust_prefix, "rustc") 135 with tempfile.TemporaryDirectory() as tempdir: 136 env = set_env(args, rustc_path, tempdir) 137 run_build_script(args, env, tempdir) 138 139 140if __name__ == '__main__': 141 sys.exit(main()) 142