|
|
|
import os, subprocess
|
|
|
|
import argparse
|
|
|
|
import tempfile
|
|
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
from . import build
|
|
|
|
from .mesonlib import MesonException, RealPathAction, is_windows, setup_vsenv
|
|
|
|
|
|
|
|
import typing as T
|
|
|
|
|
|
|
|
def add_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
|
parser.add_argument('-C', dest='wd', action=RealPathAction,
|
|
|
|
help='directory to cd into before running')
|
|
|
|
parser.add_argument('command', nargs=argparse.REMAINDER,
|
|
|
|
help='Command to run in developer environment (default: interactive shell)')
|
|
|
|
|
|
|
|
def get_windows_shell() -> str:
|
|
|
|
mesonbuild = Path(__file__).parent
|
|
|
|
script = mesonbuild / 'scripts' / 'cmd_or_ps.ps1'
|
|
|
|
command = ['powershell.exe', '-noprofile', '-executionpolicy', 'bypass', '-file', str(script)]
|
|
|
|
result = subprocess.check_output(command)
|
|
|
|
return result.decode().strip()
|
|
|
|
|
|
|
|
def get_env(b: build.Build, build_dir: str) -> T.Dict[str, str]:
|
|
|
|
env = os.environ.copy()
|
|
|
|
for i in b.devenv:
|
|
|
|
env = i.get_env(env)
|
|
|
|
|
|
|
|
extra_env = build.EnvironmentVariables()
|
|
|
|
extra_env.set('MESON_DEVENV', ['1'])
|
|
|
|
extra_env.set('MESON_PROJECT_NAME', [b.project_name])
|
|
|
|
|
|
|
|
meson_uninstalled = Path(build_dir) / 'meson-uninstalled'
|
|
|
|
if meson_uninstalled.is_dir():
|
|
|
|
extra_env.prepend('PKG_CONFIG_PATH', [str(meson_uninstalled)])
|
|
|
|
|
|
|
|
return extra_env.get_env(env)
|
|
|
|
|
|
|
|
def run(options: argparse.Namespace) -> int:
|
|
|
|
buildfile = Path(options.wd) / 'meson-private' / 'build.dat'
|
|
|
|
if not buildfile.is_file():
|
|
|
|
raise MesonException(f'Directory {options.wd!r} does not seem to be a Meson build directory.')
|
|
|
|
b = build.load(options.wd)
|
|
|
|
setup_vsenv(b.need_vsenv)
|
|
|
|
|
|
|
|
devenv = get_env(b, options.wd)
|
|
|
|
|
|
|
|
args = options.command
|
|
|
|
if not args:
|
|
|
|
prompt_prefix = f'[{b.project_name}]'
|
|
|
|
shell_env = os.environ.get("SHELL")
|
|
|
|
# Prefer $SHELL in a MSYS2 bash despite it being Windows
|
|
|
|
if shell_env and os.path.exists(shell_env):
|
|
|
|
args = [shell_env]
|
|
|
|
elif is_windows():
|
|
|
|
shell = get_windows_shell()
|
|
|
|
if shell == 'powershell.exe':
|
|
|
|
args = ['powershell.exe']
|
|
|
|
args += ['-NoLogo', '-NoExit']
|
|
|
|
prompt = f'function global:prompt {{ "{prompt_prefix} PS " + $PWD + "> "}}'
|
|
|
|
args += ['-Command', prompt]
|
|
|
|
else:
|
|
|
|
args = [os.environ.get("COMSPEC", r"C:\WINDOWS\system32\cmd.exe")]
|
|
|
|
args += ['/k', f'prompt {prompt_prefix} $P$G']
|
|
|
|
else:
|
|
|
|
args = [os.environ.get("SHELL", os.path.realpath("/bin/sh"))]
|
|
|
|
if "bash" in args[0] and not os.environ.get("MESON_DISABLE_PS1_OVERRIDE"):
|
|
|
|
tmprc = tempfile.NamedTemporaryFile(mode='w')
|
|
|
|
tmprc.write('[ -e ~/.bashrc ] && . ~/.bashrc\n')
|
|
|
|
tmprc.write(f'export PS1="{prompt_prefix} $PS1"')
|
|
|
|
tmprc.flush()
|
|
|
|
# Let the GC remove the tmp file
|
|
|
|
args.append("--rcfile")
|
|
|
|
args.append(tmprc.name)
|
|
|
|
|
|
|
|
try:
|
|
|
|
return subprocess.call(args, close_fds=False,
|
|
|
|
env=devenv,
|
|
|
|
cwd=options.wd)
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
|
|
return e.returncode
|