xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/distutils/spawn.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""distutils.spawn
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard WorkerProvides the 'spawn()' function, a front-end to various platform-
4*cda5da8dSAndroid Build Coastguard Workerspecific functions for launching another program in a sub-process.
5*cda5da8dSAndroid Build Coastguard WorkerAlso provides the 'find_executable()' to search the path for a given
6*cda5da8dSAndroid Build Coastguard Workerexecutable name.
7*cda5da8dSAndroid Build Coastguard Worker"""
8*cda5da8dSAndroid Build Coastguard Worker
9*cda5da8dSAndroid Build Coastguard Workerimport sys
10*cda5da8dSAndroid Build Coastguard Workerimport os
11*cda5da8dSAndroid Build Coastguard Workerimport subprocess
12*cda5da8dSAndroid Build Coastguard Worker
13*cda5da8dSAndroid Build Coastguard Workerfrom distutils.errors import DistutilsPlatformError, DistutilsExecError
14*cda5da8dSAndroid Build Coastguard Workerfrom distutils.debug import DEBUG
15*cda5da8dSAndroid Build Coastguard Workerfrom distutils import log
16*cda5da8dSAndroid Build Coastguard Worker
17*cda5da8dSAndroid Build Coastguard Worker
18*cda5da8dSAndroid Build Coastguard Workerif sys.platform == 'darwin':
19*cda5da8dSAndroid Build Coastguard Worker    _cfg_target = None
20*cda5da8dSAndroid Build Coastguard Worker    _cfg_target_split = None
21*cda5da8dSAndroid Build Coastguard Worker
22*cda5da8dSAndroid Build Coastguard Worker
23*cda5da8dSAndroid Build Coastguard Workerdef spawn(cmd, search_path=1, verbose=0, dry_run=0):
24*cda5da8dSAndroid Build Coastguard Worker    """Run another program, specified as a command list 'cmd', in a new process.
25*cda5da8dSAndroid Build Coastguard Worker
26*cda5da8dSAndroid Build Coastguard Worker    'cmd' is just the argument list for the new process, ie.
27*cda5da8dSAndroid Build Coastguard Worker    cmd[0] is the program to run and cmd[1:] are the rest of its arguments.
28*cda5da8dSAndroid Build Coastguard Worker    There is no way to run a program with a name different from that of its
29*cda5da8dSAndroid Build Coastguard Worker    executable.
30*cda5da8dSAndroid Build Coastguard Worker
31*cda5da8dSAndroid Build Coastguard Worker    If 'search_path' is true (the default), the system's executable
32*cda5da8dSAndroid Build Coastguard Worker    search path will be used to find the program; otherwise, cmd[0]
33*cda5da8dSAndroid Build Coastguard Worker    must be the exact path to the executable.  If 'dry_run' is true,
34*cda5da8dSAndroid Build Coastguard Worker    the command will not actually be run.
35*cda5da8dSAndroid Build Coastguard Worker
36*cda5da8dSAndroid Build Coastguard Worker    Raise DistutilsExecError if running the program fails in any way; just
37*cda5da8dSAndroid Build Coastguard Worker    return on success.
38*cda5da8dSAndroid Build Coastguard Worker    """
39*cda5da8dSAndroid Build Coastguard Worker    # cmd is documented as a list, but just in case some code passes a tuple
40*cda5da8dSAndroid Build Coastguard Worker    # in, protect our %-formatting code against horrible death
41*cda5da8dSAndroid Build Coastguard Worker    cmd = list(cmd)
42*cda5da8dSAndroid Build Coastguard Worker
43*cda5da8dSAndroid Build Coastguard Worker    log.info(' '.join(cmd))
44*cda5da8dSAndroid Build Coastguard Worker    if dry_run:
45*cda5da8dSAndroid Build Coastguard Worker        return
46*cda5da8dSAndroid Build Coastguard Worker
47*cda5da8dSAndroid Build Coastguard Worker    if search_path:
48*cda5da8dSAndroid Build Coastguard Worker        executable = find_executable(cmd[0])
49*cda5da8dSAndroid Build Coastguard Worker        if executable is not None:
50*cda5da8dSAndroid Build Coastguard Worker            cmd[0] = executable
51*cda5da8dSAndroid Build Coastguard Worker
52*cda5da8dSAndroid Build Coastguard Worker    env = None
53*cda5da8dSAndroid Build Coastguard Worker    if sys.platform == 'darwin':
54*cda5da8dSAndroid Build Coastguard Worker        global _cfg_target, _cfg_target_split
55*cda5da8dSAndroid Build Coastguard Worker        if _cfg_target is None:
56*cda5da8dSAndroid Build Coastguard Worker            from distutils import sysconfig
57*cda5da8dSAndroid Build Coastguard Worker            _cfg_target = sysconfig.get_config_var(
58*cda5da8dSAndroid Build Coastguard Worker                                  'MACOSX_DEPLOYMENT_TARGET') or ''
59*cda5da8dSAndroid Build Coastguard Worker            if _cfg_target:
60*cda5da8dSAndroid Build Coastguard Worker                _cfg_target_split = [int(x) for x in _cfg_target.split('.')]
61*cda5da8dSAndroid Build Coastguard Worker        if _cfg_target:
62*cda5da8dSAndroid Build Coastguard Worker            # Ensure that the deployment target of the build process is not
63*cda5da8dSAndroid Build Coastguard Worker            # less than 10.3 if the interpreter was built for 10.3 or later.
64*cda5da8dSAndroid Build Coastguard Worker            # This ensures extension modules are built with correct
65*cda5da8dSAndroid Build Coastguard Worker            # compatibility values, specifically LDSHARED which can use
66*cda5da8dSAndroid Build Coastguard Worker            # '-undefined dynamic_lookup' which only works on >= 10.3.
67*cda5da8dSAndroid Build Coastguard Worker            cur_target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', _cfg_target)
68*cda5da8dSAndroid Build Coastguard Worker            cur_target_split = [int(x) for x in cur_target.split('.')]
69*cda5da8dSAndroid Build Coastguard Worker            if _cfg_target_split[:2] >= [10, 3] and cur_target_split[:2] < [10, 3]:
70*cda5da8dSAndroid Build Coastguard Worker                my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: '
71*cda5da8dSAndroid Build Coastguard Worker                          'now "%s" but "%s" during configure;'
72*cda5da8dSAndroid Build Coastguard Worker                          'must use 10.3 or later'
73*cda5da8dSAndroid Build Coastguard Worker                                % (cur_target, _cfg_target))
74*cda5da8dSAndroid Build Coastguard Worker                raise DistutilsPlatformError(my_msg)
75*cda5da8dSAndroid Build Coastguard Worker            env = dict(os.environ,
76*cda5da8dSAndroid Build Coastguard Worker                       MACOSX_DEPLOYMENT_TARGET=cur_target)
77*cda5da8dSAndroid Build Coastguard Worker
78*cda5da8dSAndroid Build Coastguard Worker    try:
79*cda5da8dSAndroid Build Coastguard Worker        proc = subprocess.Popen(cmd, env=env)
80*cda5da8dSAndroid Build Coastguard Worker        proc.wait()
81*cda5da8dSAndroid Build Coastguard Worker        exitcode = proc.returncode
82*cda5da8dSAndroid Build Coastguard Worker    except OSError as exc:
83*cda5da8dSAndroid Build Coastguard Worker        if not DEBUG:
84*cda5da8dSAndroid Build Coastguard Worker            cmd = cmd[0]
85*cda5da8dSAndroid Build Coastguard Worker        raise DistutilsExecError(
86*cda5da8dSAndroid Build Coastguard Worker            "command %r failed: %s" % (cmd, exc.args[-1])) from exc
87*cda5da8dSAndroid Build Coastguard Worker
88*cda5da8dSAndroid Build Coastguard Worker    if exitcode:
89*cda5da8dSAndroid Build Coastguard Worker        if not DEBUG:
90*cda5da8dSAndroid Build Coastguard Worker            cmd = cmd[0]
91*cda5da8dSAndroid Build Coastguard Worker        raise DistutilsExecError(
92*cda5da8dSAndroid Build Coastguard Worker              "command %r failed with exit code %s" % (cmd, exitcode))
93*cda5da8dSAndroid Build Coastguard Worker
94*cda5da8dSAndroid Build Coastguard Worker
95*cda5da8dSAndroid Build Coastguard Workerdef find_executable(executable, path=None):
96*cda5da8dSAndroid Build Coastguard Worker    """Tries to find 'executable' in the directories listed in 'path'.
97*cda5da8dSAndroid Build Coastguard Worker
98*cda5da8dSAndroid Build Coastguard Worker    A string listing directories separated by 'os.pathsep'; defaults to
99*cda5da8dSAndroid Build Coastguard Worker    os.environ['PATH'].  Returns the complete filename or None if not found.
100*cda5da8dSAndroid Build Coastguard Worker    """
101*cda5da8dSAndroid Build Coastguard Worker    _, ext = os.path.splitext(executable)
102*cda5da8dSAndroid Build Coastguard Worker    if (sys.platform == 'win32') and (ext != '.exe'):
103*cda5da8dSAndroid Build Coastguard Worker        executable = executable + '.exe'
104*cda5da8dSAndroid Build Coastguard Worker
105*cda5da8dSAndroid Build Coastguard Worker    if os.path.isfile(executable):
106*cda5da8dSAndroid Build Coastguard Worker        return executable
107*cda5da8dSAndroid Build Coastguard Worker
108*cda5da8dSAndroid Build Coastguard Worker    if path is None:
109*cda5da8dSAndroid Build Coastguard Worker        path = os.environ.get('PATH', None)
110*cda5da8dSAndroid Build Coastguard Worker        if path is None:
111*cda5da8dSAndroid Build Coastguard Worker            try:
112*cda5da8dSAndroid Build Coastguard Worker                path = os.confstr("CS_PATH")
113*cda5da8dSAndroid Build Coastguard Worker            except (AttributeError, ValueError):
114*cda5da8dSAndroid Build Coastguard Worker                # os.confstr() or CS_PATH is not available
115*cda5da8dSAndroid Build Coastguard Worker                path = os.defpath
116*cda5da8dSAndroid Build Coastguard Worker        # bpo-35755: Don't use os.defpath if the PATH environment variable is
117*cda5da8dSAndroid Build Coastguard Worker        # set to an empty string
118*cda5da8dSAndroid Build Coastguard Worker
119*cda5da8dSAndroid Build Coastguard Worker    # PATH='' doesn't match, whereas PATH=':' looks in the current directory
120*cda5da8dSAndroid Build Coastguard Worker    if not path:
121*cda5da8dSAndroid Build Coastguard Worker        return None
122*cda5da8dSAndroid Build Coastguard Worker
123*cda5da8dSAndroid Build Coastguard Worker    paths = path.split(os.pathsep)
124*cda5da8dSAndroid Build Coastguard Worker    for p in paths:
125*cda5da8dSAndroid Build Coastguard Worker        f = os.path.join(p, executable)
126*cda5da8dSAndroid Build Coastguard Worker        if os.path.isfile(f):
127*cda5da8dSAndroid Build Coastguard Worker            # the file exists, we have a shot at spawn working
128*cda5da8dSAndroid Build Coastguard Worker            return f
129*cda5da8dSAndroid Build Coastguard Worker    return None
130