xref: /llvm-project/lldb/bindings/python/get-python-config.py (revision c8387a31a4adfa9c29a578cf67321f756d3b4ac1)
1#!/usr/bin/env python3
2
3import os
4import sys
5import argparse
6import sysconfig
7
8
9def relpath_nodots(path, base):
10    rel = os.path.normpath(os.path.relpath(path, base))
11    assert not os.path.isabs(rel)
12    parts = rel.split(os.path.sep)
13    if parts and parts[0] == "..":
14        raise ValueError(f"{path} is not under {base}")
15    return rel
16
17
18def main():
19    parser = argparse.ArgumentParser(description="extract cmake variables from python")
20    parser.add_argument("variable_name")
21    args = parser.parse_args()
22    if args.variable_name == "LLDB_PYTHON_RELATIVE_PATH":
23        # LLDB_PYTHON_RELATIVE_PATH is the relative path from lldb's prefix
24        # to where lldb's python libraries will be installed.
25        #
26        # The way we're going to compute this is to take the relative path from
27        # PYTHON'S prefix to where python libraries are supposed to be
28        # installed.
29        #
30        # The result is if LLDB and python are give the same prefix, then
31        # lldb's python lib will be put in the correct place for python to find it.
32        # If not, you'll have to use lldb -P or lldb -print-script-interpreter-info
33        # to figure out where it is.
34        try:
35            print(relpath_nodots(sysconfig.get_path("platlib"), sys.prefix))
36        except ValueError:
37            # Try to fall back to something reasonable if sysconfig's platlib
38            # is outside of sys.prefix
39            if os.name == "posix":
40                print("lib/python%d.%d/site-packages" % sys.version_info[:2])
41            elif os.name == "nt":
42                print("Lib\\site-packages")
43            else:
44                raise
45    elif args.variable_name == "LLDB_PYTHON_EXE_RELATIVE_PATH":
46        tried = list()
47        exe = sys.executable
48        prefix = os.path.realpath(sys.prefix)
49        while True:
50            try:
51                print(relpath_nodots(exe, prefix))
52                break
53            except ValueError:
54                tried.append(exe)
55                # Retry if the executable is symlinked or similar.
56                # This is roughly equal to os.path.islink, except it also works for junctions on Windows.
57                if os.path.realpath(exe) != exe:
58                    exe = os.path.realpath(exe)
59                    continue
60                else:
61                    print(
62                        "Could not find a relative path to sys.executable under sys.prefix",
63                        file=sys.stderr,
64                    )
65                    for e in tried:
66                        print("tried:", e, file=sys.stderr)
67                    print("realpath(sys.prefix):", prefix, file=sys.stderr)
68                    print("sys.prefix:", sys.prefix, file=sys.stderr)
69                    sys.exit(1)
70    elif args.variable_name == "LLDB_PYTHON_EXT_SUFFIX":
71        print(sysconfig.get_config_var("EXT_SUFFIX"))
72    else:
73        parser.error(f"unknown variable {args.variable_name}")
74
75
76if __name__ == "__main__":
77    main()
78