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 19 20# To generate rust-project.json from bazel, run 21# bazel run @rules_rust//tools/rust_analyzer:gen_rust_project --norepository_disable_download @gbl//efi:main 22# However, this yields incorrect source path. 23# Your source file 24# /usr/local/google/home/zhangkelvin/uefi-gbl-mainline/bootable/libbootloader/gbl/efi/src/main.rs 25# would turn into 26# /usr/local/google/home/uefi-gbl-mainline/out/bazel/output_user_root/e14d642d361d598c63507c64a56ecbc7/execroot/_main/external/gbl/efi/src/main.rs 27# and this confuses the rust-analyzer. This script will resolve the right 28# source path for you by checking if any of the parent path is a symlink, 29# and resolve all symlinks to final destination. 30 31 32def traverse(obj: dict): 33 if isinstance(obj, dict): 34 for (key, val) in obj.items(): 35 if key == "root_module" or key == "CARGO_MANIFEST_DIR": 36 obj[key] = os.path.realpath(val) 37 continue 38 elif key == "include_dirs" or key == "exclude_dirs": 39 obj[key] = [os.path.realpath(d) for d in val] 40 continue 41 elif key == "cfg" and isinstance(val, list): 42 obj[key] = [o for o in val if o != "test"] 43 continue 44 traverse(val) 45 elif isinstance(obj, list): 46 for item in obj: 47 traverse(item) 48 49 50def main(argv): 51 logging.basicConfig(level=logging.INFO) 52 rust_project_json_path = "rust-project.json" 53 if len(argv) == 2: 54 rust_project_json_path = argv[1] 55 rust_project_json_path = os.path.realpath(rust_project_json_path) 56 project_root_path = os.path.dirname(rust_project_json_path) 57 logging.info("Using %s as project root path", project_root_path) 58 with open(rust_project_json_path, "r") as fp: 59 data = json.load(fp) 60 traverse(data) 61 62 with tempfile.NamedTemporaryFile("w+") as fp: 63 json.dump(data, fp.file, indent=True) 64 os.rename(fp.name, rust_project_json_path) 65 # create the tempfile again so deleting it works after exiting this scope 66 with open(fp.name, "w"): 67 pass 68 69 70if __name__ == "__main__": 71 import sys 72 73 main(sys.argv) 74