environment: use ExternalProgram to find ninja

This allows the NINJA environment variable to support all the Windows special
cases, especially allowing an absolute path without extension.

Based on a patch by Yonggang Luo.

Fixes: #7659
Suggested-by: Nirbheek Chauhan <nirbheek@centricular.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
pull/7698/head
Paolo Bonzini 4 years ago committed by Daniel Mensinger
parent fa5c2363eb
commit 492afe50a4
  1. 4
      mesonbuild/backend/ninjabackend.py
  2. 16
      mesonbuild/environment.py
  3. 2
      mesonbuild/mcompile.py
  4. 12
      mesonbuild/mdist.py
  5. 2
      mesonbuild/minit.py
  6. 2
      mesonbuild/mtest.py
  7. 2
      mesonbuild/scripts/scanbuild.py

@ -548,7 +548,7 @@ int dummy;
rules += [ "%s%s" % (rule, ext) for rule in [self.get_pch_rule_name(lang, for_machine)]
for ext in ['', '_RSP']]
compdb_options = ['-x'] if mesonlib.version_compare(self.ninja_version, '>=1.9') else []
ninja_compdb = [self.ninja_command, '-t', 'compdb'] + compdb_options + rules
ninja_compdb = self.ninja_command + ['-t', 'compdb'] + compdb_options + rules
builddir = self.environment.get_build_dir()
try:
jsondb = subprocess.check_output(ninja_compdb, cwd=builddir)
@ -2958,7 +2958,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
self.add_build(elem)
elem = NinjaBuildElement(self.all_outputs, 'meson-clean', 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('COMMAND', [self.ninja_command, '-t', 'clean'])
elem.add_item('COMMAND', self.ninja_command + ['-t', 'clean'])
elem.add_item('description', 'Cleaning')
# Alias that runs the above-defined meson-clean target
self.create_target_alias('meson-clean')

@ -168,15 +168,19 @@ def find_coverage_tools():
return gcovr_exe, gcovr_new_rootdir, lcov_exe, genhtml_exe, llvm_cov_exe
def detect_ninja(version: str = '1.7', log: bool = False) -> str:
def detect_ninja(version: str = '1.7', log: bool = False) -> T.List[str]:
r = detect_ninja_command_and_version(version, log)
return r[0] if r else None
def detect_ninja_command_and_version(version: str = '1.7', log: bool = False) -> (str, str):
def detect_ninja_command_and_version(version: str = '1.7', log: bool = False) -> (T.List[str], str):
from .dependencies.base import ExternalProgram
env_ninja = os.environ.get('NINJA', None)
for n in [env_ninja] if env_ninja else ['ninja', 'ninja-build', 'samu']:
prog = ExternalProgram(n, silent=True)
if not prog.found():
continue
try:
p, found = Popen_safe([n, '--version'])[0:2]
p, found = Popen_safe(prog.command + ['--version'])[0:2]
except (FileNotFoundError, PermissionError):
# Doesn't exist in PATH or isn't executable
continue
@ -184,7 +188,6 @@ def detect_ninja_command_and_version(version: str = '1.7', log: bool = False) ->
# Perhaps we should add a way for the caller to know the failure mode
# (not found or too old)
if p.returncode == 0 and mesonlib.version_compare(found, '>=' + version):
n = shutil.which(n)
if log:
name = os.path.basename(n)
if name.endswith('-' + found):
@ -193,8 +196,9 @@ def detect_ninja_command_and_version(version: str = '1.7', log: bool = False) ->
name = 'ninja'
if name == 'samu':
name = 'samurai'
mlog.log('Found {}-{} at {}'.format(name, found, quote_arg(n)))
return (n, found)
mlog.log('Found {}-{} at {}'.format(name, found,
' '.join([quote_arg(x) for x in prog.command])))
return (prog.command, found)
def get_llvm_tool_names(tool: str) -> T.List[str]:
# Ordered list of possible suffixes of LLVM executables to try. Start with

@ -139,7 +139,7 @@ def get_parsed_args_ninja(options: 'argparse.Namespace', builddir: Path) -> T.Li
raise MesonException('Cannot find ninja.')
mlog.log('Found runner:', runner)
cmd = [runner, '-C', builddir.as_posix()]
cmd = runner + ['-C', builddir.as_posix()]
if options.targets:
intro_data = parse_introspect_data(builddir)

@ -180,19 +180,19 @@ def create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, dist_scrip
output_names.append(zipname)
return output_names
def run_dist_steps(meson_command, unpacked_src_dir, builddir, installdir, ninja_bin):
def run_dist_steps(meson_command, unpacked_src_dir, builddir, installdir, ninja_args):
if subprocess.call(meson_command + ['--backend=ninja', unpacked_src_dir, builddir]) != 0:
print('Running Meson on distribution package failed')
return 1
if subprocess.call([ninja_bin], cwd=builddir) != 0:
if subprocess.call(ninja_args, cwd=builddir) != 0:
print('Compiling the distribution package failed')
return 1
if subprocess.call([ninja_bin, 'test'], cwd=builddir) != 0:
if subprocess.call(ninja_args + ['test'], cwd=builddir) != 0:
print('Running unit tests on the distribution package failed')
return 1
myenv = os.environ.copy()
myenv['DESTDIR'] = installdir
if subprocess.call([ninja_bin, 'install'], cwd=builddir, env=myenv) != 0:
if subprocess.call(ninja_args + ['install'], cwd=builddir, env=myenv) != 0:
print('Installing the distribution package failed')
return 1
return 0
@ -206,7 +206,7 @@ def check_dist(packagename, meson_command, extra_meson_args, bld_root, privdir):
if os.path.exists(p):
windows_proof_rmtree(p)
os.mkdir(p)
ninja_bin = detect_ninja()
ninja_args = detect_ninja()
shutil.unpack_archive(packagename, unpackdir)
unpacked_files = glob(os.path.join(unpackdir, '*'))
assert(len(unpacked_files) == 1)
@ -216,7 +216,7 @@ def check_dist(packagename, meson_command, extra_meson_args, bld_root, privdir):
if o['name'] not in ['backend', 'install_umask', 'buildtype']]
meson_command += extra_meson_args
ret = run_dist_steps(meson_command, unpacked_src_dir, builddir, installdir, ninja_bin)
ret = run_dist_steps(meson_command, unpacked_src_dir, builddir, installdir, ninja_args)
if ret > 0:
print('Dist check build directory was {}'.format(builddir))
else:

