xref: /llvm-project/llvm/utils/sysroot.py (revision b71edfaa4ec3c998aadb35255ce2f60bba2940b0)
1#!/usr/bin/env python3
2
3"""Helps manage sysroots."""
4
5import argparse
6import os
7import subprocess
8import sys
9
10
11def make_fake_sysroot(out_dir):
12    def cmdout(cmd):
13        return subprocess.check_output(cmd).decode(sys.stdout.encoding).strip()
14
15    if sys.platform == "win32":
16
17        def mkjunction(dst, src):
18            subprocess.check_call(["mklink", "/j", dst, src], shell=True)
19
20        os.mkdir(out_dir)
21        p = os.getenv("ProgramFiles(x86)", "C:\\Program Files (x86)")
22
23        winsdk = os.getenv("WindowsSdkDir")
24        if not winsdk:
25            winsdk = os.path.join(p, "Windows Kits", "10")
26            print("%WindowsSdkDir% not set. You might want to run this from")
27            print("a Visual Studio cmd prompt. Defaulting to", winsdk)
28        os.mkdir(os.path.join(out_dir, "Windows Kits"))
29        mkjunction(os.path.join(out_dir, "Windows Kits", "10"), winsdk)
30
31        vswhere = os.path.join(p, "Microsoft Visual Studio", "Installer", "vswhere")
32        vcid = "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"
33        vsinstalldir = cmdout(
34            [
35                vswhere,
36                "-latest",
37                "-products",
38                "*",
39                "-requires",
40                vcid,
41                "-property",
42                "installationPath",
43            ]
44        )
45
46        mkjunction(os.path.join(out_dir, "VC"), os.path.join(vsinstalldir, "VC"))
47        # Not all MSVC versions ship the DIA SDK, so the junction destination
48        # might not exist. That's fine.
49        mkjunction(
50            os.path.join(out_dir, "DIA SDK"), os.path.join(vsinstalldir, "DIA SDK")
51        )
52    elif sys.platform == "darwin":
53        # The SDKs used by default in compiler-rt/cmake/base-config-ix.cmake.
54        # COMPILER_RT_ENABLE_IOS defaults to on.
55        # COMPILER_RT_ENABLE_WATCHOS and COMPILER_RT_ENABLE_TV default to off.
56        # compiler-rt/cmake/config-ix.cmake sets DARWIN_EMBEDDED_PLATFORMS
57        # depending on these.
58        sdks = ["macosx", "iphoneos", "iphonesimulator"]
59        os.mkdir(out_dir)
60        for sdk in sdks:
61            sdkpath = cmdout(["xcrun", "-sdk", sdk, "-show-sdk-path"])
62            # sdkpath is something like /.../SDKs/MacOSX11.1.sdk, which is a
63            # symlink to MacOSX.sdk in the same directory. Resolve the symlink,
64            # to make the symlink in out_dir less likely to break when the SDK
65            # is updated (which will bump the number on xcrun's output, but not
66            # on the symlink destination).
67            sdkpath = os.path.realpath(sdkpath)
68            os.symlink(sdkpath, os.path.join(out_dir, os.path.basename(sdkpath)))
69    else:
70        os.symlink("/", out_dir)
71
72    print("Done. Pass these flags to cmake:")
73    abs_out_dir = os.path.abspath(out_dir)
74    if sys.platform == "win32":
75        # CMake doesn't like backslashes in commandline args.
76        abs_out_dir = abs_out_dir.replace(os.path.sep, "/")
77        print("  -DLLVM_WINSYSROOT=" + abs_out_dir)
78    elif sys.platform == "darwin":
79        flags = [
80            "-DCMAKE_OSX_SYSROOT=" + os.path.join(abs_out_dir, "MacOSX.sdk"),
81            # For find_darwin_sdk_dir() in
82            # compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake
83            "-DDARWIN_macosx_CACHED_SYSROOT=" + os.path.join(abs_out_dir, "MacOSX.sdk"),
84            "-DDARWIN_iphoneos_CACHED_SYSROOT="
85            + os.path.join(abs_out_dir, "iPhoneOS.sdk"),
86            "-DDARWIN_iphonesimulator_CACHED_SYSROOT="
87            + os.path.join(abs_out_dir, "iPhoneSimulator.sdk"),
88        ]
89        print("  " + " ".join(flags))
90    else:
91        print("  -DCMAKE_SYSROOT=" + abs_out_dir + " to cmake.")
92
93
94def main():
95    parser = argparse.ArgumentParser(description=__doc__)
96
97    subparsers = parser.add_subparsers(dest="command", required=True)
98
99    makefake = subparsers.add_parser(
100        "make-fake", help="Create a sysroot that symlinks to local directories."
101    )
102    makefake.add_argument("--out-dir", required=True)
103
104    args = parser.parse_args()
105
106    assert args.command == "make-fake"
107    make_fake_sysroot(args.out_dir)
108
109
110if __name__ == "__main__":
111    main()
112