aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Reference-manual.md9
-rw-r--r--docs/markdown/Users.md2
-rw-r--r--docs/markdown/snippets/run_command_check.md4
-rw-r--r--mesonbuild/compilers/c.py7
-rw-r--r--mesonbuild/compilers/fortran.py347
-rw-r--r--mesonbuild/coredata.py11
-rw-r--r--mesonbuild/environment.py4
-rw-r--r--mesonbuild/interpreter.py20
-rw-r--r--mesonbuild/mesonlib.py2
-rw-r--r--mesonbuild/mesonmain.py6
-rw-r--r--mesonbuild/modules/windows.py2
-rw-r--r--test cases/failing/75 run_command unclean exit/meson.build4
-rwxr-xr-xtest cases/failing/75 run_command unclean exit/returncode.py4
-rw-r--r--test cases/fortran/10 find library/gzip.f9032
-rw-r--r--test cases/fortran/10 find library/main.f9040
-rw-r--r--test cases/fortran/10 find library/meson.build9
16 files changed, 320 insertions, 183 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index f9efe53..6c20221 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -1016,7 +1016,7 @@ Project supports the following keyword arguments.
### run_command()
``` meson
- runresult run_command(command, list_of_args)
+ runresult run_command(command, list_of_args, ...)
```
Runs the command specified in positional arguments.
@@ -1031,6 +1031,13 @@ Meson will set three environment variables `MESON_SOURCE_ROOT`,
directory, build directory and subdirectory the target was defined in,
respectively.
+This function has one keyword argument.
+
+ - `check` takes a boolean. If `true`, the exit status code of the command will
+ be checked, and the configuration will fail if it is non-zero. The default is
+ `false`.
+ Since 0.47.0
+
See also [External commands](External-commands.md).
### run_target
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index 0a30d9c..a15e5eb 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -47,6 +47,8 @@ listed in the [`meson` GitHub topic](https://github.com/topics/meson).
- [Libhttpseverywhere](https://git.gnome.org/browse/libhttpseverywhere), a library to enable httpseverywhere on any desktop app
- [Libosmscout](https://github.com/Framstag/libosmscout), a C++ library for offline map rendering, routing and location
lookup based on OpenStreetMap data
+ - [libspng](https://gitlab.com/randy408/libspng), a C library for reading and writing Portable Network Graphics (PNG)
+format files
- [Libva](https://github.com/intel/libva), an implementation for the VA (VIdeo Acceleration) API
- [Libzim](https://github.com/openzim/libzim), the reference implementation for the ZIM file format
- [Kiwix libraries](https://github.com/kiwix/kiwix-lib)
diff --git a/docs/markdown/snippets/run_command_check.md b/docs/markdown/snippets/run_command_check.md
new file mode 100644
index 0000000..018456b
--- /dev/null
+++ b/docs/markdown/snippets/run_command_check.md
@@ -0,0 +1,4 @@
+## New 'check' keyword argument for the run_command function
+
+If `check` is `true`, then the configuration will fail if the command returns a
+non-zero exit status. The default value is `false` for compatibility reasons.
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 81c0229..13b3dcc 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -808,12 +808,11 @@ class CCompiler(Compiler):
raise AssertionError('BUG: unknown libtype {!r}'.format(libtype))
return prefixes, suffixes
- def find_library(self, libname, env, extra_dirs, libtype='default'):
+ def find_library_impl(self, libname, env, extra_dirs, code, libtype='default'):
# These libraries are either built-in or invalid
if libname in self.ignore_libs:
return []
# First try if we can just add the library as -l.
- code = 'int main(int argc, char **argv) { return 0; }'
if extra_dirs and isinstance(extra_dirs, str):
extra_dirs = [extra_dirs]
# Gcc + co seem to prefer builtin lib dirs to -L dirs.
@@ -838,6 +837,10 @@ class CCompiler(Compiler):
return [trial]
return None
+ def find_library(self, libname, env, extra_dirs, libtype='default'):
+ code = 'int main(int argc, char **argv) { return 0; }'
+ return self.find_library_impl(libname, env, extra_dirs, code, libtype)
+
def thread_flags(self, env):
if for_haiku(self.is_cross, env):
return []
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 4c9b6b5..16a89b2 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -14,174 +14,207 @@
import os.path, subprocess
-from ..mesonlib import EnvironmentException, is_osx
-
+from .c import CCompiler
from .compilers import (
- GCC_CYGWIN,
- GCC_MINGW,
- GCC_OSX,
- GCC_STANDARD,
ICC_STANDARD,
- apple_buildtype_linker_args,
- get_gcc_soname_args,
- gnulike_buildtype_args,
- gnulike_buildtype_linker_args,
Compiler,
+ GnuCompiler,
ElbrusCompiler,
IntelCompiler,
)
class FortranCompiler(Compiler):
+ library_dirs_cache = CCompiler.library_dirs_cache
+
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs):
self.language = 'fortran'
- super().__init__(exelist, version, **kwargs)
- self.is_cross = is_cross
- self.exe_wrapper = exe_wrapper
- # Not really correct but I don't have Fortran compilers to test with. Sorry.
- self.gcc_type = GCC_STANDARD
- self.id = "IMPLEMENTATION CLASSES MUST SET THIS"
+ Compiler.__init__(self, exelist, version, **kwargs)
+ cc = CCompiler(exelist, version, is_cross, exe_wrapper, **kwargs)
+ self.id = 'unknown'
+ self.is_cross = cc.is_cross
+ self.exe_wrapper = cc.exe_wrapper
- def name_string(self):
- return ' '.join(self.exelist)
+ def get_display_language(self):
+ return 'Fortran'
- def get_pic_args(self):
- if self.gcc_type in (GCC_CYGWIN, GCC_MINGW, GCC_OSX):
- return [] # On Window and OS X, pic is always on.
- return ['-fPIC']
+ def needs_static_linker(self):
+ return CCompiler.needs_static_linker(self)
- def get_std_shared_lib_link_args(self):
- return ['-shared']
+ def get_always_args(self):
+ return CCompiler.get_always_args(self)
- def needs_static_linker(self):
- return True
+ def get_linker_debug_crt_args(self):
+ return CCompiler.get_linker_debug_crt_args(self)
- def sanity_check(self, work_dir, environment):
- source_name = os.path.join(work_dir, 'sanitycheckf.f90')
- binary_name = os.path.join(work_dir, 'sanitycheckf')
- with open(source_name, 'w') as ofile:
- ofile.write('''program prog
- print *, "Fortran compilation is working."
-end program prog
-''')
- extra_flags = self.get_cross_extra_flags(environment, link=True)
- pc = subprocess.Popen(self.exelist + extra_flags + [source_name, '-o', binary_name])
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Compiler %s can not compile programs.' % self.name_string())
- if self.is_cross:
- if self.exe_wrapper is None:
- # Can't check if the binaries run so we have to assume they do
- return
- cmdlist = self.exe_wrapper + [binary_name]
- else:
- cmdlist = [binary_name]
- pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- pe.wait()
- if pe.returncode != 0:
- raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string())
-
- def get_std_warn_args(self, level):
- return FortranCompiler.std_warn_args
-
- def get_buildtype_args(self, buildtype):
- return gnulike_buildtype_args[buildtype]
-
- def get_buildtype_linker_args(self, buildtype):
- if is_osx():
- return apple_buildtype_linker_args[buildtype]
- return gnulike_buildtype_linker_args[buildtype]
+ def get_no_stdinc_args(self):
+ return CCompiler.get_no_stdinc_args(self)
- def split_shlib_to_parts(self, fname):
- return os.path.dirname(fname), fname
+ def get_no_stdlib_link_args(self):
+ return CCompiler.get_no_stdlib_link_args(self)
+
+ def get_warn_args(self, level):
+ return CCompiler.get_warn_args(self, level)
+
+ def get_no_warn_args(self):
+ return CCompiler.get_no_warn_args(self)
def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module):
- return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module)
+ return CCompiler.get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module)
+
+ def split_shlib_to_parts(self, fname):
+ return CCompiler.split_shlib_to_parts(self, fname)
+
+ def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
+ return CCompiler.build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
def get_dependency_gen_args(self, outtarget, outfile):
- # Disabled until this is fixed:
- # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162
- # return ['-cpp', '-MD', '-MQ', outtarget]
return []
- def get_output_args(self, target):
- return ['-o', target]
+ def depfile_for_object(self, objfile):
+ return CCompiler.depfile_for_object(self, objfile)
+
+ def get_depfile_suffix(self):
+ return CCompiler.get_depfile_suffix(self)
+
+ def get_exelist(self):
+ return CCompiler.get_exelist(self)
+
+ def get_linker_exelist(self):
+ return CCompiler.get_linker_exelist(self)
def get_preprocess_only_args(self):
- return ['-E']
+ return ['-cpp'] + CCompiler.get_preprocess_only_args(self)
def get_compile_only_args(self):
- return ['-c']
+ return CCompiler.get_compile_only_args(self)
- def get_linker_exelist(self):
- return self.exelist[:]
+ def get_no_optimization_args(self):
+ return CCompiler.get_no_optimization_args(self)
+
+ def get_compiler_check_args(self):
+ return CCompiler.get_compiler_check_args(self)
+
+ def get_output_args(self, target):
+ return CCompiler.get_output_args(self, target)
def get_linker_output_args(self, outputname):
- return ['-o', outputname]
+ return CCompiler.get_linker_output_args(self, outputname)
+
+ def get_coverage_args(self):
+ return CCompiler.get_coverage_args(self)
+
+ def get_coverage_link_args(self):
+ return CCompiler.get_coverage_link_args(self)
+
+ def get_werror_args(self):
+ return CCompiler.get_werror_args(self)
+
+ def get_std_exe_link_args(self):
+ return CCompiler.get_std_exe_link_args(self)
def get_include_args(self, path, is_system):
- return ['-I' + path]
+ return CCompiler.get_include_args(self, path, is_system)
def get_module_incdir_args(self):
return ('-I', )
def get_module_outdir_args(self, path):
- return ['-J' + path]
+ return ['-module' + path]
- def depfile_for_object(self, objfile):
- return objfile + '.' + self.get_depfile_suffix()
+ def module_name_to_filename(self, module_name):
+ return module_name.lower() + '.mod'
- def get_depfile_suffix(self):
- return 'd'
+ def get_std_shared_lib_link_args(self):
+ return CCompiler.get_std_shared_lib_link_args(self)
- def get_std_exe_link_args(self):
- return []
+ def get_library_dirs_real(self):
+ return CCompiler.get_library_dirs_real(self)
- def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
- return self.build_unix_rpath_args(build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
+ def get_library_dirs(self):
+ return CCompiler.get_library_dirs(self)
- def module_name_to_filename(self, module_name):
- return module_name.lower() + '.mod'
+ def get_pic_args(self):
+ return CCompiler.get_pic_args(self)
- def get_warn_args(self, level):
- return ['-Wall']
+ def name_string(self):
+ return CCompiler.name_string(self)
- def get_no_warn_args(self):
- return ['-w']
+ def get_linker_search_args(self, dirname):
+ return CCompiler.get_linker_search_args(self, dirname)
+ def get_default_include_dirs(self):
+ return CCompiler.get_default_include_dirs(self)
-class GnuFortranCompiler(FortranCompiler):
- def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
- super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwargs)
- self.gcc_type = gcc_type
- self.defines = defines or {}
- self.id = 'gcc'
+ def gen_export_dynamic_link_args(self, env):
+ return CCompiler.gen_export_dynamic_link_args(self, env)
- def has_builtin_define(self, define):
- return define in self.defines
+ def gen_import_library_args(self, implibname):
+ return CCompiler.gen_import_library_args(self, implibname)
- def get_builtin_define(self, define):
- if define in self.defines:
- return self.defines[define]
+ def sanity_check(self, work_dir, environment):
+ code = '''program main
+ integer :: ret = 0
+ call exit(ret)
+ end program main'''
+ return CCompiler.sanity_check_impl(self, work_dir, environment, 'sanitycheckf.f90', code)
- def get_always_args(self):
- return ['-pipe']
+ def _get_compiler_check_args(self, env, extra_args, dependencies, mode='compile'):
+ return CCompiler._get_compiler_check_args(self, env, extra_args, dependencies, mode='compile')
- def get_coverage_args(self):
- return ['--coverage']
+ def compiles(self, code, env, extra_args=None, dependencies=None, mode='compile'):
+ return CCompiler.compiles(self, code, env, extra_args, dependencies, mode)
- def get_coverage_link_args(self):
- return ['--coverage']
+ def _build_wrapper(self, code, env, extra_args, dependencies=None, mode='compile', want_output=False):
+ return CCompiler._build_wrapper(self, code, env, extra_args, dependencies, mode, want_output)
- def gen_import_library_args(self, implibname):
- """
- The name of the outputted import library
+ def links(self, code, env, extra_args=None, dependencies=None):
+ return CCompiler.links(self, code, env, extra_args, dependencies)
- Used only on Windows
- """
- return ['-Wl,--out-implib=' + implibname]
+ def run(self, code, env, extra_args=None, dependencies=None):
+ return CCompiler.run(self, code, env, extra_args, dependencies)
- def openmp_flags(self):
- return ['-fopenmp']
+ def get_library_naming(self, env, libtype, strict=False):
+ return CCompiler.get_library_naming(self, env, libtype, strict)
+
+ def find_library(self, libname, env, extra_dirs, libtype='default'):
+ code = '''program main
+ call exit(0)
+ end program main'''
+ return CCompiler.find_library_impl(self, libname, env, extra_dirs, code, libtype)
+
+ def thread_flags(self, env):
+ return CCompiler.thread_flags(self, env)
+
+ def thread_link_flags(self, env):
+ return CCompiler.thread_link_flags(self, env)
+
+ def linker_to_compiler_args(self, args):
+ return CCompiler.linker_to_compiler_args(self, args)
+
+ def has_arguments(self, args, env, code, mode):
+ return CCompiler.has_arguments(self, args, env, code, mode)
+
+ def has_multi_arguments(self, args, env):
+ return CCompiler.has_multi_arguments(self, args, env)
+
+
+class GnuFortranCompiler(GnuCompiler, FortranCompiler):
+ def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None, **kwargs):
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs)
+ GnuCompiler.__init__(self, gcc_type, defines)
+ default_warn_args = ['-Wall']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-Wpedantic']}
+
+ def get_dependency_gen_args(self, outtarget, outfile):
+ # Disabled until this is fixed:
+ # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62162
+ # return ['-cpp', '-MD', '-MQ', outtarget]
+ return []
+
+ def get_module_outdir_args(self, path):
+ return ['-J' + path]
def language_stdlib_only_link_flags(self):
return ['-lgfortran', '-lm', '-lquadmath']
@@ -194,31 +227,24 @@ class ElbrusFortranCompiler(GnuFortranCompiler, ElbrusCompiler):
class G95FortranCompiler(FortranCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
- super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
self.id = 'g95'
+ default_warn_args = ['-Wall']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-Wextra'],
+ '3': default_warn_args + ['-Wextra', '-pedantic']}
def get_module_outdir_args(self, path):
return ['-fmod=' + path]
- def get_always_args(self):
- return ['-pipe']
-
def get_no_warn_args(self):
# FIXME: Confirm that there's no compiler option to disable all warnings
return []
- def gen_import_library_args(self, implibname):
- """
- The name of the outputted import library
-
- Used only on Windows
- """
- return ['-Wl,--out-implib=' + implibname]
-
class SunFortranCompiler(FortranCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
- super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
self.id = 'sun'
def get_dependency_gen_args(self, outtarget, outfile):
@@ -241,8 +267,6 @@ class SunFortranCompiler(FortranCompiler):
class IntelFortranCompiler(IntelCompiler, FortranCompiler):
- std_warn_args = ['-warn', 'all']
-
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp')
FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
@@ -250,47 +274,40 @@ class IntelFortranCompiler(IntelCompiler, FortranCompiler):
# we are sent the type of compiler
IntelCompiler.__init__(self, ICC_STANDARD)
self.id = 'intel'
+ default_warn_args = ['-warn', 'general', '-warn', 'truncated_source']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args + ['-warn', 'unused'],
+ '3': ['-warn', 'all']}
- def get_module_outdir_args(self, path):
- return ['-module', path]
-
- def get_warn_args(self, level):
- return IntelFortranCompiler.std_warn_args
+ def get_preprocess_only_args(self):
+ return ['-cpp', '-EP']
class PathScaleFortranCompiler(FortranCompiler):
- std_warn_args = ['-fullwarn']
-
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
- super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
self.id = 'pathscale'
-
- def get_module_outdir_args(self, path):
- return ['-module', path]
-
- def get_std_warn_args(self, level):
- return PathScaleFortranCompiler.std_warn_args
+ default_warn_args = ['-fullwarn']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args,
+ '3': default_warn_args}
def openmp_flags(self):
return ['-mp']
class PGIFortranCompiler(FortranCompiler):
- std_warn_args = ['-Minform=inform']
-
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
- super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
self.id = 'pgi'
+ default_warn_args = ['-Minform=inform']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args,
+ '3': default_warn_args}
def get_module_incdir_args(self):
return ('-module', )
- def get_module_outdir_args(self, path):
- return ['-module', path]
-
- def get_warn_args(self, level):
- return PGIFortranCompiler.std_warn_args
-
def get_no_warn_args(self):
return ['-silent']
@@ -299,34 +316,28 @@ class PGIFortranCompiler(FortranCompiler):
class Open64FortranCompiler(FortranCompiler):
- std_warn_args = ['-fullwarn']
-
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
- super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
self.id = 'open64'
-
- def get_module_outdir_args(self, path):
- return ['-module', path]
-
- def get_warn_args(self, level):
- return Open64FortranCompiler.std_warn_args
+ default_warn_args = ['-fullwarn']
+ self.warn_args = {'1': default_warn_args,
+ '2': default_warn_args,
+ '3': default_warn_args}
def openmp_flags(self):
return ['-mp']
class NAGFortranCompiler(FortranCompiler):
- std_warn_args = []
-
def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags):
- super().__init__(exelist, version, is_cross, exe_wrapper=None, **kwags)
+ FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags)
self.id = 'nagfor'
+ def get_warn_args(self, level):
+ return []
+
def get_module_outdir_args(self, path):
return ['-mdir', path]
- def get_warn_args(self, level):
- return NAGFortranCompiler.std_warn_args
-
def openmp_flags(self):
return ['-openmp']
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index a1dbac8..f3313f3 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -354,10 +354,19 @@ def load(build_dir):
def save(obj, build_dir):
filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
+ prev_filename = filename + '.prev'
+ tempfilename = filename + '~'
if obj.version != version:
raise MesonException('Fatal version mismatch corruption.')
- with open(filename, 'wb') as f:
+ if os.path.exists(filename):
+ import shutil
+ shutil.copyfile(filename, prev_filename)
+ with open(tempfilename, 'wb') as f:
pickle.dump(obj, f)
+ f.flush()
+ os.fsync(f.fileno())
+ os.replace(tempfilename, filename)
+ return filename
def get_builtin_options():
return list(builtin_options.keys())
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 15b3737..045be82 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -261,7 +261,6 @@ def search_version(text):
class Environment:
private_dir = 'meson-private'
log_dir = 'meson-logs'
- coredata_file = os.path.join(private_dir, 'coredata.dat')
def __init__(self, source_dir, build_dir, main_script_launcher, options, original_cmd_line_args):
self.source_dir = source_dir
@@ -335,8 +334,7 @@ class Environment:
return self.cross_info is not None
def dump_coredata(self):
- coredata.save(self.coredata, self.get_build_dir())
- return os.path.join(self.get_build_dir(), Environment.coredata_file)
+ return coredata.save(self.coredata, self.get_build_dir())
def get_script_dir(self):
import mesonbuild.scripts
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 4118a96..a63c143 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -94,18 +94,18 @@ class TryRunResultHolder(InterpreterObject):
class RunProcess(InterpreterObject):
- def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False):
+ def __init__(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False):
super().__init__()
if not isinstance(cmd, ExternalProgram):
raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
- pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir)
+ pc, self.stdout, self.stderr = self.run_command(cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
self.returncode = pc.returncode
self.methods.update({'returncode': self.returncode_method,
'stdout': self.stdout_method,
'stderr': self.stderr_method,
})
- def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir):
+ def run_command(self, cmd, args, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
command_array = cmd.get_command() + args
env = {'MESON_SOURCE_ROOT': source_dir,
'MESON_BUILD_ROOT': build_dir,
@@ -126,6 +126,10 @@ class RunProcess(InterpreterObject):
mlog.debug('----stderr----')
mlog.debug(e)
mlog.debug('')
+
+ if check and p.returncode != 0:
+ raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
+
return p, o, e
except FileNotFoundError:
raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
@@ -1681,6 +1685,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'install_subdir': {'exclude_files', 'exclude_directories', 'install_dir', 'install_mode', 'strip_directory'},
'jar': build.known_jar_kwargs,
'project': {'version', 'meson_version', 'default_options', 'license', 'subproject_dir'},
+ 'run_command': {'check'},
'run_target': {'command', 'depends'},
'shared_library': build.known_shlib_kwargs,
'shared_module': build.known_shmod_kwargs,
@@ -1959,7 +1964,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if not isinstance(actual, wanted):
raise InvalidArguments('Incorrect argument type.')
- @noKwargs
+ @permittedKwargs(permitted_kwargs['run_command'])
def func_run_command(self, node, args, kwargs):
return self.run_command_impl(node, args, kwargs)
@@ -1970,6 +1975,11 @@ external dependencies (including libraries) must go to "dependencies".''')
cargs = args[1:]
srcdir = self.environment.get_source_dir()
builddir = self.environment.get_build_dir()
+
+ check = kwargs.get('check', False)
+ if not isinstance(check, bool):
+ raise InterpreterException('Check must be boolean.')
+
m = 'must be a string, or the output of find_program(), files() '\
'or configure_file(), or a compiler object; not {!r}'
if isinstance(cmd, ExternalProgramHolder):
@@ -2022,7 +2032,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if a not in self.build_def_files:
self.build_def_files.append(a)
return RunProcess(cmd, expanded_args, srcdir, builddir, self.subdir,
- self.environment.get_build_command() + ['introspect'], in_builddir)
+ self.environment.get_build_command() + ['introspect'], in_builddir, check)
@stringArgs
def func_gettext(self, nodes, args, kwargs):
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 2a3b920..fe426c5 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -373,7 +373,7 @@ def for_darwin(is_cross, env):
if not is_cross:
return is_osx()
elif env.cross_info.has_host():
- return env.cross_info.config['host_machine']['system'] == 'darwin'
+ return env.cross_info.config['host_machine']['system'] in ('darwin', 'ios')
return False
def for_android(is_cross, env):
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 2b6281d..82f5031 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -204,7 +204,11 @@ class MesonApp:
g.run_postconf_scripts()
except:
if 'cdf' in locals():
- os.unlink(cdf)
+ old_cdf = cdf + '.prev'
+ if os.path.exists(old_cdf):
+ os.replace(old_cdf, cdf)
+ else:
+ os.unlink(cdf)
raise
def run_script_command(args):
diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py
index 62cb9d1..ac5b8b3 100644
--- a/mesonbuild/modules/windows.py
+++ b/mesonbuild/modules/windows.py
@@ -66,7 +66,7 @@ class WindowsModule(ExtensionModule):
res_args = extra_args + ['@INPUT@', '@OUTPUT@']
suffix = 'o'
if not rescomp.found():
- raise MesonException('Could not find Windows resource compiler %s.' % ' '.join(rescomp.get_command()))
+ raise MesonException('Could not find Windows resource compiler "%s".' % rescomp_name)
res_targets = []
diff --git a/test cases/failing/75 run_command unclean exit/meson.build b/test cases/failing/75 run_command unclean exit/meson.build
new file mode 100644
index 0000000..4bc02ae
--- /dev/null
+++ b/test cases/failing/75 run_command unclean exit/meson.build
@@ -0,0 +1,4 @@
+project('run_command unclean exit', 'c')
+
+rcprog = find_program('./returncode.py')
+run_command(rcprog, '1', check : true)
diff --git a/test cases/failing/75 run_command unclean exit/returncode.py b/test cases/failing/75 run_command unclean exit/returncode.py
new file mode 100755
index 0000000..84dbc5d
--- /dev/null
+++ b/test cases/failing/75 run_command unclean exit/returncode.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python3
+
+import sys
+exit(int(sys.argv[1]))
diff --git a/test cases/fortran/10 find library/gzip.f90 b/test cases/fortran/10 find library/gzip.f90
new file mode 100644
index 0000000..2a7e7df
--- /dev/null
+++ b/test cases/fortran/10 find library/gzip.f90
@@ -0,0 +1,32 @@
+module gzip
+
+ interface
+ function gzopen(path, mode) bind(C)
+ use iso_c_binding, only: c_char, c_ptr
+ implicit none
+ character(c_char), intent(in) :: path(*), mode(*)
+ type(c_ptr) :: gzopen
+ end function gzopen
+ end interface
+
+ interface
+ function gzwrite(file, buf, len) bind(C)
+ use iso_c_binding, only: c_int, c_ptr
+ implicit none
+ type(c_ptr), value, intent(in) :: file
+ type(*), intent(in) :: buf
+ integer(c_int), value, intent(in) :: len
+ integer(c_int) :: gzwrite
+ end function gzwrite
+ end interface
+
+ interface
+ function gzclose(file) bind(C)
+ use iso_c_binding, only: c_int, c_ptr
+ implicit none
+ type(c_ptr), value, intent(in) :: file
+ integer(c_int) :: gzclose
+ end function gzclose
+ end interface
+
+end module gzip
diff --git a/test cases/fortran/10 find library/main.f90 b/test cases/fortran/10 find library/main.f90
new file mode 100644
index 0000000..2550b44
--- /dev/null
+++ b/test cases/fortran/10 find library/main.f90
@@ -0,0 +1,40 @@
+program main
+
+ use iso_c_binding, only: c_int, c_char, c_null_char, c_ptr
+ use gzip, only: gzopen, gzwrite, gzclose
+
+ implicit none
+
+ character(kind=c_char,len=*), parameter :: path = &
+ c_char_"test.gz"//c_null_char
+ character(kind=c_char,len=*), parameter :: mode = &
+ c_char_"wb9"//c_null_char
+ integer(c_int), parameter :: buffer_size = 512
+
+ type(c_ptr) :: file
+ character(len=buffer_size) :: buffer
+ integer(c_int) :: ret
+ integer :: i
+
+ ! open file
+ file = gzopen(path, mode)
+
+ ! fill buffer with data
+ do i=1,buffer_size/4
+ write(buffer(4*(i-1)+1:4*i), '(i3.3, a)') i, new_line('')
+ end do
+ ret = gzwrite(file, buffer, buffer_size)
+ if (ret.ne.buffer_size) then
+ write(*,'(a, i3, a, i3, a)') 'Error: ', ret, ' / ', buffer_size, &
+ ' bytes written.'
+ stop 1
+ end if
+
+ ! close file
+ ret = gzclose(file)
+ if (ret.ne.0) then
+ print *, 'Error: failure to close file with error code ', ret
+ stop 1
+ end if
+
+end program main
diff --git a/test cases/fortran/10 find library/meson.build b/test cases/fortran/10 find library/meson.build
new file mode 100644
index 0000000..be66888
--- /dev/null
+++ b/test cases/fortran/10 find library/meson.build
@@ -0,0 +1,9 @@
+project('find fortran library', 'fortran')
+
+fortranc = meson.get_compiler('fortran')
+
+sources = ['main.f90', 'gzip.f90']
+zlib = fortranc.find_library('z')
+
+exe = executable('zlibtest', sources, dependencies : zlib)
+test('testzlib', exe)