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