@ -174,7 +174,7 @@ def run(options) -> int:
ret = subprocess.run(cmd)
if ret.returncode:
raise SystemExit
cmd = [detect_ninja(), '-C', options.builddir]
cmd = detect_ninja() + ['-C', options.builddir]
ret = subprocess.run(cmd)
if ret.returncode:
raise SystemExit

@ -1178,7 +1178,7 @@ def rebuild_all(wd: str) -> bool:
print("Can't find ninja, can't rebuild test.")
return False
ret = subprocess.run([ninja, '-C', wd]).returncode
ret = subprocess.run(ninja + ['-C', wd]).returncode
if ret != 0:
print('Could not rebuild {}'.format(wd))
return False

@ -22,7 +22,7 @@ from ..environment import detect_ninja, detect_scanbuild
def scanbuild(exelist, srcdir, blddir, privdir, logdir, args):
with tempfile.TemporaryDirectory(dir=privdir) as scandir:
meson_cmd = exelist + args
build_cmd = exelist + ['-o', logdir, detect_ninja(), '-C', scandir]
build_cmd = exelist + ['-o', logdir] + detect_ninja() + ['-C', scandir]
rc = subprocess.call(meson_cmd + [srcdir, scandir])
if rc != 0:
return rc

Loading…
Cancel
Save