diff options
-rw-r--r-- | docs/markdown/Reference-manual.md | 9 | ||||
-rw-r--r-- | docs/markdown/Users.md | 2 | ||||
-rw-r--r-- | docs/markdown/snippets/run_command_check.md | 4 | ||||
-rw-r--r-- | mesonbuild/compilers/c.py | 7 | ||||
-rw-r--r-- | mesonbuild/compilers/fortran.py | 347 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 11 | ||||
-rw-r--r-- | mesonbuild/environment.py | 4 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 20 | ||||
-rw-r--r-- | mesonbuild/mesonlib.py | 2 | ||||
-rw-r--r-- | mesonbuild/mesonmain.py | 6 | ||||
-rw-r--r-- | mesonbuild/modules/windows.py | 2 | ||||
-rw-r--r-- | test cases/failing/75 run_command unclean exit/meson.build | 4 | ||||
-rwxr-xr-x | test cases/failing/75 run_command unclean exit/returncode.py | 4 | ||||
-rw-r--r-- | test cases/fortran/10 find library/gzip.f90 | 32 | ||||
-rw-r--r-- | test cases/fortran/10 find library/main.f90 | 40 | ||||
-rw-r--r-- | test cases/fortran/10 find library/meson.build | 9 |
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) |