diff options
35 files changed, 304 insertions, 58 deletions
diff --git a/ciimage/Dockerfile b/ciimage/Dockerfile index 35997f8..3789e8d 100644 --- a/ciimage/Dockerfile +++ b/ciimage/Dockerfile @@ -8,4 +8,6 @@ RUN apt-get -y update && apt-get -y upgrade \ && apt-get -y install valgrind doxygen \ && apt-get -y install llvm libsdl2-dev \ && apt-get -y install python3-pip libxml2-dev libxslt1-dev cmake libyaml-dev \ +&& apt-get -y install openmpi-bin libopenmpi-dev \ +&& apt-get -y install libvulkan-dev libpcap-dev \ && python3 -m pip install hotdoc codecov diff --git a/docs/markdown/Localisation.md b/docs/markdown/Localisation.md index 27181e5..34cad8d 100644 --- a/docs/markdown/Localisation.md +++ b/docs/markdown/Localisation.md @@ -29,7 +29,7 @@ langs = ['fi', 'de'] i18n.gettext('intltest', languages : langs) ``` -The first command imports the `i18n` module that provides gettext features. The second line does the actual invocation. The first argument to the is the gettext package name. This causes two things to happen. The first is that Meson will generate binary mo files and put them to their proper locations when doing an install. The second is that it creates a build rule to regenerate the main pot file. If you are using the Ninja backend, this is how you would invoke the rebuild. +The first command imports the `i18n` module that provides gettext features. The third line does the actual invocation. The first argument is the gettext package name. This causes two things to happen. The first is that Meson will generate binary mo files and put them to their proper locations when doing an install. The second is that it creates a build rule to regenerate the main pot file. If you are using the Ninja backend, this is how you would invoke the rebuild. ```console $ ninja intltest-pot diff --git a/docs/markdown/Porting-from-autotools.md b/docs/markdown/Porting-from-autotools.md index f9c9ad8..91ed5d2 100644 --- a/docs/markdown/Porting-from-autotools.md +++ b/docs/markdown/Porting-from-autotools.md @@ -625,3 +625,62 @@ if not os.environ.get('DESTDIR'): print('Compiling gsettings schemas...') subprocess.call(['glib-compile-schemas', schemadir]) ``` + +### gettext + +Note this example does not include `intltool` usage. + +`configure.ac`: +```m4 +AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.19.7]) + +GETTEXT_PACKAGE=foo +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [The prefix for our gettext translation domains.]) +``` + +`po/Makevars`: +```make +XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ --keyword=N_ --keyword=C_:1c,2 --keyword=NC_:1c,2 --keyword=g_dngettext:2,3 --add-comments +``` + +`Makefile.am`: +```make +%.desktop: %.desktop.in + $(AM_V_GEN)$(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@ + +%.appdata.xml: %.appdata.xml.in + $(AM_V_GEN)$(MSGFMT) --xml --template $< -d $(top_srcdir)/po -o $@ +``` + +`meson.build`: +```meson +i18n = import('i18n') + +gettext_package = 'foo' +add_project_arguments('-DGETTEXT_PACKAGE=' + gettext_package, language: 'c') +subdir('po') + +i18n.merge_file( + input: 'foo.desktop.in', + output: 'foo.desktop', + type: 'desktop', + po_dir: 'po', + install: true, + install_dir: join_paths(get_option('datadir'), 'applications') +) + +i18n.merge_file( + input: 'foo.appdata.xml.in', + output: 'foo.appdata.xml', + po_dir: 'po', + install: true, + install_dir: join_paths(get_option('datadir'), 'appdata') +) +``` + +`po/meson.build`: +```meson +i18n.gettext(gettext_package, preset: 'glib') +``` diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md index 09369e6..02db228 100644 --- a/docs/markdown/Syntax.md +++ b/docs/markdown/Syntax.md @@ -68,6 +68,16 @@ single quote = 'contains a \' character' Similarly `\n` gets converted to a newline and `\\\\` to a single backslash. +#### String concatenation + +Strings can be concatenated to form a new string using the `+` symbol. + +```meson +str1 = 'abc' +str2 = 'xyz' +combined = str1 + '_' + str2 # combined is now abc_xyz +``` + #### Strings running over multiple lines Strings running over multiple lines can be declared with three single quotes, like this: @@ -194,19 +204,37 @@ Arrays are delimited by brackets. An array can contain an arbitrary number of ob my_array = [1, 2, 'string', some_obj] ``` -You can add additional items to an array like this: +Accessing elements of an array can be done via array indexing: ```meson -my_array += [ 'foo', 3, 4, another_obj ] +my_array = [1, 2, 'string', some_obj] +second_element = my_array[1] +last_element = my_array[-1] ``` +You can add more items to an array like this: + +```meson +my_array += ['foo', 3, 4, another_obj] +``` + +When adding a single item, you do not need to enclose it in an array: + +```meson +my_array += ['something'] +# This also works +my_array += 'else' +``` + +Note appending to an array will always create a new array object and assign it to `my_array` instead of modifying the original since all objects in Meson are immutable. + #### Array methods The following methods are defined for all arrays: - `length`, the size of the array - `contains`, returns `true` if the array contains the object given as argument, `false` otherwise - - `get`, returns the object at the given index, negative indices count from the back of the array, indexing out of bounds is a fatal error + - `get`, returns the object at the given index, negative indices count from the back of the array, indexing out of bounds is a fatal error. Provided for backwards-compatibility, it is identical to array indexing. Function calls -- diff --git a/manual tests/4 standalone binaries/build_linux_package.sh b/manual tests/4 standalone binaries/build_linux_package.sh index 806a453..783981e 100755 --- a/manual tests/4 standalone binaries/build_linux_package.sh +++ b/manual tests/4 standalone binaries/build_linux_package.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -eu curdir=`pwd` rm -rf buildtmp diff --git a/manual tests/4 standalone binaries/build_osx_package.sh b/manual tests/4 standalone binaries/build_osx_package.sh index eb4ec38..8a94ca5 100755 --- a/manual tests/4 standalone binaries/build_osx_package.sh +++ b/manual tests/4 standalone binaries/build_osx_package.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -eu rm -rf buildtmp mkdir buildtmp diff --git a/manual tests/4 standalone binaries/linux_bundler.sh b/manual tests/4 standalone binaries/linux_bundler.sh index a0e5c12..2a8e907 100755 --- a/manual tests/4 standalone binaries/linux_bundler.sh +++ b/manual tests/4 standalone binaries/linux_bundler.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -eu libdir="${MESON_INSTALL_PREFIX}/lib" mkdir -p $libdir diff --git a/manual tests/4 standalone binaries/osx_bundler.sh b/manual tests/4 standalone binaries/osx_bundler.sh index 7b83573..3bad65f 100755 --- a/manual tests/4 standalone binaries/osx_bundler.sh +++ b/manual tests/4 standalone binaries/osx_bundler.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -eu mkdir -p ${MESON_INSTALL_PREFIX}/Contents/Frameworks cp -R /Library/Frameworks/SDL2.framework ${MESON_INSTALL_PREFIX}/Contents/Frameworks diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 5fc6d6b..9048a78 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -782,8 +782,8 @@ int dummy; subdir = m.get_custom_install_dir() if subdir is None: subdir = os.path.join(manroot, 'man' + num) - srcabs = os.path.join(self.environment.get_source_dir(), m.get_source_subdir(), f) - dstabs = os.path.join(subdir, os.path.split(f)[1] + '.gz') + srcabs = f.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) + dstabs = os.path.join(subdir, os.path.split(f.fname)[1] + '.gz') i = [srcabs, dstabs] d.man.append(i) @@ -1094,6 +1094,7 @@ int dummy; valac_outputs.append(vala_c_file) args = self.generate_basic_compiler_args(target, valac) + args += valac.get_colorout_args(self.environment.coredata.base_options.get('b_colorout').value) # Tell Valac to output everything in our private directory. Sadly this # means it will also preserve the directory components of Vala sources # found inside the build tree (generated sources). @@ -2263,7 +2264,7 @@ rule FORTRAN_DEP_HACK commands += linker.get_gui_app_args() # If implib, and that's significant on this platform (i.e. Windows using either GCC or Visual Studio) if target.import_filename: - commands += linker.gen_import_library_args(os.path.join(target.subdir, target.import_filename)) + commands += linker.gen_import_library_args(os.path.join(self.get_target_dir(target), target.import_filename)) elif isinstance(target, build.SharedLibrary): if isinstance(target, build.SharedModule): commands += linker.get_std_shared_module_link_args() @@ -2280,7 +2281,7 @@ rule FORTRAN_DEP_HACK commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) # This is only visited when building for Windows using either GCC or Visual Studio if target.import_filename: - commands += linker.gen_import_library_args(os.path.join(target.subdir, target.import_filename)) + commands += linker.gen_import_library_args(os.path.join(self.get_target_dir(target), target.import_filename)) elif isinstance(target, build.StaticLibrary): commands += linker.get_std_link_args() else: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 58cf987..94f177a 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -14,6 +14,7 @@ import copy, os, re from collections import OrderedDict +import itertools from . import environment from . import dependencies @@ -936,7 +937,7 @@ You probably should put it in link_with instead.''') langs.append(dep.language) # Check if any of the internal libraries this target links to were # written in this language - for link_target in self.link_targets: + for link_target in itertools.chain(self.link_targets, self.link_whole_targets): for language in link_target.compilers: if language not in langs: langs.append(language) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 5de39d4..018c353 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -273,9 +273,13 @@ class CCompiler(Compiler): for d in dependencies: # Add compile flags needed by dependencies args += d.get_compile_args() + if d.need_threads(): + args += self.thread_flags() if mode == 'link': # Add link flags needed to find dependencies args += d.get_link_args() + if d.need_threads(): + args += self.thread_link_flags() # Select a CRT if needed since we're linking if mode == 'link': args += self.get_linker_debug_crt_args() diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index a8fc8a3..a933f0e 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -175,7 +175,6 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler): class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap, is_64): self.language = 'cpp' - CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap, is_64) self.base_options = ['b_pch'] # FIXME add lto, pgo and the like diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py index 21c040c..9da9b81 100644 --- a/mesonbuild/compilers/vala.py +++ b/mesonbuild/compilers/vala.py @@ -15,7 +15,7 @@ import os.path from .. import mlog -from ..mesonlib import EnvironmentException +from ..mesonlib import EnvironmentException, version_compare from .compilers import Compiler @@ -26,6 +26,7 @@ class ValaCompiler(Compiler): self.version = version self.id = 'valac' self.is_cross = False + self.base_options = ['b_colorout'] def name_string(self): return ' '.join(self.exelist) @@ -54,6 +55,11 @@ class ValaCompiler(Compiler): def get_werror_args(self): return ['--fatal-warnings'] + def get_colorout_args(self, colortype): + if version_compare(self.version, '>=0.37.1'): + return ['--color=' + colortype] + return [] + def sanity_check(self, work_dir, environment): code = 'class MesonSanityCheck : Object { }' args = self.get_cross_extra_flags(environment, link=False) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index dd9f56e..85473b1 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -309,8 +309,8 @@ class Environment: self.default_c = ['cl', 'cc', 'gcc', 'clang'] self.default_cpp = ['cl', 'c++', 'g++', 'clang++'] else: - self.default_c = ['cc'] - self.default_cpp = ['c++'] + self.default_c = ['cc', 'gcc', 'clang'] + self.default_cpp = ['c++', 'g++', 'clang++'] self.default_objc = ['cc'] self.default_objcpp = ['c++'] self.default_fortran = ['gfortran', 'g95', 'f95', 'f90', 'f77', 'ifort'] diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 1858e8c..16bf9ac 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -465,13 +465,10 @@ class InstallDir(InterpreterObject): class Man(InterpreterObject): - def __init__(self, source_subdir, sources, kwargs): + def __init__(self, sources, kwargs): InterpreterObject.__init__(self) - self.source_subdir = source_subdir self.sources = sources self.validate_sources() - if len(kwargs) > 1: - raise InvalidArguments('Man function takes at most one keyword arguments.') self.custom_install_dir = kwargs.get('install_dir', None) if self.custom_install_dir is not None and not isinstance(self.custom_install_dir, str): raise InterpreterException('Custom_install_dir must be a string.') @@ -491,9 +488,6 @@ class Man(InterpreterObject): def get_sources(self): return self.sources - def get_source_subdir(self): - return self.source_subdir - class GeneratedObjectsHolder(InterpreterObject): def __init__(self, held_object): super().__init__() @@ -2055,6 +2049,7 @@ class Interpreter(InterpreterBase): # we won't actually read all the build files. return fallback_dep if not dep: + assert(exception is not None) raise exception # Only store found-deps in the cache @@ -2303,8 +2298,12 @@ class Interpreter(InterpreterBase): raise InterpreterException('Incorrect number of arguments') if not isinstance(args[0], str): raise InterpreterException('First argument of test must be a string.') - if not isinstance(args[1], (ExecutableHolder, JarHolder, ExternalProgramHolder)): - raise InterpreterException('Second argument must be executable.') + exe = args[1] + if not isinstance(exe, (ExecutableHolder, JarHolder, ExternalProgramHolder)): + if isinstance(exe, mesonlib.File): + exe = self.func_find_program(node, (args[1], ), {}) + else: + raise InterpreterException('Second argument must be executable.') par = kwargs.get('is_parallel', True) if not isinstance(par, bool): raise InterpreterException('Keyword argument is_parallel must be a boolean.') @@ -2338,7 +2337,7 @@ class Interpreter(InterpreterBase): suite.append(self.subproject.replace(' ', '_').replace(':', '_') + s) else: suite.append(self.build.project_name.replace(' ', '_').replace(':', '_') + s) - t = Test(args[0], suite, args[1].held_object, par, cmd_args, env, should_fail, timeout, workdir) + t = Test(args[0], suite, exe.held_object, par, cmd_args, env, should_fail, timeout, workdir) if is_base_test: self.build.tests.append(t) mlog.debug('Adding test "', mlog.bold(args[0]), '".', sep='') @@ -2354,9 +2353,9 @@ class Interpreter(InterpreterBase): return h @permittedKwargs(permitted_kwargs['install_man']) - @stringArgs def func_install_man(self, node, args, kwargs): - m = Man(self.subdir, args, kwargs) + fargs = self.source_strings_to_files(args) + m = Man(fargs, kwargs) self.build.man.append(m) return m diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index addcab3..6bf8b7f 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -368,7 +368,7 @@ class GnomeModule(ExtensionModule): if lib.startswith("-W"): continue if gir_has_extra_lib_arg() and use_gir_args: - lib = lib.replace('-l', '--extra-library=') + lib = lib.replace('-l', '--extra-library=', 1) ldflags.update([lib]) if isinstance(dep, PkgConfigDependency): @@ -984,7 +984,7 @@ class GnomeModule(ExtensionModule): cmd += ['--prefix', value] elif arg == 'extra_args': if new_genmarshal: - cmd += mesonlib.stringlistify(value, []) + cmd += mesonlib.stringlistify(value) else: mlog.warning('The current version of GLib does not support extra arguments \n' 'for glib-genmarshal. You need at least GLib 2.53.3. See ', diff --git a/mesonbuild/modules/unstable_simd.py b/mesonbuild/modules/unstable_simd.py index 4aebc02..828afec 100644 --- a/mesonbuild/modules/unstable_simd.py +++ b/mesonbuild/modules/unstable_simd.py @@ -43,6 +43,12 @@ class SimdModule(ExtensionModule): raise mesonlib.MesonException('Argument must be a string.') if 'compiler' not in kwargs: raise mesonlib.MesonException('Must specify compiler keyword') + if 'sources' in kwargs: + raise mesonlib.MesonException('SIMD module does not support the "sources" keyword') + basic_kwargs = {} + for key, value in kwargs.items(): + if key not in self.isets and key != 'compiler': + basic_kwargs[key] = value compiler = kwargs['compiler'].compiler if not isinstance(compiler, compilers.compilers.Compiler): raise mesonlib.MesonException('Compiler argument must be a compiler object.') @@ -64,7 +70,14 @@ class SimdModule(ExtensionModule): conf.values['HAVE_' + iset.upper()] = ('1', 'Compiler supports %s.' % iset) libname = prefix + '_' + iset lib_kwargs = {'sources': iset_fname, - compiler.get_language() + '_args': args} + } + lib_kwargs.update(basic_kwargs) + langarg_key = compiler.get_language() + '_args' + old_lang_args = lib_kwargs.get(langarg_key, []) + if not isinstance(old_lang_args, list): + old_lang_args = [old_lang_args] + all_lang_args = old_lang_args + args + lib_kwargs[langarg_key] = all_lang_args result.append(interpreter.func_static_lib(None, [libname], lib_kwargs)) return [result, cdata] diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py index d949090..f61cbab 100644 --- a/mesonbuild/scripts/meson_install.py +++ b/mesonbuild/scripts/meson_install.py @@ -19,6 +19,36 @@ from . import destdir_join from ..mesonlib import is_windows, Popen_safe install_log_file = None +use_selinux = True + +class DirMaker: + def __init__(self): + self.dirs = [] + + def makedirs(self, path, exist_ok=False): + dirname = os.path.normpath(path) + dirs = [] + while dirname != os.path.dirname(dirname): + if not os.path.exists(dirname): + dirs.append(dirname) + dirname = os.path.dirname(dirname) + os.makedirs(path, exist_ok=exist_ok) + + # store the directories in creation order, with the parent directory + # before the child directories. Future calls of makedir() will not + # create the parent directories, so the last element in the list is + # the last one to be created. That is the first one to be removed on + # __exit__ + dirs.reverse() + self.dirs += dirs + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.dirs.reverse() + for d in self.dirs: + append_to_log(d) def set_mode(path, mode): if mode is None: @@ -53,6 +83,28 @@ def set_mode(path, mode): msg = '{!r}: Unable to set permissions {!r}: {}, ignoring...' print(msg.format(path, mode.perms_s, e.strerror)) +def restore_selinux_context(to_file): + ''' + Restores the SELinux context for @to_file + ''' + global use_selinux + + if not use_selinux: + return + + try: + subprocess.check_call(['selinuxenabled']) + try: + subprocess.check_call(['restorecon', '-F', to_file], stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError as e: + use_selinux = False + msg = "{!r}: Failed to restore SELinux context, ignoring SELinux context for all remaining files..." + print(msg.format(to_file, e.returncode)) + except (FileNotFoundError, subprocess.CalledProcessError) as e: + # If we don't have selinux or selinuxenabled returned 1, failure + # is ignored quietly. + use_selinux = False + def append_to_log(line): install_log_file.write(line) if not line.endswith('\n'): @@ -73,9 +125,10 @@ def do_copyfile(from_file, to_file): os.unlink(to_file) shutil.copyfile(from_file, to_file) shutil.copystat(from_file, to_file) + restore_selinux_context(to_file) append_to_log(to_file) -def do_copydir(src_prefix, src_dir, dst_dir): +def do_copydir(data, src_prefix, src_dir, dst_dir): ''' Copies the directory @src_prefix (full path) into @dst_dir @@ -91,7 +144,7 @@ def do_copydir(src_prefix, src_dir, dst_dir): if os.path.exists(abs_dst): print('Tried to copy directory %s but a file of that name already exists.' % abs_dst) sys.exit(1) - os.makedirs(abs_dst) + data.dirmaker.makedirs(abs_dst) shutil.copystat(abs_src, abs_dst) for f in files: abs_src = os.path.join(src_dir, root, f) @@ -121,23 +174,24 @@ def do_install(datafilename): d.destdir = os.environ.get('DESTDIR', '') d.fullprefix = destdir_join(d.destdir, d.prefix) - install_subdirs(d) # Must be first, because it needs to delete the old subtree. - install_targets(d) - install_headers(d) - install_man(d) - install_data(d) - run_install_script(d) + d.dirmaker = DirMaker() + with d.dirmaker: + install_subdirs(d) # Must be first, because it needs to delete the old subtree. + install_targets(d) + install_headers(d) + install_man(d) + install_data(d) + run_install_script(d) -def install_subdirs(data): - for (src_dir, inst_dir, dst_dir, mode) in data.install_subdirs: +def install_subdirs(d): + for (src_dir, inst_dir, dst_dir, mode) in d.install_subdirs: if src_dir.endswith('/') or src_dir.endswith('\\'): src_dir = src_dir[:-1] src_prefix = os.path.join(src_dir, inst_dir) print('Installing subdir %s to %s' % (src_prefix, dst_dir)) - dst_dir = get_destdir_path(data, dst_dir) - if not os.path.exists(dst_dir): - os.makedirs(dst_dir) - do_copydir(src_prefix, src_dir, dst_dir) + dst_dir = get_destdir_path(d, dst_dir) + d.dirmaker.makedirs(dst_dir, exist_ok=True) + do_copydir(d, src_prefix, src_dir, dst_dir) dst_prefix = os.path.join(dst_dir, inst_dir) set_mode(dst_prefix, mode) @@ -147,7 +201,7 @@ def install_data(d): outfilename = get_destdir_path(d, i[1]) mode = i[2] outdir = os.path.split(outfilename)[0] - os.makedirs(outdir, exist_ok=True) + d.dirmaker.makedirs(outdir, exist_ok=True) print('Installing %s to %s' % (fullfilename, outdir)) do_copyfile(fullfilename, outfilename) set_mode(outfilename, mode) @@ -157,7 +211,7 @@ def install_man(d): full_source_filename = m[0] outfilename = get_destdir_path(d, m[1]) outdir = os.path.split(outfilename)[0] - os.makedirs(outdir, exist_ok=True) + d.dirmaker.makedirs(outdir, exist_ok=True) print('Installing %s to %s' % (full_source_filename, outdir)) if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'): with open(outfilename, 'wb') as of: @@ -175,7 +229,7 @@ def install_headers(d): outdir = get_destdir_path(d, t[1]) outfilename = os.path.join(outdir, fname) print('Installing %s to %s' % (fname, outdir)) - os.makedirs(outdir, exist_ok=True) + d.dirmaker.makedirs(outdir, exist_ok=True) do_copyfile(fullfilename, outfilename) def run_install_script(d): @@ -240,7 +294,7 @@ def install_targets(d): should_strip = t[3] install_rpath = t[4] print('Installing %s to %s' % (fname, outname)) - os.makedirs(outdir, exist_ok=True) + d.dirmaker.makedirs(outdir, exist_ok=True) if not os.path.exists(fname): raise RuntimeError('File {!r} could not be found'.format(fname)) elif os.path.isfile(fname): @@ -263,7 +317,7 @@ def install_targets(d): do_copyfile(pdb_filename, pdb_outname) elif os.path.isdir(fname): fname = os.path.join(d.build_dir, fname.rstrip('/')) - do_copydir(fname, os.path.dirname(fname), outdir) + do_copydir(d, fname, os.path.dirname(fname), outdir) else: raise RuntimeError('Unknown file type for {!r}'.format(fname)) printed_symlink_error = False diff --git a/mesonbuild/scripts/uninstall.py b/mesonbuild/scripts/uninstall.py index 1480921..bdc036b 100644 --- a/mesonbuild/scripts/uninstall.py +++ b/mesonbuild/scripts/uninstall.py @@ -24,7 +24,10 @@ def do_uninstall(log): continue fname = line.strip() try: - os.unlink(fname) + if os.path.isdir(fname) and not os.path.islink(fname): + os.rmdir(fname) + else: + os.unlink(fname) print('Deleted:', fname) successes += 1 except Exception as e: diff --git a/run_project_tests.py b/run_project_tests.py index 69a778e..d7ad257 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -420,14 +420,17 @@ def have_d_compiler(): def have_objc_compiler(): with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: env = environment.Environment(None, build_dir, None, get_fake_options('/'), []) - objc_comp = env.detect_objc_compiler(False) + try: + objc_comp = env.detect_objc_compiler(False) + except: + return False if not objc_comp: return False try: objc_comp.sanity_check(env.get_scratch_dir(), env) + objcpp_comp = env.detect_objc_compiler(False) except: return False - objcpp_comp = env.detect_objc_compiler(False) if not objcpp_comp: return False try: diff --git a/test cases/common/10 man install/baz.1.in b/test cases/common/10 man install/baz.1.in new file mode 100644 index 0000000..d0b79b4 --- /dev/null +++ b/test cases/common/10 man install/baz.1.in @@ -0,0 +1,6 @@ +This is a man page of baz.1 it was generated @TODAY@. + +You should not put generation timestamps in real world projects +because they break reproducible builds. This manpage is written +by professionals or under the supervision of professionals. Do +not try this at home. diff --git a/test cases/common/10 man install/installed_files.txt b/test cases/common/10 man install/installed_files.txt index 7b19616..c13baa4 100644 --- a/test cases/common/10 man install/installed_files.txt +++ b/test cases/common/10 man install/installed_files.txt @@ -2,3 +2,4 @@ usr/share/man/man1/foo.1.gz usr/share/man/man2/bar.2.gz usr/share/man/man1/vanishing.1.gz usr/share/man/man2/vanishing.2.gz +usr/share/man/man1/baz.1.gz diff --git a/test cases/common/10 man install/meson.build b/test cases/common/10 man install/meson.build index 8436fa5..8262ffc 100644 --- a/test cases/common/10 man install/meson.build +++ b/test cases/common/10 man install/meson.build @@ -3,3 +3,11 @@ m1 = install_man('foo.1') m2 = install_man('bar.2') install_man('vanishing/vanishing.2') subdir('vanishing') + +cdata = configuration_data() +cdata.set('TODAY', '$this_day') +b1 = configure_file(input : 'baz.1.in', + output : 'baz.1', + configuration : cdata) + +install_man(b1) diff --git a/test cases/common/111 has header symbol/meson.build b/test cases/common/111 has header symbol/meson.build index 2a9f5d4..54cedce 100644 --- a/test cases/common/111 has header symbol/meson.build +++ b/test cases/common/111 has header symbol/meson.build @@ -14,8 +14,9 @@ foreach comp : [cc, cpp] assert (not comp.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header') endforeach -# This is likely only available on Glibc, so just test for it -if cc.has_function('ppoll') +# This is available on Glibc, Solaris & the BSD's, so just test for _GNU_SOURCE +# on Linux +if cc.has_function('ppoll') and host_machine.system() == 'linux' assert (not cc.has_header_symbol('poll.h', 'ppoll'), 'ppoll should not be accessible without _GNU_SOURCE') assert (cc.has_header_symbol('poll.h', 'ppoll', prefix : '#define _GNU_SOURCE'), 'ppoll should be accessible with _GNU_SOURCE') endif diff --git a/test cases/common/126 llvm ir and assembly/square-arm.S b/test cases/common/126 llvm ir and assembly/square-arm.S index 58a5b1b..e66fa47 100644 --- a/test cases/common/126 llvm ir and assembly/square-arm.S +++ b/test cases/common/126 llvm ir and assembly/square-arm.S @@ -2,6 +2,9 @@ .text .globl SYMBOL_NAME(square_unsigned) +# ifdef __linux__ +.type square_unsigned, %function +#endif SYMBOL_NAME(square_unsigned): mul r1, r0, r0 diff --git a/test cases/common/126 llvm ir and assembly/square-x86.S b/test cases/common/126 llvm ir and assembly/square-x86.S index b38da4f..7d1202a 100644 --- a/test cases/common/126 llvm ir and assembly/square-x86.S +++ b/test cases/common/126 llvm ir and assembly/square-x86.S @@ -23,6 +23,9 @@ END .text .globl SYMBOL_NAME(square_unsigned) +# ifdef __linux__ +.type square_unsigned, %function +#endif SYMBOL_NAME(square_unsigned): movl 4(%esp), %eax diff --git a/test cases/common/126 llvm ir and assembly/square-x86_64.S b/test cases/common/126 llvm ir and assembly/square-x86_64.S index 1452f47..09cc7a4 100644 --- a/test cases/common/126 llvm ir and assembly/square-x86_64.S +++ b/test cases/common/126 llvm ir and assembly/square-x86_64.S @@ -18,6 +18,9 @@ END .text .globl SYMBOL_NAME(square_unsigned) +# ifdef __linux__ +.type square_unsigned, %function +#endif # if defined(_WIN32) || defined(__CYGWIN__) /* msabi */ SYMBOL_NAME(square_unsigned): diff --git a/test cases/common/146 C and CPP link/meson.build b/test cases/common/146 C and CPP link/meson.build index af40de7..db84445 100644 --- a/test cases/common/146 C and CPP link/meson.build +++ b/test cases/common/146 C and CPP link/meson.build @@ -60,3 +60,15 @@ libfoo = shared_library( ['foobar.c', 'foobar.h'], link_with : [libc, libcpp], ) + +# Test that link_whole is also honored +# +# VS2010 lacks the /WHOLEARCHIVE option that later versions of MSVC support, so +# don't run this tests on that backend. +if meson.backend() != 'vs2010' + libfoowhole = shared_library( + 'foowhole', + ['foobar.c', 'foobar.h'], + link_whole : [libc, libcpp], + ) +endif diff --git a/test cases/common/155 simd/include/simdheader.h b/test cases/common/155 simd/include/simdheader.h new file mode 100644 index 0000000..6515e41 --- /dev/null +++ b/test cases/common/155 simd/include/simdheader.h @@ -0,0 +1,3 @@ +#pragma once + +#define I_CAN_HAZ_SIMD diff --git a/test cases/common/155 simd/meson.build b/test cases/common/155 simd/meson.build index 9da1651..2628a12 100644 --- a/test cases/common/155 simd/meson.build +++ b/test cases/common/155 simd/meson.build @@ -28,7 +28,8 @@ rval = simd.check('mysimds', avx : 'simd_avx.c', avx2 : 'simd_avx2.c', neon : 'simd_neon.c', - compiler : cc) + compiler : cc, + include_directories : include_directories('include')) simdlibs = rval[0] cdata.merge_from(rval[1]) diff --git a/test cases/common/155 simd/simd_avx.c b/test cases/common/155 simd/simd_avx.c index 989620b..1c84dae 100644 --- a/test cases/common/155 simd/simd_avx.c +++ b/test cases/common/155 simd/simd_avx.c @@ -1,3 +1,9 @@ +#include<simdheader.h> + +#ifndef I_CAN_HAZ_SIMD +#error The correct internal header was not used +#endif + #include<simdconfig.h> #include<simdfuncs.h> #include<stdint.h> diff --git a/test cases/common/157 configure file in test/meson.build b/test cases/common/157 configure file in test/meson.build new file mode 100644 index 0000000..9028101 --- /dev/null +++ b/test cases/common/157 configure file in test/meson.build @@ -0,0 +1,9 @@ +project('conf file in test') + +test_file = configure_file( + input: 'test.py.in', + output: 'test.py', + configuration: configuration_data() +) + +test('configure-file', test_file) diff --git a/test cases/common/157 configure file in test/test.py.in b/test cases/common/157 configure file in test/test.py.in new file mode 100755 index 0000000..15a61f5 --- /dev/null +++ b/test cases/common/157 configure file in test/test.py.in @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +import sys +sys.exit(0) diff --git a/test cases/linuxlike/9 compiler checks with dependencies/meson.build b/test cases/linuxlike/9 compiler checks with dependencies/meson.build index 2aa9015..bebfb84 100644 --- a/test cases/linuxlike/9 compiler checks with dependencies/meson.build +++ b/test cases/linuxlike/9 compiler checks with dependencies/meson.build @@ -29,3 +29,10 @@ int main(int argc, char *argv[]) { assert (cc.has_function('deflate', prefix : '#include<zlib.h>', dependencies : zlib, name : 'Test for function in zlib'), 'has_function test failed.') assert (cc.links(linkcode, dependencies : zlib, name : 'Test link against zlib'), 'Linking test failed against zlib.') endif + +assert(cc.has_function('pthread_create', + dependencies : dependency('threads'), + prefix : '#include <pthread.h>'), + 'Could not detect pthread_create with a thread dependency.') + + diff --git a/tools/ac_converter.py b/tools/ac_converter.py index eda5097..739c42c 100755 --- a/tools/ac_converter.py +++ b/tools/ac_converter.py @@ -14,7 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""This script reads config.h.meson, looks for header +help_message = """Usage: %s <config.h.meson> + +This script reads config.h.meson, looks for header checks and writes the corresponding meson declaration. Copy config.h.in to config.h.meson, replace #undef @@ -364,6 +366,11 @@ function_data = \ headers = [] functions = [] sizes = [] + +if len(sys.argv) != 2: + print(help_message % sys.argv[0]) + sys.exit(0) + with open(sys.argv[1]) as f: for line in f: line = line.strip() |