aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/ninjabackend.py3
-rw-r--r--mesonbuild/environment.py49
-rw-r--r--mesonbuild/scripts/scanbuild.py40
3 files changed, 56 insertions, 36 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 17b4986..fc88896 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2646,8 +2646,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
self.create_target_alias('meson-dist')
def generate_scanbuild(self):
- import shutil
- if shutil.which('scan-build') is None:
+ if not environment.detect_scanbuild():
return
cmd = self.environment.get_build_command() + \
['--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir] + \
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index e67e744..f5b24d8 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -163,6 +163,55 @@ def detect_ninja(version: str = '1.5', log: bool = False) -> str:
mlog.log('Found {}-{} at {}'.format(name, found, quote_arg(n)))
return n
+def detect_scanbuild():
+ """ Look for scan-build binary on build platform
+
+ First, if a SCANBUILD env variable has been provided, give it precedence
+ on all platforms.
+
+ For most platforms, scan-build is found is the PATH contains a binary
+ named "scan-build". However, some distribution's package manager (FreeBSD)
+ don't. For those, loop through a list of candidates to see if one is
+ available.
+ Since this is a costly operation, limit it to the impacted platforms
+ (currently all non-linux platforms)
+
+ Return: a single-element list of the found scan-build binary ready to be
+ passed to Popen()
+ """
+ exelist = []
+ if 'SCANBUILD' in os.environ:
+ exelist = split_args(os.environ['SCANBUILD'])
+
+ elif shutil.which('scan-build') is not None:
+ exelist = [shutil.which('scan-build')]
+
+ elif platform.system() != 'Linux':
+ tools = [
+ 'scan-build', # base
+ 'scan-build-8.0', 'scan-build80',
+ 'scan-build-7.0', 'scan-build70',
+ 'scan-build-6.0', 'scan-build60',
+ 'scan-build-5.0', 'scan-build50',
+ 'scan-build-4.0', 'scan-build40',
+ 'scan-build-3.9', 'scan-build39',
+ 'scan-build-3.8', 'scan-build38',
+ 'scan-build-3.7', 'scan-build37',
+ 'scan-build-3.6', 'scan-build36',
+ 'scan-build-3.5', 'scan-build35',
+ 'scan-build-9.0', 'scan-build-devel', # development snapshot
+ ]
+ for tool in tools:
+ if shutil.which(tool) is not None:
+ exelist = [shutil.which(tool)]
+ break
+
+ if exelist:
+ tool = exelist[0]
+ if os.path.isfile(tool) and os.access(tool, os.X_OK):
+ return [tool]
+ return []
+
def detect_native_windows_arch():
"""
The architecture of Windows itself: x86, amd64 or arm64
diff --git a/mesonbuild/scripts/scanbuild.py b/mesonbuild/scripts/scanbuild.py
index 8c0f423..d83ca12 100644
--- a/mesonbuild/scripts/scanbuild.py
+++ b/mesonbuild/scripts/scanbuild.py
@@ -16,9 +16,10 @@ import os
import subprocess
import shutil
import tempfile
-from ..environment import detect_ninja
+from ..environment import detect_ninja, detect_scanbuild
from ..mesonlib import Popen_safe, split_args
+
def scanbuild(exelist, srcdir, blddir, privdir, logdir, args):
with tempfile.TemporaryDirectory(dir=privdir) as scandir:
meson_cmd = exelist + args
@@ -28,6 +29,7 @@ def scanbuild(exelist, srcdir, blddir, privdir, logdir, args):
return rc
return subprocess.call(build_cmd)
+
def run(args):
srcdir = args[0]
blddir = args[1]
@@ -35,40 +37,10 @@ def run(args):
privdir = os.path.join(blddir, 'meson-private')
logdir = os.path.join(blddir, 'meson-logs/scanbuild')
shutil.rmtree(logdir, ignore_errors=True)
- tools = [
- 'scan-build', # base
- 'scan-build-8.0', 'scan-build80',
- 'scan-build-7.0', 'scan-build70',
- 'scan-build-6.0', 'scan-build60',
- 'scan-build-5.0', 'scan-build50',
- 'scan-build-4.0', 'scan-build40',
- 'scan-build-3.9', 'scan-build39',
- 'scan-build-3.8', 'scan-build38',
- 'scan-build-3.7', 'scan-build37',
- 'scan-build-3.6', 'scan-build36',
- 'scan-build-3.5', 'scan-build35',
- 'scan-build-9.0', 'scan-build-devel', # development snapshot
- ]
- toolname = 'scan-build'
- for tool in tools:
- try:
- p, out = Popen_safe([tool, '--help'])[:2]
- except (FileNotFoundError, PermissionError):
- continue
- if p.returncode != 0:
- continue
- else:
- toolname = tool
- break
- if 'SCANBUILD' in os.environ:
- exelist = split_args(os.environ['SCANBUILD'])
- else:
- exelist = [toolname]
-
- try:
- Popen_safe(exelist + ['--help'])
- except OSError:
+ exelist = detect_scanbuild()
+ if not exelist:
print('Could not execute scan-build "%s"' % ' '.join(exelist))
return 1
+
return scanbuild(exelist, srcdir, blddir, privdir, logdir, meson_cmd)