1# Copyright (C) 2024 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import json 16import os 17import logging 18import tempfile 19import shutil 20 21# To generate rust-project.json from bazel, run 22# bazel run @rules_rust//tools/rust_analyzer:gen_rust_project --norepository_disable_download @gbl//efi:main 23# However, this yields incorrect source path. 24# Your source file 25# /usr/local/google/home/zhangkelvin/uefi-gbl-mainline/bootable/libbootloader/gbl/efi/src/main.rs 26# would turn into 27# /usr/local/google/home/uefi-gbl-mainline/out/bazel/output_user_root/e14d642d361d598c63507c64a56ecbc7/execroot/_main/external/gbl/efi/src/main.rs 28# and this confuses the rust-analyzer. This script will resolve the right 29# source path for you by checking if any of the parent path is a symlink, 30# and resolve all symlinks to final destination. 31 32 33def traverse(obj: dict): 34 if isinstance(obj, dict): 35 for (key, val) in obj.items(): 36 if key == "root_module" or key == "CARGO_MANIFEST_DIR": 37 obj[key] = os.path.realpath(val) 38 continue 39 elif key == "include_dirs" or key == "exclude_dirs": 40 obj[key] = [os.path.realpath(d) for d in val] 41 continue 42 elif key == "cfg" and isinstance(val, list): 43 obj[key] = [o for o in val if o != "test"] 44 continue 45 traverse(val) 46 elif isinstance(obj, list): 47 for item in obj: 48 traverse(item) 49 50 51def main(argv): 52 logging.basicConfig(level=logging.INFO) 53 rust_project_json_path = "rust-project.json" 54 if len(argv) == 2: 55 rust_project_json_path = argv[1] 56 rust_project_json_path = os.path.realpath(rust_project_json_path) 57 project_root_path = os.path.dirname(rust_project_json_path) 58 logging.info("Using %s as project root path", project_root_path) 59 with open(rust_project_json_path, "r") as fp: 60 data = json.load(fp) 61 traverse(data) 62 63 with tempfile.NamedTemporaryFile("w+", delete=False) as fp: 64 json.dump(data, fp.file, indent=True) 65 tmp_path = fp.name 66 shutil.move(tmp_path, rust_project_json_path) 67 68 69if __name__ == "__main__": 70 import sys 71 72 main(sys.argv) 73