diff options
41 files changed, 730 insertions, 43 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index 6551445..77d00af 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -76,6 +76,17 @@ install: - ps: If($Env:compiler -eq 'msys2-mingw') {(new-object Net.WebClient).DownloadFile('https://bootstrap.pypa.io/get-pip.py', 'C:\projects\meson\get-pip.py')} - cmd: if %compiler%==msys2-mingw ( %PYTHON% "C:\projects\meson\get-pip.py" ) - cmd: if %compiler%==cygwin ( call ci\appveyor-install.bat ) + - ps: | + If($Env:compiler -like 'msvc*') { + (new-object net.webclient).DownloadFile( + "https://download.microsoft.com/download/D/B/B/DBB64BA1-7B51-43DB-8BF1-D1FB45EACF7A/msmpisdk.msi", + "C:\projects\msmpisdk.msi") + c:\windows\system32\msiexec.exe /i C:\projects\msmpisdk.msi /quiet + (new-object net.webclient).DownloadFile( + "https://download.microsoft.com/download/D/B/B/DBB64BA1-7B51-43DB-8BF1-D1FB45EACF7A/MSMpiSetup.exe", + "C:\projects\MSMpiSetup.exe") + c:\projects\MSMpiSetup.exe -unattend -full + } # Install additional packages needed for all builds. - cmd: "%WRAPPER% %PYTHON% -m pip install codecov" diff --git a/ciimage/Dockerfile b/ciimage/Dockerfile index 23edb79..3789e8d 100644 --- a/ciimage/Dockerfile +++ b/ciimage/Dockerfile @@ -9,5 +9,5 @@ RUN apt-get -y update && apt-get -y upgrade \ && 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 \ +&& apt-get -y install libvulkan-dev libpcap-dev \ && python3 -m pip install hotdoc codecov diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index 1851233..401e019 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -51,6 +51,21 @@ If your boost headers or libraries are in non-standard locations you can set the GTest and GMock come as sources that must be compiled as part of your project. With Meson you don't have to care about the details, just pass `gtest` or `gmock` to `dependency` and it will do everything for you. If you want to use GMock, it is recommended to use GTest as well, as getting it to work standalone is tricky. +## MPI ## + +MPI is supported for C, C++ and Fortran. Because dependencies are +language-specific, you must specify the requested language using the +`language` keyword argument, i.e., + * `dependency('mpi', language='c')` for the C MPI headers and libraries + * `dependency('mpi', language='cpp')` for the C++ MPI headers and libraries + * `dependency('mpi', language='fortran')` for the Fortran MPI headers and libraries + +Meson prefers pkg-config for MPI, but if your MPI implementation does not +provide them, it will search for the standard wrapper executables, `mpic`, +`mpicxx`, `mpic++`, `mpifort`, `mpif90`, `mpif77`. If these are not in your +path, they can be specified by setting the standard environment variables +`MPICC`, `MPICXX`, `MPIFC`, `MPIF90`, or `MPIF77`, during configuration. + ## Qt5 ## Meson has native Qt5 support. Its usage is best demonstrated with an example. diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 1a98c4c..84b2fb1 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -193,6 +193,7 @@ Finds an external dependency with the given name with `pkg-config` if possible a - `fallback` specifies a subproject fallback to use in case the dependency is not found in the system. The value is an array `['subproj_name', 'subproj_dep']` where the first value is the name of the subproject and the second is the variable name in that subproject that contains the value of [`declare_dependency`](#declare_dependency). - `default_options` *(added 0.37.0)* an array of option values that override those set in the project's `default_options` invocation (like `default_options` in [`project()`](#project), they only have effect when Meson is run for the first time, and command line arguments override any default options in build files) - `method` defines the way the dependency is detected, the default is `auto` but can be overridden to be e.g. `qmake` for Qt development, and different dependencies support different values for this (though `auto` will work on all of them) +- `language` *(added 0.42.0)* defines what language-specific dependency to find if it's available for multiple languages. The returned object also has methods that are documented in the [object methods section](#dependency-object) below. @@ -250,6 +251,7 @@ Executable supports the following keyword arguments. Note that just like the pos - `build_by_default` causes, when set to true, to have this target be built by default, that is, when invoking plain `ninja`, the default value is true for all built target types, since 0.38.0 - `override_options` takes an array of strings in the same format as `project`'s `default_options` overriding the values of these options for this target only, since 0.40.0 - `implib` when set to true, an import library is generated for the executable (the name of the import library is based on *exe_name*). Alternatively, when set to a string, that gives the base name for the import library. The import library is used when the returned build target object appears in `link_with:` elsewhere. Only has any effect on platforms where that is meaningful (e.g. Windows). Since 0.42.0 +- `implicit_include_directories` is a boolean telling whether Meson adds the current source and build directories to the include path, defaults to `true`, since 0.42.0 The list of `sources`, `objects`, and `dependencies` is always flattened, which means you can freely nest and add lists while creating the final list. As a corollary, the best way to handle a 'disabled dependency' is by assigning an empty list `[]` to it and passing it like any other dependency to the `dependencies:` keyword argument. @@ -473,11 +475,19 @@ Installs the specified man files from the source tree into system's man director ### install_subdir() ``` meson - void install_subdir(subdir_name) + void install_subdir(subdir_name, install_dir : ..., exclude_files : ..., exclude_directories : ...) ``` Installs the entire given subdirectory and its contents from the source tree to the location specified by the keyword argument `install_dir`. Note that due to implementation issues this command deletes the entire target dir before copying the files, so you should never use `install_subdir` to install into two overlapping directories (such as `foo` and `foo/bar`) because if you do the behavior is undefined. +The following keyword arguments are supported: + +- `install_dir`: the location to place the installed subdirectory. +- `exclude_files`: a list of file names that should not be installed. + Names are interpreted as paths relative to the `subdir_name` location. +- `exclude_directories`: a list of directory names that should not be installed. + Names are interpreted as paths relative to the `subdir_name` location. + ### is_variable() ``` meson diff --git a/docs/markdown/Release-notes-for-0.42.0.md b/docs/markdown/Release-notes-for-0.42.0.md index 78a5917..5472341 100644 --- a/docs/markdown/Release-notes-for-0.42.0.md +++ b/docs/markdown/Release-notes-for-0.42.0.md @@ -83,10 +83,47 @@ flag manually, e.g. via `link_args` to a target. This is not recommended because having multiple rpath causes them to stomp on each other. This warning will become a hard error in some future release. +## Vulkan dependency module + +Vulkan can now be used as native dependency. The dependency module +will detect the VULKAN_SDK environment variable or otherwise try to +receive the vulkan library and header via pkgconfig or from the +system. + +## Limiting the maximum number of linker processes + +With the Ninja backend it is now possible to limit the maximum number of +concurrent linker processes. This is usually only needed for projects +that have many large link steps that cause the system to run out of +memory if they are run in parallel. This limit can be set with the +new `backend_max_links` option. + +## Disable implicit include directories + +By default Meson adds the current source and build directories to the +header search path. On some rare occasions this is not desired. Setting +the `implicit_include_directories` keyword argument to `false` these +directories are not used. + +## Support for MPI dependency + +MPI is now supported as a dependency. Because dependencies are +language-specific, you must specify the requested language with the +`language` keyword, i.e., `dependency('mpi', language='c')` will +request the C MPI headers and libraries. See [the MPI +dependency](Dependencies.md#mpi) for more information. + +## Allow excluding files or directories from `install_subdir` + +The [`install_subdir`](Reference-manual.md#install_subdir) command +accepts the new `exclude_files` and `exclude_directories` keyword +arguments that allow specified files or directories to be excluded +from the installed subdirectory. + ## Make all Meson functionality invokable via the main executable Previously Meson had multiple executables such as `mesonintrospect` -and `mesontest`. Thes are now invokable via the main Meson executable +and `mesontest`. They are now invokable via the main Meson executable like this: meson configure <arguments> # equivalent to mesonconf <options> diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 287b683..a0fd90a 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -813,7 +813,7 @@ int dummy; inst_dir = sd.installable_subdir src_dir = os.path.join(self.environment.get_source_dir(), subdir) dst_dir = os.path.join(self.environment.get_prefix(), sd.install_dir) - d.install_subdirs.append([src_dir, inst_dir, dst_dir, sd.install_mode]) + d.install_subdirs.append([src_dir, inst_dir, dst_dir, sd.install_mode, sd.exclude]) def generate_tests(self, outfile): self.serialize_tests() @@ -842,6 +842,12 @@ int dummy; outfile.write('# Rules for compiling.\n\n') self.generate_compile_rules(outfile) outfile.write('# Rules for linking.\n\n') + num_pools = self.environment.coredata.backend_options['backend_max_links'].value + if num_pools > 0: + outfile.write('''pool link_pool + depth = %d + +''' % num_pools) if self.environment.is_cross_build(): self.generate_static_link_rules(True, outfile) self.generate_static_link_rules(False, outfile) @@ -1369,6 +1375,7 @@ int dummy; raise MesonException('Swift supports only executable and static library targets.') def generate_static_link_rules(self, is_cross, outfile): + num_pools = self.environment.coredata.backend_options['backend_max_links'].value if 'java' in self.build.compilers: if not is_cross: self.generate_java_link(outfile) @@ -1412,9 +1419,12 @@ int dummy; description = ' description = Linking static target $out.\n\n' outfile.write(rule) outfile.write(command) + if num_pools > 0: + outfile.write(' pool = link_pool\n') outfile.write(description) def generate_dynamic_link_rules(self, outfile): + num_pools = self.environment.coredata.backend_options['backend_max_links'].value ctypes = [(self.build.compilers, False)] if self.environment.is_cross_build(): if self.environment.cross_info.need_cross_compiler(): @@ -1452,9 +1462,11 @@ int dummy; cross_args=' '.join(cross_args), output_args=' '.join(compiler.get_linker_output_args('$out')) ) - description = ' description = Linking target $out.' + description = ' description = Linking target $out.\n' outfile.write(rule) outfile.write(command) + if num_pools > 0: + outfile.write(' pool = link_pool\n') outfile.write(description) outfile.write('\n') outfile.write('\n') @@ -2034,9 +2046,11 @@ rule FORTRAN_DEP_HACK # srcdir == builddir Autotools build in their source tree. Many # projects that are moving to Meson have both Meson and Autotools in # parallel as part of the transition. - commands += self.get_source_dir_include_args(target, compiler) + if target.implicit_include_directories: + commands += self.get_source_dir_include_args(target, compiler) commands += self.get_custom_target_dir_include_args(target, compiler) - commands += self.get_build_dir_include_args(target, compiler) + if target.implicit_include_directories: + commands += self.get_build_dir_include_args(target, compiler) # Finally add the private dir for the target to the include path. This # must override everything else and must be the final path added. commands += compiler.get_include_args(self.get_target_private_dir(target), False) @@ -2264,7 +2278,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() @@ -2281,7 +2295,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/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 4a92155..28c0f76 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -793,9 +793,13 @@ class Vs2010Backend(backends.Backend): # target private dir, target build dir, generated sources include dirs, # target source dir for args in file_args.values(): - t_inc_dirs = ['.', self.relpath(self.get_target_private_dir(target), - self.get_target_dir(target))] - t_inc_dirs += generated_files_include_dirs + [proj_to_src_dir] + t_inc_dirs = [self.relpath(self.get_target_private_dir(target), + self.get_target_dir(target))] + if target.implicit_include_directories: + t_inc_dirs += ['.'] + t_inc_dirs += generated_files_include_dirs + if target.implicit_include_directories: + t_inc_dirs += [proj_to_src_dir] args += ['-I' + arg for arg in t_inc_dirs] # Split preprocessor defines and include directories out of the list of diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 58cf987..89689d7 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 @@ -41,6 +42,7 @@ known_basic_kwargs = {'install': True, 'link_depends': True, 'link_with': True, 'link_whole': True, + 'implicit_include_directories': True, 'include_directories': True, 'dependencies': True, 'install_dir': True, @@ -760,6 +762,9 @@ This will become a hard error in a future Meson release.''') self.pic = kwargs.get('pic', False) if not isinstance(self.pic, bool): raise InvalidArguments('Argument pic to static library {!r} must be boolean'.format(self.name)) + self.implicit_include_directories = kwargs.get('implicit_include_directories', True) + if not isinstance(self.implicit_include_directories, bool): + raise InvalidArguments('Implicit_include_directories must be a boolean.') def get_filename(self): return self.filename @@ -936,7 +941,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/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/fortran.py b/mesonbuild/compilers/fortran.py index e17cda0..49200bb 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -120,6 +120,9 @@ end program prog def get_include_args(self, path, is_system): return ['-I' + path] + def get_module_incdir_args(self): + return ('-I', ) + def get_module_outdir_args(self, path): return ['-J' + path] @@ -209,6 +212,9 @@ class SunFortranCompiler(FortranCompiler): def get_warn_args(self, level): return [] + def get_module_incdir_args(self): + return ('-M', ) + def get_module_outdir_args(self, path): return ['-moddir=' + path] @@ -251,6 +257,9 @@ class PGIFortranCompiler(FortranCompiler): super().__init__(exelist, version, is_cross, exe_wrapper=None) self.id = 'pgi' + def get_module_incdir_args(self): + return ('-module', ) + def get_module_outdir_args(self, path): return ['-module', path] diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 80ad94f..d39270b 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -85,6 +85,36 @@ class UserBooleanOption(UserOption): def validate_value(self, value): return self.tobool(value) +class UserIntegerOption(UserOption): + def __init__(self, name, description, min_value, max_value, value): + super().__init__(name, description, [True, False]) + self.min_value = min_value + self.max_value = max_value + self.set_value(value) + + def set_value(self, newvalue): + if isinstance(newvalue, str): + newvalue = self.toint(newvalue) + if not isinstance(newvalue, int): + raise MesonException('New value for integer option is not an integer.') + if self.min_value is not None and newvalue < self.min_value: + raise MesonException('New value %d is less than minimum value %d.' % (newvalue, self.min_value)) + if self.max_value is not None and newvalue > self.max_value: + raise MesonException('New value %d is more than maximum value %d.' % (newvalue, self.max_value)) + self.value = newvalue + + def toint(self, valuestring): + try: + return int(valuestring) + except: + raise MesonException('Value string "%s" is not convertable to an integer.' % valuestring) + + def parse_string(self, valuestring): + return self.toint(valuestring) + + def validate_value(self, value): + return self.toint(value) + class UserComboOption(UserOption): def __init__(self, name, description, choices, value): super().__init__(name, description, choices) @@ -145,6 +175,7 @@ class CoreData: self.target_guids = {} self.version = version self.init_builtins(options) + self.init_backend_options(self.builtins['backend'].value) self.user_options = {} self.compiler_options = {} self.base_options = {} @@ -218,6 +249,13 @@ class CoreData: args = [key] + builtin_options[key][1:-1] + [value] self.builtins[key] = builtin_options[key][0](*args) + def init_backend_options(self, backend_name): + self.backend_options = {} + if backend_name == 'ninja': + self.backend_options['backend_max_links'] = UserIntegerOption('backend_max_links', + 'Maximum number of linker processes to run or 0 for no limit', + 0, None, 0) + def get_builtin_option(self, optname): if optname in self.builtins: return self.builtins[optname].value diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index 3d41a2b..c16b92e 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -15,11 +15,11 @@ from .base import ( # noqa: F401 Dependency, DependencyException, DependencyMethods, ExternalProgram, ExternalDependency, ExternalLibrary, ExtraFrameworkDependency, InternalDependency, - PkgConfigDependency, find_external_dependency, get_dep_identifier, packages) + PkgConfigDependency, find_external_dependency, get_dep_identifier, packages, _packages_accept_language) from .dev import GMockDependency, GTestDependency, LLVMDependency, ValgrindDependency -from .misc import BoostDependency, Python3Dependency, ThreadDependency +from .misc import (BoostDependency, MPIDependency, Python3Dependency, ThreadDependency) from .platform import AppleFrameworks -from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency +from .ui import GLDependency, GnuStepDependency, Qt4Dependency, Qt5Dependency, SDL2Dependency, WxDependency, VulkanDependency packages.update({ @@ -31,6 +31,7 @@ packages.update({ # From misc: 'boost': BoostDependency, + 'mpi': MPIDependency, 'python3': Python3Dependency, 'threads': ThreadDependency, @@ -44,4 +45,8 @@ packages.update({ 'qt5': Qt5Dependency, 'sdl2': SDL2Dependency, 'wxwidgets': WxDependency, + 'vulkan': VulkanDependency, +}) +_packages_accept_language.update({ + 'mpi', }) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index f98de44..1f18c52 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -26,8 +26,9 @@ from .. import mesonlib from ..mesonlib import MesonException, Popen_safe, flatten, version_compare_many -# This must be defined in this file to avoid cyclical references. +# These must be defined in this file to avoid cyclical references. packages = {} +_packages_accept_language = set() class DependencyException(MesonException): @@ -610,10 +611,15 @@ def find_external_dependency(name, env, kwargs): raise DependencyException('Keyword "method" must be a string.') lname = name.lower() if lname in packages: + if lname not in _packages_accept_language and 'language' in kwargs: + raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, )) dep = packages[lname](env, kwargs) if required and not dep.found(): raise DependencyException('Dependency "%s" not found' % name) return dep + if 'language' in kwargs: + # Remove check when PkgConfigDependency supports language. + raise DependencyException('%s dependency does not accept "language" keyword argument' % (lname, )) pkg_exc = None pkgdep = None try: diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py index 99df587..f5cbb96 100644 --- a/mesonbuild/dependencies/misc.py +++ b/mesonbuild/dependencies/misc.py @@ -16,6 +16,8 @@ import glob import os +import re +import shlex import stat import sysconfig @@ -24,7 +26,7 @@ from .. import mesonlib from ..environment import detect_cpu_family from .base import DependencyException, DependencyMethods -from .base import ExternalDependency, ExtraFrameworkDependency, PkgConfigDependency +from .base import ExternalDependency, ExternalProgram, ExtraFrameworkDependency, PkgConfigDependency class BoostDependency(ExternalDependency): @@ -277,6 +279,210 @@ class BoostDependency(ExternalDependency): return 'thread' in self.requested_modules +class MPIDependency(ExternalDependency): + def __init__(self, environment, kwargs): + language = kwargs.get('language', 'c') + super().__init__('mpi', environment, language, kwargs) + required = kwargs.pop('required', True) + kwargs['required'] = False + kwargs['silent'] = True + self.is_found = False + + # NOTE: Only OpenMPI supplies a pkg-config file at the moment. + if language == 'c': + env_vars = ['MPICC'] + pkgconfig_files = ['ompi-c'] + default_wrappers = ['mpicc'] + elif language == 'cpp': + env_vars = ['MPICXX'] + pkgconfig_files = ['ompi-cxx'] + default_wrappers = ['mpic++', 'mpicxx', 'mpiCC'] + elif language == 'fortran': + env_vars = ['MPIFC', 'MPIF90', 'MPIF77'] + pkgconfig_files = ['ompi-fort'] + default_wrappers = ['mpifort', 'mpif90', 'mpif77'] + else: + raise DependencyException('Language {} is not supported with MPI.'.format(language)) + + for pkg in pkgconfig_files: + try: + pkgdep = PkgConfigDependency(pkg, environment, kwargs) + if pkgdep.found(): + self.compile_args = pkgdep.get_compile_args() + self.link_args = pkgdep.get_link_args() + self.version = pkgdep.get_version() + self.is_found = True + break + except Exception: + pass + + if not self.is_found: + # Prefer environment. + for var in env_vars: + if var in os.environ: + wrappers = [os.environ[var]] + break + else: + # Or search for default wrappers. + wrappers = default_wrappers + + for prog in wrappers: + result = self._try_openmpi_wrapper(prog) + if result is not None: + self.is_found = True + self.version = result[0] + self.compile_args = self._filter_compile_args(result[1]) + self.link_args = self._filter_link_args(result[2]) + break + result = self._try_other_wrapper(prog) + if result is not None: + self.is_found = True + self.version = result[0] + self.compile_args = self._filter_compile_args(result[1]) + self.link_args = self._filter_link_args(result[2]) + break + + if not self.is_found and mesonlib.is_windows(): + result = self._try_msmpi() + if result is not None: + self.is_found = True + self.version, self.compile_args, self.link_args = result + + if self.is_found: + mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.green('YES'), self.version) + else: + mlog.log('Dependency', mlog.bold(self.name), 'for', self.language, 'found:', mlog.red('NO')) + if required: + raise DependencyException('MPI dependency {!r} not found'.format(self.name)) + + def _filter_compile_args(self, args): + """ + MPI wrappers return a bunch of garbage args. + Drop -O2 and everything that is not needed. + """ + result = [] + multi_args = ('-I', ) + if self.language == 'fortran': + fc = self.env.coredata.compilers['fortran'] + multi_args += fc.get_module_incdir_args() + + include_next = False + for f in args: + if f.startswith(('-D', '-f') + multi_args) or f == '-pthread' \ + or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')): + result.append(f) + if f in multi_args: + # Path is a separate argument. + include_next = True + elif include_next: + include_next = False + result.append(f) + return result + + def _filter_link_args(self, args): + """ + MPI wrappers return a bunch of garbage args. + Drop -O2 and everything that is not needed. + """ + result = [] + include_next = False + for f in args: + if f.startswith(('-L', '-l', '-Xlinker')) or f == '-pthread' \ + or (f.startswith('-W') and f != '-Wall' and not f.startswith('-Werror')): + result.append(f) + if f in ('-L', '-Xlinker'): + include_next = True + elif include_next: + include_next = False + result.append(f) + return result + + def _try_openmpi_wrapper(self, prog): + prog = ExternalProgram(prog, silent=True) + if prog.found(): + cmd = prog.get_command() + ['--showme:compile'] + p, o, e = mesonlib.Popen_safe(cmd) + p.wait() + if p.returncode != 0: + mlog.debug('Command', mlog.bold(cmd), 'failed to run:') + mlog.debug(mlog.bold('Standard output\n'), o) + mlog.debug(mlog.bold('Standard error\n'), e) + return + cargs = shlex.split(o) + + cmd = prog.get_command() + ['--showme:link'] + p, o, e = mesonlib.Popen_safe(cmd) + p.wait() + if p.returncode != 0: + mlog.debug('Command', mlog.bold(cmd), 'failed to run:') + mlog.debug(mlog.bold('Standard output\n'), o) + mlog.debug(mlog.bold('Standard error\n'), e) + return + libs = shlex.split(o) + + cmd = prog.get_command() + ['--showme:version'] + p, o, e = mesonlib.Popen_safe(cmd) + p.wait() + if p.returncode != 0: + mlog.debug('Command', mlog.bold(cmd), 'failed to run:') + mlog.debug(mlog.bold('Standard output\n'), o) + mlog.debug(mlog.bold('Standard error\n'), e) + return + version = re.search('\d+.\d+.\d+', o) + if version: + version = version.group(0) + else: + version = 'none' + + return version, cargs, libs + + def _try_other_wrapper(self, prog): + prog = ExternalProgram(prog, silent=True) + if prog.found(): + cmd = prog.get_command() + ['-show'] + p, o, e = mesonlib.Popen_safe(cmd) + p.wait() + if p.returncode != 0: + mlog.debug('Command', mlog.bold(cmd), 'failed to run:') + mlog.debug(mlog.bold('Standard output\n'), o) + mlog.debug(mlog.bold('Standard error\n'), e) + return + args = shlex.split(o) + + version = 'none' + + return version, args, args + + def _try_msmpi(self): + if self.language == 'cpp': + # MS-MPI does not support the C++ version of MPI, only the standard C API. + return + if 'MSMPI_INC' not in os.environ: + return + incdir = os.environ['MSMPI_INC'] + arch = detect_cpu_family(self.env.coredata.compilers) + if arch == 'x86': + if 'MSMPI_LIB32' not in os.environ: + return + libdir = os.environ['MSMPI_LIB32'] + post = 'x86' + elif arch == 'x86_64': + if 'MSMPI_LIB64' not in os.environ: + return + libdir = os.environ['MSMPI_LIB64'] + post = 'x64' + else: + return + if self.language == 'fortran': + return ('none', + ['-I' + incdir, '-I' + os.path.join(incdir, post)], + [os.path.join(libdir, 'msmpi.lib'), os.path.join(libdir, 'msmpifec.lib')]) + else: + return ('none', + ['-I' + incdir, '-I' + os.path.join(incdir, post)], + [os.path.join(libdir, 'msmpi.lib')]) + + class ThreadDependency(ExternalDependency): def __init__(self, environment, kwargs): super().__init__('threads', environment, None, {}) diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index 1c59a41..99e017b 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -24,7 +24,7 @@ from collections import OrderedDict from .. import mlog from .. import mesonlib from ..mesonlib import MesonException, Popen_safe, version_compare -from ..environment import for_windows +from ..environment import for_windows, detect_cpu from .base import DependencyException, DependencyMethods from .base import ExternalDependency, ExternalProgram @@ -493,3 +493,79 @@ class WxDependency(ExternalDependency): pass WxDependency.wxconfig_found = False mlog.log('Found wx-config:', mlog.red('NO')) + +class VulkanDependency(ExternalDependency): + def __init__(self, environment, kwargs): + super().__init__('vulkan', environment, None, kwargs) + + if DependencyMethods.PKGCONFIG in self.methods: + try: + pcdep = PkgConfigDependency('vulkan', environment, kwargs) + if pcdep.found(): + self.type_name = 'pkgconfig' + self.is_found = True + self.compile_args = pcdep.get_compile_args() + self.link_args = pcdep.get_link_args() + self.version = pcdep.get_version() + return + except Exception: + pass + + if DependencyMethods.SYSTEM in self.methods: + try: + self.vulkan_sdk = os.environ['VULKAN_SDK'] + if not os.path.isabs(self.vulkan_sdk): + raise DependencyException('VULKAN_SDK must be an absolute path.') + except KeyError: + self.vulkan_sdk = None + + if self.vulkan_sdk: + # TODO: this config might not work on some platforms, fix bugs as reported + # we should at least detect other 64-bit platforms (e.g. armv8) + lib_name = 'vulkan' + if mesonlib.is_windows(): + lib_name = 'vulkan-1' + lib_dir = 'Lib32' + inc_dir = 'Include' + if detect_cpu({}) == 'x86_64': + lib_dir = 'Lib' + else: + lib_name = 'vulkan' + lib_dir = 'lib' + inc_dir = 'include' + + # make sure header and lib are valid + inc_path = os.path.join(self.vulkan_sdk, inc_dir) + header = os.path.join(inc_path, 'vulkan', 'vulkan.h') + lib_path = os.path.join(self.vulkan_sdk, lib_dir) + find_lib = self.compiler.find_library(lib_name, environment, lib_path) + + if not find_lib: + raise DependencyException('VULKAN_SDK point to invalid directory (no lib)') + + if not os.path.isfile(header): + raise DependencyException('VULKAN_SDK point to invalid directory (no include)') + + self.type_name = 'vulkan_sdk' + self.is_found = True + self.compile_args.append('-I' + inc_path) + self.link_args.append('-L' + lib_path) + self.link_args.append('-l' + lib_name) + + # TODO: find a way to retrieve the version from the sdk? + # Usually it is a part of the path to it (but does not have to be) + self.version = '1' + return + else: + # simply try to guess it, usually works on linux + libs = self.compiler.find_library('vulkan', environment, []) + if libs is not None and self.compiler.has_header('vulkan/vulkan.h', '', environment): + self.type_name = 'system' + self.is_found = True + self.version = 1 # TODO + for lib in libs: + self.link_args.append(lib) + return + + def get_methods(self): + return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM] diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index f88c265..970ab7c 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -456,12 +456,13 @@ class DataHolder(InterpreterObject): return self.held_object.install_dir class InstallDir(InterpreterObject): - def __init__(self, src_subdir, inst_subdir, install_dir, install_mode): + def __init__(self, src_subdir, inst_subdir, install_dir, install_mode, exclude): InterpreterObject.__init__(self) self.source_subdir = src_subdir self.installable_subdir = inst_subdir self.install_dir = install_dir self.install_mode = install_mode + self.exclude = exclude class Man(InterpreterObject): @@ -1243,6 +1244,7 @@ buildtarget_kwargs = set(['build_by_default', 'link_whole', 'link_args', 'link_depends', + 'implicit_include_directories', 'include_directories', 'install', 'install_rpath', @@ -1296,7 +1298,7 @@ permitted_kwargs = {'add_global_arguments': {'language'}, 'install_data': {'install_dir', 'install_mode', 'sources'}, 'install_headers': {'install_dir', 'subdir'}, 'install_man': {'install_dir'}, - 'install_subdir': {'install_dir', 'install_mode'}, + 'install_subdir': {'exclude_files', 'exclude_directories', 'install_dir', 'install_mode'}, 'jar': jar_kwargs, 'project': {'version', 'meson_version', 'default_options', 'license', 'subproject_dir'}, 'run_target': {'command', 'depends'}, @@ -2049,6 +2051,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 @@ -2440,13 +2443,39 @@ class Interpreter(InterpreterBase): def func_install_subdir(self, node, args, kwargs): if len(args) != 1: raise InvalidArguments('Install_subdir requires exactly one argument.') + subdir = args[0] if 'install_dir' not in kwargs: raise InvalidArguments('Missing keyword argument install_dir') install_dir = kwargs['install_dir'] if not isinstance(install_dir, str): raise InvalidArguments('Keyword argument install_dir not a string.') + if 'exclude_files' in kwargs: + exclude = kwargs['exclude_files'] + if not isinstance(exclude, list): + exclude = [exclude] + for f in exclude: + if not isinstance(f, str): + raise InvalidArguments('Exclude argument not a string.') + elif os.path.isabs(f): + raise InvalidArguments('Exclude argument cannot be absolute.') + exclude_files = {os.path.join(subdir, f) for f in exclude} + else: + exclude_files = set() + if 'exclude_directories' in kwargs: + exclude = kwargs['exclude_directories'] + if not isinstance(exclude, list): + exclude = [exclude] + for d in exclude: + if not isinstance(d, str): + raise InvalidArguments('Exclude argument not a string.') + elif os.path.isabs(d): + raise InvalidArguments('Exclude argument cannot be absolute.') + exclude_directories = {os.path.join(subdir, f) for f in exclude} + else: + exclude_directories = set() + exclude = (exclude_files, exclude_directories) install_mode = self._get_kwarg_install_mode(kwargs) - idir = InstallDir(self.subdir, args[0], install_dir, install_mode) + idir = InstallDir(self.subdir, subdir, install_dir, install_mode, exclude) self.build.install_dirs.append(idir) return idir diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 14eddf5..ee4dbf8 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -122,6 +122,9 @@ class Conf: (k, v) = o.split('=', 1) if coredata.is_builtin_option(k): self.coredata.set_builtin_option(k, v) + elif k in self.coredata.backend_options: + tgt = self.coredata.backend_options[k] + tgt.set_value(v) elif k in self.coredata.user_options: tgt = self.coredata.user_options[k] tgt.set_value(v) @@ -163,6 +166,16 @@ class Conf: 'choices': coredata.get_builtin_option_choices(key)}) self.print_aligned(carr) print('') + bekeys = sorted(self.coredata.backend_options.keys()) + if not bekeys: + print(' No backend options\n') + else: + bearr = [] + for k in bekeys: + o = self.coredata.backend_options[k] + bearr.append({'name': k, 'descr': o.description, 'value': o.value, 'choices': ''}) + self.print_aligned(bearr) + print('') print('Base options:') okeys = sorted(self.coredata.base_options.keys()) if not okeys: diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 1630d95..6bf8b7f 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -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/optinterpreter.py b/mesonbuild/optinterpreter.py index f9e7f26..ac27269 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -18,17 +18,18 @@ from . import mesonlib import os, re forbidden_option_names = coredata.get_builtin_options() -forbidden_prefixes = {'c_': True, - 'cpp_': True, - 'd_': True, - 'rust_': True, - 'fortran_': True, - 'objc_': True, - 'objcpp_': True, - 'vala_': True, - 'csharp_': True, - 'swift_': True, - 'b_': True, +forbidden_prefixes = {'c_', + 'cpp_', + 'd_', + 'rust_', + 'fortran_', + 'objc_', + 'objcpp_', + 'vala_', + 'csharp_', + 'swift_', + 'b_', + 'backend_', } def is_invalid_name(name): diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py index f61cbab..01ea771 100644 --- a/mesonbuild/scripts/meson_install.py +++ b/mesonbuild/scripts/meson_install.py @@ -128,17 +128,25 @@ def do_copyfile(from_file, to_file): restore_selinux_context(to_file) append_to_log(to_file) -def do_copydir(data, src_prefix, src_dir, dst_dir): +def do_copydir(data, src_prefix, src_dir, dst_dir, exclude): ''' Copies the directory @src_prefix (full path) into @dst_dir @src_dir is simply the parent directory of @src_prefix ''' + if exclude is not None: + exclude_files, exclude_dirs = exclude + else: + exclude_files = exclude_dirs = set() for root, dirs, files in os.walk(src_prefix): - for d in dirs: + for d in dirs[:]: abs_src = os.path.join(src_dir, root, d) filepart = abs_src[len(src_dir) + 1:] abs_dst = os.path.join(dst_dir, filepart) + # Remove these so they aren't visited by os.walk at all. + if filepart in exclude_dirs: + dirs.remove(d) + continue if os.path.isdir(abs_dst): continue if os.path.exists(abs_dst): @@ -149,6 +157,8 @@ def do_copydir(data, src_prefix, src_dir, dst_dir): for f in files: abs_src = os.path.join(src_dir, root, f) filepart = abs_src[len(src_dir) + 1:] + if filepart in exclude_files: + continue abs_dst = os.path.join(dst_dir, filepart) if os.path.isdir(abs_dst): print('Tried to copy file %s but a directory of that name already exists.' % abs_dst) @@ -184,14 +194,14 @@ def do_install(datafilename): run_install_script(d) def install_subdirs(d): - for (src_dir, inst_dir, dst_dir, mode) in d.install_subdirs: + for (src_dir, inst_dir, dst_dir, mode, exclude) 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(d, dst_dir) d.dirmaker.makedirs(dst_dir, exist_ok=True) - do_copydir(d, src_prefix, src_dir, dst_dir) + do_copydir(d, src_prefix, src_dir, dst_dir, exclude) dst_prefix = os.path.join(dst_dir, inst_dir) set_mode(dst_prefix, mode) @@ -317,7 +327,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(d, fname, os.path.dirname(fname), outdir) + do_copydir(d, fname, os.path.dirname(fname), outdir, None) else: raise RuntimeError('Unknown file type for {!r}'.format(fname)) printed_symlink_error = False diff --git a/run_tests.py b/run_tests.py index e678d37..b8c5062 100755 --- a/run_tests.py +++ b/run_tests.py @@ -119,7 +119,7 @@ def get_fake_options(prefix): return opts def should_run_linux_cross_tests(): - return shutil.which('arm-linux-gnueabihf-gcc-6') and not platform.machine().startswith('arm') + return shutil.which('arm-linux-gnueabihf-gcc-6') and not platform.machine().lower().startswith('arm') def run_configure_inprocess(commandlist): old_stdout = sys.stdout @@ -142,7 +142,17 @@ class FakeEnvironment(object): def is_cross_build(self): return False +def print_system_info(): + print(mlog.bold('System information.').get_text(mlog.colorize_console)) + print('Architecture:', platform.architecture()) + print('Machine:', platform.machine()) + print('Platform:', platform.system()) + print('Processor:', platform.processor()) + print('System:', platform.system()) + print('') + if __name__ == '__main__': + print_system_info() # Enable coverage early... enable_coverage = '--cov' in sys.argv if enable_coverage: 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/158 dotinclude/dotproc.c b/test cases/common/158 dotinclude/dotproc.c new file mode 100644 index 0000000..5e65f7b --- /dev/null +++ b/test cases/common/158 dotinclude/dotproc.c @@ -0,0 +1,10 @@ +#include"stdio.h" + +#ifndef WRAPPER_INCLUDED +#error The wrapper stdio.h was not included. +#endif + +int main(int argc, char **argv) { + printf("Eventually I got printed.\n"); + return 0; +} diff --git a/test cases/common/158 dotinclude/meson.build b/test cases/common/158 dotinclude/meson.build new file mode 100644 index 0000000..e0c2cd7 --- /dev/null +++ b/test cases/common/158 dotinclude/meson.build @@ -0,0 +1,5 @@ +project('dotinclude', 'c') + +executable('dotproc', 'dotproc.c', + implicit_include_directories : false) + diff --git a/test cases/common/158 dotinclude/stdio.h b/test cases/common/158 dotinclude/stdio.h new file mode 100644 index 0000000..b6bd09f --- /dev/null +++ b/test cases/common/158 dotinclude/stdio.h @@ -0,0 +1,6 @@ +// There is no #pragma once because we _want_ to cause an eternal loop +// if this wrapper invokes itself. + +#define WRAPPER_INCLUDED + +#include<stdio.h> diff --git a/test cases/common/66 install subdir/installed_files.txt b/test cases/common/66 install subdir/installed_files.txt index a610c51..e5d2307 100644 --- a/test cases/common/66 install subdir/installed_files.txt +++ b/test cases/common/66 install subdir/installed_files.txt @@ -2,3 +2,5 @@ usr/share/sub1/data1.dat usr/share/sub1/second.dat usr/share/sub1/third.dat usr/share/sub1/sub2/data2.dat +usr/share/sub2/one.dat +usr/share/sub2/dircheck/excluded-three.dat diff --git a/test cases/common/66 install subdir/meson.build b/test cases/common/66 install subdir/meson.build index fed2f89..18e0eaf 100644 --- a/test cases/common/66 install subdir/meson.build +++ b/test cases/common/66 install subdir/meson.build @@ -1,5 +1,11 @@ project('install a whole subdir', 'c') +# A subdir with an exclusion: +install_subdir('sub2', + exclude_files : ['excluded-three.dat'], + exclude_directories : ['excluded'], + install_dir : 'share') + subdir('subdir') # A subdir with write perms only for the owner # and read-list perms for owner and group diff --git a/test cases/common/66 install subdir/sub2/dircheck/excluded-three.dat b/test cases/common/66 install subdir/sub2/dircheck/excluded-three.dat new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/66 install subdir/sub2/dircheck/excluded-three.dat diff --git a/test cases/common/66 install subdir/sub2/excluded-three.dat b/test cases/common/66 install subdir/sub2/excluded-three.dat new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/66 install subdir/sub2/excluded-three.dat diff --git a/test cases/common/66 install subdir/sub2/excluded/two.dat b/test cases/common/66 install subdir/sub2/excluded/two.dat new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/66 install subdir/sub2/excluded/two.dat diff --git a/test cases/common/66 install subdir/sub2/one.dat b/test cases/common/66 install subdir/sub2/one.dat new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/66 install subdir/sub2/one.dat diff --git a/test cases/frameworks/17 mpi/main.c b/test cases/frameworks/17 mpi/main.c new file mode 100644 index 0000000..e44357a --- /dev/null +++ b/test cases/frameworks/17 mpi/main.c @@ -0,0 +1,27 @@ +#include <stdio.h> +#include <mpi.h> + +int main(int argc, char **argv) +{ + int ier, flag; + ier = MPI_Init(&argc, &argv); + if (ier) { + printf("Unable to initialize MPI: %d\n", ier); + return 1; + } + ier = MPI_Initialized(&flag); + if (ier) { + printf("Unable to check MPI initialization state: %d\n", ier); + return 1; + } + if (!flag) { + printf("MPI did not initialize!\n"); + return 1; + } + ier = MPI_Finalize(); + if (ier) { + printf("Unable to finalize MPI: %d\n", ier); + return 1; + } + return 0; +} diff --git a/test cases/frameworks/17 mpi/main.cpp b/test cases/frameworks/17 mpi/main.cpp new file mode 100644 index 0000000..0e0b621 --- /dev/null +++ b/test cases/frameworks/17 mpi/main.cpp @@ -0,0 +1,11 @@ +#include <mpi.h> + +int main(int argc, char **argv) +{ + MPI::Init(argc, argv); + if (!MPI::Is_initialized()) { + printf("MPI did not initialize!\n"); + return 1; + } + MPI::Finalize(); +} diff --git a/test cases/frameworks/17 mpi/main.f90 b/test cases/frameworks/17 mpi/main.f90 new file mode 100644 index 0000000..d379e96 --- /dev/null +++ b/test cases/frameworks/17 mpi/main.f90 @@ -0,0 +1,21 @@ +program mpitest + implicit none + include 'mpif.h' + logical :: flag + integer :: ier + call MPI_Init(ier) + if (ier /= 0) then + print *, 'Unable to initialize MPI: ', ier + stop 1 + endif + call MPI_Initialized(flag, ier) + if (ier /= 0) then + print *, 'Unable to check MPI initialization state: ', ier + stop 1 + endif + call MPI_Finalize(ier) + if (ier /= 0) then + print *, 'Unable to finalize MPI: ', ier + stop 1 + endif +end program mpitest diff --git a/test cases/frameworks/17 mpi/meson.build b/test cases/frameworks/17 mpi/meson.build new file mode 100644 index 0000000..5e9bc56 --- /dev/null +++ b/test cases/frameworks/17 mpi/meson.build @@ -0,0 +1,33 @@ +project('mpi', 'c', 'cpp') + +cc = meson.get_compiler('c') + +if build_machine.system() == 'windows' and cc.get_id() != 'msvc' + error('MESON_SKIP_TEST: MPI not available on Windows without MSVC.') +endif + +mpic = dependency('mpi', language : 'c') +exec = executable('exec', + 'main.c', + dependencies : [mpic]) + +test('MPI C', exec) + +if build_machine.system() != 'windows' + # C++ MPI not supported by MS-MPI used on AppVeyor. + mpicpp = dependency('mpi', language : 'cpp') + execpp = executable('execpp', + 'main.cpp', + dependencies : [mpicpp]) + + test('MPI C++', execpp) +endif + +if add_languages('fortran', required : false) + mpifort = dependency('mpi', language : 'fortran') + exef = executable('exef', + 'main.f90', + dependencies : [mpifort]) + + test('MPI Fortran', exef) +endif diff --git a/test cases/frameworks/17 vulkan/meson.build b/test cases/frameworks/17 vulkan/meson.build new file mode 100644 index 0000000..54f1d47 --- /dev/null +++ b/test cases/frameworks/17 vulkan/meson.build @@ -0,0 +1,7 @@ +project('vulkan test', 'c') + +vulkan_dep = dependency('vulkan') + +e = executable('vulkanprog', 'vulkanprog.c', dependencies : vulkan_dep) + +test('vulkantest', e) diff --git a/test cases/frameworks/17 vulkan/vulkanprog.c b/test cases/frameworks/17 vulkan/vulkanprog.c new file mode 100644 index 0000000..1c1c58a --- /dev/null +++ b/test cases/frameworks/17 vulkan/vulkanprog.c @@ -0,0 +1,26 @@ +#include <vulkan/vulkan.h> +#include <stdio.h> + +int main() +{ + VkInstanceCreateInfo instance_create_info = { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + NULL, + 0, + NULL, + 0, + NULL, + 0, + NULL, + }; + + // we don't actually require instance creation to succeed since + // we cannot expect test environments to have a vulkan driver installed. + // As long as this does not produce as segmentation fault or similar, + // everything's alright. + VkInstance instance; + if(vkCreateInstance(&instance_create_info, NULL, &instance) == VK_SUCCESS) + vkDestroyInstance(instance, NULL); + + return 0; +}
\ No newline at end of file |