aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Reference-manual.md9
-rw-r--r--docs/markdown/Release-notes-for-0.51.0.md2
-rw-r--r--docs/markdown/Syntax.md7
-rw-r--r--docs/markdown/Unit-tests.md35
-rw-r--r--mesonbuild/ast/interpreter.py2
-rw-r--r--mesonbuild/ast/introspection.py8
-rw-r--r--mesonbuild/compilers/cpp.py1
-rw-r--r--mesonbuild/compilers/fortran.py3
-rw-r--r--mesonbuild/compilers/mixins/clike.py14
-rw-r--r--mesonbuild/compilers/mixins/intel.py3
-rw-r--r--mesonbuild/compilers/mixins/pgi.py32
-rw-r--r--mesonbuild/dependencies/misc.py21
-rw-r--r--mesonbuild/interpreter.py2
-rw-r--r--mesonbuild/mdist.py8
-rw-r--r--mesonbuild/mtest.py33
-rwxr-xr-xrun_project_tests.py63
-rwxr-xr-xrun_tests.py6
-rwxr-xr-xrun_unittests.py16
-rw-r--r--test cases/common/13 pch/c/meson.build6
-rw-r--r--test cases/common/13 pch/cpp/prog.cc3
-rw-r--r--test cases/common/13 pch/generated/meson.build6
-rw-r--r--test cases/common/13 pch/meson.build10
-rw-r--r--test cases/common/13 pch/mixed/meson.build8
-rw-r--r--test cases/common/13 pch/withIncludeDirectories/meson.build6
-rw-r--r--test cases/common/190 openmp/meson.build21
-rw-r--r--test cases/common/223 source set realistic example/meson.build6
-rw-r--r--test cases/fortran/13 coarray/meson.build7
-rw-r--r--test cases/fortran/14 fortran links c/meson.build3
-rw-r--r--test cases/fortran/2 modules/meson.build3
-rw-r--r--test cases/fortran/6 dynamic/meson.build6
-rw-r--r--test cases/unit/55 introspection/meson.build2
31 files changed, 250 insertions, 102 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 3a21cef..6be3ed7 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -131,7 +131,7 @@ This function creates a new top-level target. Like all top-level targets, this
integrates with the selected backend. For instance, with Ninja you can
run it as `ninja target_name`. This is a dummy target that does not execute any
command, but ensures that all dependencies are built. Dependencies can be any
-build target (e.g. return value of executable(), custom_target(), etc)
+build target (e.g. return value of [executable()](#executable), custom_target(), etc)
### assert()
@@ -586,7 +586,7 @@ be passed to [shared and static libraries](#library).
- `include_directories` one or more objects created with the
`include_directories` function, or, since 0.50.0, strings, which
will be transparently expanded to include directory objects
-- `install`, when set to true, this executable should be installed
+- `install`, when set to true, this executable should be installed, defaults to `false`
- `install_dir` override install directory for this file. The value is
relative to the `prefix` specified. F.ex, if you want to install
plugins into a subdir, you'd use something like this: `install_dir :
@@ -1794,6 +1794,7 @@ are immutable, all operations return their results as a new string.
- `is_even()` returns true if the number is even
- `is_odd()` returns true if the number is odd
+ - `to_string()` returns the value of the number as a string.
### `boolean` object
@@ -2225,7 +2226,7 @@ an external dependency with the following methods:
- sources: any compiled or static sources the dependency has
- `get_variable(cmake : str, pkgconfig : str, configtool : str,
- default_value : str, pkgconfig_define : [str, str]) *(Added in
+ default_value : str, pkgconfig_define : [str, str])` *(Added in
0.51.0)* A generic variable getter method, which repalces the
get_*type*_variable methods. This allows one to get the variable
from a dependency without knowing specifically how that dependency
@@ -2253,7 +2254,7 @@ and has the following methods:
- `path()` which returns a string pointing to the script or executable
**NOTE:** You should not need to use this method. Passing the object
- itself should work in all cases. F.ex.: `run_command(obj, arg1, arg2)`
+ itself should work in all cases. For example: `run_command(obj, arg1, arg2)`
### `environment` object
diff --git a/docs/markdown/Release-notes-for-0.51.0.md b/docs/markdown/Release-notes-for-0.51.0.md
index 86b2f70..b7e441c 100644
--- a/docs/markdown/Release-notes-for-0.51.0.md
+++ b/docs/markdown/Release-notes-for-0.51.0.md
@@ -110,7 +110,7 @@ dependency you have.
```meson
dep = dependency('could_be_cmake_or_pkgconfig')
# cmake returns 'YES', pkg-config returns 'ON'
-if ['YES', 'ON'].contains(dep.get_variable(pkg-config : 'var-name', cmake : 'COP_VAR_NAME', default_value : 'NO'))
+if ['YES', 'ON'].contains(dep.get_variable(pkgconfig : 'var-name', cmake : 'COP_VAR_NAME', default_value : 'NO'))
error('Cannot build your project when dep is built with var-name support')
endif
```
diff --git a/docs/markdown/Syntax.md b/docs/markdown/Syntax.md
index 7802b92..24d9deb 100644
--- a/docs/markdown/Syntax.md
+++ b/docs/markdown/Syntax.md
@@ -78,6 +78,13 @@ string_var = '42'
num = string_var.to_int()
```
+Numbers can be converted to a string:
+
+```meson
+int_var = 42
+string_var = int_var.to_string()
+```
+
Booleans
--
diff --git a/docs/markdown/Unit-tests.md b/docs/markdown/Unit-tests.md
index 694c190..3c27732 100644
--- a/docs/markdown/Unit-tests.md
+++ b/docs/markdown/Unit-tests.md
@@ -71,10 +71,23 @@ The simplest thing to do is just to run all tests, which is equivalent to runnin
$ meson test
```
-You can also run only a single test by giving its name:
+### Run subsets of tests
+
+For clarity, consider the meson.build containing:
+
+```meson
+
+test('A', ..., suite: 'foo')
+test('B', ..., suite: 'foo')
+test('C', ..., suite: 'bar')
+test('D', ..., suite: 'baz')
+
+```
+
+Specify test(s) by name like:
```console
-$ meson test testname
+$ meson test A D
```
Tests belonging to a suite `suite` can be run as follows
@@ -85,6 +98,18 @@ $ meson test --suite (sub)project_name:suite
Since version *0.46*, `(sub)project_name` can be omitted if it is the top-level project.
+Multiple suites are specified like:
+
+```console
+$ meson test --suite foo --suite bar
+```
+
+NOTE: If you choose to specify both suite(s) and specific test name(s), the
+test name(s) must be contained in the suite(s). This however is redundant--
+it would be more useful to specify either specific test names or suite(s).
+
+### Other test options
+
Sometimes you need to run the tests multiple times, which is done like this:
```console
@@ -127,4 +152,8 @@ Meson will report the output produced by the failing tests along with other usef
For further information see the command line help of Meson by running `meson test -h`.
-**NOTE:** If `meson test` does not work for you, you likely have a old version of Meson. In that case you should call `mesontest` instead. If `mesontest` doesn't work either you have a very old version prior to 0.37.0 and should upgrade.
+## Legacy notes
+
+If `meson test` does not work for you, you likely have a old version of Meson.
+In that case you should call `mesontest` instead. If `mesontest` doesn't work
+either you have a very old version prior to 0.37.0 and should upgrade.
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
index 0e490ab..13c717b 100644
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -325,7 +325,7 @@ class AstInterpreter(interpreterbase.InterpreterBase):
for key, val in kwargs.items():
if isinstance(val, ElementaryNode):
flattend_kwargs[key] = val.value
- elif isinstance(val, (ArrayNode, ArgumentNode)):
+ elif isinstance(val, (ArrayNode, ArgumentNode, ArithmeticNode, MethodNode)):
flattend_kwargs[key] = self.flatten_args(val, include_unknown_args)
elif isinstance(val, (str, bool, int, float)) or include_unknown_args:
flattend_kwargs[key] = val
diff --git a/mesonbuild/ast/introspection.py b/mesonbuild/ast/introspection.py
index 617b140..aeb0400 100644
--- a/mesonbuild/ast/introspection.py
+++ b/mesonbuild/ast/introspection.py
@@ -158,16 +158,20 @@ class IntrospectionInterpreter(AstInterpreter):
args = self.flatten_args(args)
if not args or not isinstance(args[0], str):
return
- kwargs = self.flatten_kwargs(kwargs, True)
name = args[0]
srcqueue = [node]
+
+ # Process the soruces BEFORE flattening the kwargs, to preserve the original nodes
if 'sources' in kwargs:
- srcqueue += kwargs['sources']
+ srcqueue += mesonlib.listify(kwargs['sources'])
+
+ kwargs = self.flatten_kwargs(kwargs, True)
source_nodes = []
while srcqueue:
curr = srcqueue.pop(0)
arg_node = None
+ assert(isinstance(curr, BaseNode))
if isinstance(curr, FunctionNode):
arg_node = curr.args
elif isinstance(curr, ArrayNode):
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 44f53eb..6ae2673 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -274,7 +274,6 @@ class PGICPPCompiler(PGICompiler, CPPCompiler):
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs)
PGICompiler.__init__(self, compiler_type)
-
class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, defines=None, **kwargs):
GnuCPPCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, defines, **kwargs)
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index e417566..c10e2ca 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -321,6 +321,9 @@ class FlangFortranCompiler(ClangCompiler, FortranCompiler):
'2': default_warn_args,
'3': default_warn_args}
+ def language_stdlib_only_link_flags(self) -> List[str]:
+ return ['-lflang', '-lpgmath']
+
class Open64FortranCompiler(FortranCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwags):
FortranCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwags)
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index 0591b7f..37d2424 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -209,25 +209,25 @@ class CLikeCompiler:
'''
return self.get_compiler_dirs(env, 'programs')
- def get_pic_args(self):
+ def get_pic_args(self) -> typing.List[str]:
return ['-fPIC']
- def name_string(self):
+ def name_string(self) -> str:
return ' '.join(self.exelist)
- def get_pch_use_args(self, pch_dir, header):
+ def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]:
return ['-include', os.path.basename(header)]
- def get_pch_name(self, header_name):
+ def get_pch_name(self, header_name: str) -> str:
return os.path.basename(header_name) + '.' + self.get_pch_suffix()
- def get_linker_search_args(self, dirname):
+ def get_linker_search_args(self, dirname: str) -> typing.List[str]:
return ['-L' + dirname]
def get_default_include_dirs(self):
return []
- def gen_export_dynamic_link_args(self, env):
+ def gen_export_dynamic_link_args(self, env) -> typing.List[str]:
m = env.machines[self.for_machine]
if m.is_windows() or m.is_cygwin():
return ['-Wl,--export-all-symbols']
@@ -236,7 +236,7 @@ class CLikeCompiler:
else:
return ['-Wl,-export-dynamic']
- def gen_import_library_args(self, implibname):
+ def gen_import_library_args(self, implibname: str) -> typing.List[str]:
"""
The name of the outputted import library
diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py
index f147c4c..7fadb50 100644
--- a/mesonbuild/compilers/mixins/intel.py
+++ b/mesonbuild/compilers/mixins/intel.py
@@ -22,14 +22,13 @@ import os
import typing
from ... import mesonlib
+from ..compilers import CompilerType
from .gnu import GnuLikeCompiler
from .visualstudio import VisualStudioLikeCompiler
if typing.TYPE_CHECKING:
import subprocess # noqa: F401
- from ..compilers import CompilerType
-
# XXX: avoid circular dependencies
# TODO: this belongs in a posix compiler class
clike_optimization_args = {
diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py
index a75c62d..0613e79 100644
--- a/mesonbuild/compilers/mixins/pgi.py
+++ b/mesonbuild/compilers/mixins/pgi.py
@@ -16,6 +16,7 @@
import typing
import os
+from pathlib import Path
from ..compilers import clike_debug_args, clike_optimization_args
@@ -42,8 +43,9 @@ pgi_buildtype_linker_args = {
} # type: typing.Dict[str, typing.List[str]]
-class PGICompiler:
+class PGICompiler():
def __init__(self, compiler_type: 'CompilerType'):
+ self.base_options = ['b_pch']
self.id = 'pgi'
self.compiler_type = compiler_type
@@ -59,9 +61,21 @@ class PGICompiler:
def get_no_warn_args(self) -> typing.List[str]:
return ['-silent']
+ def gen_import_library_args(self, implibname: str) -> typing.List[str]:
+ return []
+
+ def get_std_shared_lib_link_args(self) -> typing.List[str]:
+ # PGI -shared is Linux only.
+ if self.compiler_type.is_windows_compiler:
+ return ['-Bdynamic', '-Mmakedll']
+ elif not self.compiler_type.is_osx_compiler:
+ return ['-shared']
+ return []
+
def get_pic_args(self) -> typing.List[str]:
+ # PGI -fPIC is Linux only.
if self.compiler_type.is_osx_compiler or self.compiler_type.is_windows_compiler:
- return [] # PGI -fPIC is Linux only.
+ return []
return ['-fPIC']
def openmp_flags(self) -> typing.List[str]:
@@ -93,3 +107,17 @@ class PGICompiler:
def get_always_args(self) -> typing.List[str]:
return []
+
+ def get_pch_suffix(self) -> str:
+ # PGI defaults to .pch suffix for PCH on Linux and Windows with --pch option
+ return 'pch'
+
+ def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]:
+ # PGI supports PCH for C++ only.
+ hdr = Path(pch_dir).resolve().parent / header
+ if self.language == 'cpp':
+ return ['--pch',
+ '--pch_dir', str(hdr.parent),
+ '-I{}'.format(hdr.parent)]
+ else:
+ return []
diff --git a/mesonbuild/dependencies/misc.py b/mesonbuild/dependencies/misc.py
index 1bb1b6e..cdfa48b 100644
--- a/mesonbuild/dependencies/misc.py
+++ b/mesonbuild/dependencies/misc.py
@@ -370,21 +370,30 @@ class OpenMPDependency(ExternalDependency):
language = kwargs.get('language')
super().__init__('openmp', environment, language, kwargs)
self.is_found = False
+ if self.clib_compiler.get_id() == 'pgi':
+ # through at least PGI 19.4, there is no macro defined for OpenMP, but OpenMP 3.1 is supported.
+ self.version = '3.1'
+ self.is_found = True
+ self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
+ return
try:
openmp_date = self.clib_compiler.get_define(
'_OPENMP', '', self.env, self.clib_compiler.openmp_flags(), [self], disable_cache=True)[0]
except mesonlib.EnvironmentException as e:
mlog.debug('OpenMP support not available in the compiler')
mlog.debug(e)
- openmp_date = False
+ openmp_date = None
if openmp_date:
self.version = self.VERSIONS[openmp_date]
- if self.clib_compiler.has_header('omp.h', '', self.env, dependencies=[self], disable_cache=True)[0]:
- self.is_found = True
- self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
- else:
- mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.')
+ # Flang has omp_lib.h
+ header_names = ('omp.h', 'omp_lib.h')
+ for name in header_names:
+ if self.clib_compiler.has_header(name, '', self.env, dependencies=[self], disable_cache=True)[0]:
+ self.is_found = True
+ self.compile_args = self.link_args = self.clib_compiler.openmp_flags()
+ else:
+ mlog.log(mlog.yellow('WARNING:'), 'OpenMP found but omp.h missing.')
class ThreadDependency(ExternalDependency):
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 4b4d776..0891094 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -444,7 +444,7 @@ class DependencyHolder(InterpreterObject, ObjectHolder):
@FeatureNew('dep.get_variable', '0.51.0')
@noPosargs
- @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'default', 'pkgconfig_define'})
+ @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'default_value', 'pkgconfig_define'})
def variable_method(self, args, kwargs):
return self.held_object.get_variable(**kwargs)
diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py
index 7af0194..2d1aaf9 100644
--- a/mesonbuild/mdist.py
+++ b/mesonbuild/mdist.py
@@ -20,6 +20,7 @@ import sys
import shutil
import subprocess
import hashlib
+import json
from glob import glob
from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import windows_proof_rmtree
@@ -143,7 +144,7 @@ def create_dist_hg(dist_name, archives, src_root, bld_root, dist_sub, dist_scrip
return output_names
-def check_dist(packagename, meson_command, privdir):
+def check_dist(packagename, meson_command, bld_root, privdir):
print('Testing distribution package %s' % packagename)
unpackdir = os.path.join(privdir, 'dist-unpack')
builddir = os.path.join(privdir, 'dist-build')
@@ -158,6 +159,9 @@ def check_dist(packagename, meson_command, privdir):
unpacked_files = glob(os.path.join(unpackdir, '*'))
assert(len(unpacked_files) == 1)
unpacked_src_dir = unpacked_files[0]
+ with open(os.path.join(bld_root, 'meson-info', 'intro-buildoptions.json')) as boptions:
+ meson_command += ['-D{name}={value}'.format(**o) for o in json.load(boptions)
+ if o['name'] not in ['backend', 'install_umask']]
if subprocess.call(meson_command + ['--backend=ninja', unpacked_src_dir, builddir]) != 0:
print('Running Meson on distribution package failed')
return 1
@@ -214,7 +218,7 @@ def run(options):
if names is None:
return 1
# Check only one.
- rc = check_dist(names[0], meson_command, priv_dir)
+ rc = check_dist(names[0], meson_command, bld_root, priv_dir)
if rc == 0:
for name in names:
create_hash(name)
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 253f4ab..dc5c9d1 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -14,6 +14,7 @@
# A tool to run tests in many different ways.
+from pathlib import Path
from collections import namedtuple
from copy import deepcopy
import argparse
@@ -426,18 +427,18 @@ def run_with_mono(fname: str) -> bool:
return False
def load_benchmarks(build_dir: str) -> typing.List['TestSerialisation']:
- datafile = os.path.join(build_dir, 'meson-private', 'meson_benchmark_setup.dat')
- if not os.path.isfile(datafile):
- raise TestException('Directory ${!r} does not seem to be a Meson build directory.'.format(build_dir))
- with open(datafile, 'rb') as f:
+ datafile = Path(build_dir) / 'meson-private' / 'meson_benchmark_setup.dat'
+ if not datafile.is_file():
+ raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
+ with datafile.open('rb') as f:
obj = typing.cast(typing.List['TestSerialisation'], pickle.load(f))
return obj
def load_tests(build_dir: str) -> typing.List['TestSerialisation']:
- datafile = os.path.join(build_dir, 'meson-private', 'meson_test_setup.dat')
- if not os.path.isfile(datafile):
- raise TestException('Directory ${!r} does not seem to be a Meson build directory.'.format(build_dir))
- with open(datafile, 'rb') as f:
+ datafile = Path(build_dir) / 'meson-private' / 'meson_test_setup.dat'
+ if not datafile.is_file():
+ raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
+ with datafile.open('rb') as f:
obj = typing.cast(typing.List['TestSerialisation'], pickle.load(f))
return obj
@@ -833,8 +834,9 @@ Timeout: %4d
return False
def test_suitable(self, test: 'TestSerialisation') -> bool:
- return (not self.options.include_suites or TestHarness.test_in_suites(test, self.options.include_suites)) \
- and not TestHarness.test_in_suites(test, self.options.exclude_suites)
+ return ((not self.options.include_suites or
+ TestHarness.test_in_suites(test, self.options.include_suites)) and not
+ TestHarness.test_in_suites(test, self.options.exclude_suites))
def get_tests(self) -> typing.List['TestSerialisation']:
if not self.tests:
@@ -849,6 +851,7 @@ Timeout: %4d
else:
tests = self.tests
+ # allow specifying test names like "meson test foo1 foo2", where test('foo1', ...)
if self.options.args:
tests = [t for t in tests if t.name in self.options.args]
@@ -975,7 +978,7 @@ def list_tests(th: TestHarness) -> bool:
return not tests
def rebuild_all(wd: str) -> bool:
- if not os.path.isfile(os.path.join(wd, 'build.ninja')):
+ if not (Path(wd) / 'build.ninja').is_file():
print('Only ninja backend is supported to rebuild tests before running them.')
return True
@@ -984,11 +987,9 @@ def rebuild_all(wd: str) -> bool:
print("Can't find ninja, can't rebuild test.")
return False
- p = subprocess.Popen([ninja, '-C', wd])
- p.communicate()
-
- if p.returncode != 0:
- print('Could not rebuild')
+ ret = subprocess.run([ninja, '-C', wd]).returncode
+ if ret != 0:
+ print('Could not rebuild {}'.format(wd))
return False
return True
diff --git a/run_project_tests.py b/run_project_tests.py
index 80b56bb..a161525 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from typing import List, Tuple
+import typing
import itertools
import os
import subprocess
@@ -109,18 +109,10 @@ def setup_commands(optbackend):
compile_commands, clean_commands, test_commands, install_commands, \
uninstall_commands = get_backend_commands(backend, do_debug)
-def get_relative_files_list_from_dir(fromdir):
- paths = []
- for (root, _, files) in os.walk(fromdir):
- reldir = os.path.relpath(root, start=fromdir)
- for f in files:
- path = os.path.join(reldir, f).replace('\\', '/')
- if path.startswith('./'):
- path = path[2:]
- paths.append(path)
- return paths
-
-def platform_fix_name(fname, compiler, env):
+def get_relative_files_list_from_dir(fromdir: Path) -> typing.List[Path]:
+ return [file.relative_to(fromdir) for file in fromdir.rglob('*') if file.is_file()]
+
+def platform_fix_name(fname: str, compiler, env) -> str:
# canonicalize compiler
if compiler in {'clang-cl', 'intel-cl'}:
canonical_compiler = 'msvc'
@@ -200,35 +192,36 @@ def platform_fix_name(fname, compiler, env):
return fname
-def validate_install(srcdir, installdir, compiler, env):
+def validate_install(srcdir: str, installdir: Path, compiler, env) -> str:
# List of installed files
- info_file = os.path.join(srcdir, 'installed_files.txt')
+ info_file = Path(srcdir) / 'installed_files.txt'
+ installdir = Path(installdir)
# If this exists, the test does not install any other files
- noinst_file = 'usr/no-installed-files'
- expected = {}
+ noinst_file = Path('usr/no-installed-files')
+ expected = {} # type: typing.Dict[Path, bool]
ret_msg = ''
# Generate list of expected files
- if os.path.exists(os.path.join(installdir, noinst_file)):
+ if (installdir / noinst_file).is_file():
expected[noinst_file] = False
- elif os.path.exists(info_file):
- with open(info_file) as f:
+ elif info_file.is_file():
+ with info_file.open() as f:
for line in f:
line = platform_fix_name(line.strip(), compiler, env)
if line:
- expected[line] = False
+ expected[Path(line)] = False
# Check if expected files were found
for fname in expected:
- file_path = os.path.join(installdir, fname)
- if os.path.exists(file_path) or os.path.islink(file_path):
+ file_path = installdir / fname
+ if file_path.is_file() or file_path.is_symlink():
expected[fname] = True
for (fname, found) in expected.items():
if not found:
- ret_msg += 'Expected file {0} missing.\n'.format(fname)
+ ret_msg += 'Expected file {} missing.\n'.format(fname)
# Check if there are any unexpected files
found = get_relative_files_list_from_dir(installdir)
for fname in found:
if fname not in expected:
- ret_msg += 'Extra file {0} found.\n'.format(fname)
+ ret_msg += 'Extra file {} found.\n'.format(fname)
if ret_msg != '':
ret_msg += '\nInstall dir contents:\n'
for i in found:
@@ -445,7 +438,7 @@ def _run_test(testdir, test_build_dir, install_dir, extra_args, compiler, backen
return TestResult(validate_install(testdir, install_dir, compiler, builddata.environment),
BuildStep.validate, stdo, stde, mesonlog, gen_time, build_time, test_time)
-def gather_tests(testdir: Path) -> List[Path]:
+def gather_tests(testdir: Path) -> typing.List[Path]:
test_names = [t.name for t in testdir.glob('*') if t.is_dir()]
test_names = [t for t in test_names if not t.startswith('.')] # Filter non-tests files (dot files, etc)
test_nums = [(int(t.split()[0]), t) for t in test_names]
@@ -598,7 +591,7 @@ def should_skip_rust() -> bool:
return True
return False
-def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
+def detect_tests_to_run(only: typing.List[str]) -> typing.List[typing.Tuple[str, typing.List[Path], bool]]:
"""
Parameters
----------
@@ -611,10 +604,8 @@ def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
tests to run
"""
- ninja_fortran_compiler = shutil.which('gfortran') or shutil.which('flang') or shutil.which('pgfortran') or (not mesonlib.is_windows() and shutil.which('ifort'))
- ninja_fortran = backend is Backend.ninja and ninja_fortran_compiler
- vs_fortran = mesonlib.is_windows() and backend is Backend.vs and shutil.which('ifort')
- skip_fortran = not(ninja_fortran or vs_fortran)
+ skip_fortran = not(shutil.which('gfortran') or shutil.which('flang') or
+ shutil.which('pgfortran') or shutil.which('ifort'))
# Name, subdirectory, skip condition.
all_tests = [
@@ -637,7 +628,7 @@ def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
('d', 'd', backend is not Backend.ninja or not have_d_compiler()),
('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or not have_objc_compiler()),
('objective c++', 'objcpp', backend not in (Backend.ninja, Backend.xcode) or not have_objcpp_compiler()),
- ('fortran', 'fortran', skip_fortran),
+ ('fortran', 'fortran', skip_fortran or backend != Backend.ninja),
('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')),
('cuda', 'cuda', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('nvcc')),
('python3', 'python3', backend is not Backend.ninja),
@@ -654,14 +645,14 @@ def detect_tests_to_run(only: List[str]) -> List[Tuple[str, List[Path], bool]]:
gathered_tests = [(name, gather_tests(Path('test cases', subdir)), skip) for name, subdir, skip in all_tests]
return gathered_tests
-def run_tests(all_tests, log_name_base, failfast, extra_args):
+def run_tests(all_tests, log_name_base, failfast: bool, extra_args):
global logfile
txtname = log_name_base + '.txt'
with open(txtname, 'w', encoding='utf-8', errors='ignore') as lf:
logfile = lf
return _run_tests(all_tests, log_name_base, failfast, extra_args)
-def _run_tests(all_tests, log_name_base, failfast, extra_args):
+def _run_tests(all_tests, log_name_base, failfast: bool, extra_args):
global stop, executor, futures, system_compiler
xmlname = log_name_base + '.xml'
junit_root = ET.Element('testsuites')
@@ -767,8 +758,8 @@ def _run_tests(all_tests, log_name_base, failfast, extra_args):
stdeel = ET.SubElement(current_test, 'system-err')
stdeel.text = result.stde
- if failfast and failing_tests > 0:
- break
+ if failfast and failing_tests > 0:
+ break
print("\nTotal configuration time: %.2fs" % conf_time)
print("Total build time: %.2fs" % build_time)
diff --git a/run_tests.py b/run_tests.py
index 38c65c5..6a42681 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -34,11 +34,13 @@ from mesonbuild import mlog
from mesonbuild.environment import Environment, detect_ninja
from mesonbuild.coredata import backendlist
-def guess_backend(backend, msbuild_exe):
+def guess_backend(backend, msbuild_exe: str):
# Auto-detect backend if unspecified
backend_flags = []
if backend is None:
- if msbuild_exe is not None and mesonlib.is_windows():
+ if (msbuild_exe is not None and
+ mesonlib.is_windows() and not
+ (os.environ.get('CC') == 'icl' or os.environ.get('CXX') == 'icl' or os.environ.get('FC') == 'ifort')):
backend = 'vs' # Meson will auto-detect VS version to use
else:
backend = 'ninja'
diff --git a/run_unittests.py b/run_unittests.py
index 1ac4c53..0bd2c02 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -6605,6 +6605,21 @@ def unset_envs():
if v in os.environ:
del os.environ[v]
+def convert_args(argv):
+ # If we got passed a list of tests, pass it on
+ pytest_args = ['-v'] if '-v' in argv else []
+ test_list = []
+ for arg in argv:
+ if arg.startswith('-'):
+ continue
+ # ClassName.test_name => 'ClassName and test_name'
+ if '.' in arg:
+ arg = ' and '.join(arg.split('.'))
+ test_list.append(arg)
+ if test_list:
+ pytest_args += ['-k', ' or '.join(test_list)]
+ return pytest_args
+
def main():
unset_envs()
try:
@@ -6612,6 +6627,7 @@ def main():
# Need pytest-xdist for `-n` arg
import xdist # noqa: F401
pytest_args = ['-n', 'auto', './run_unittests.py']
+ pytest_args += convert_args(sys.argv[1:])
return subprocess.run(python_command + ['-m', 'pytest'] + pytest_args).returncode
except ImportError:
print('pytest-xdist not found, using unittest instead')
diff --git a/test cases/common/13 pch/c/meson.build b/test cases/common/13 pch/c/meson.build
index fe4ac68..6fba15b 100644
--- a/test cases/common/13 pch/c/meson.build
+++ b/test cases/common/13 pch/c/meson.build
@@ -1,8 +1,14 @@
cc = meson.get_compiler('c')
cc_id = cc.get_id()
+
if cc_id == 'lcc'
error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.')
endif
+# PGI compiler only supports PCH for C++
+if cc_id == 'pgi'
+ subdir_done()
+endif
+
exe = executable('prog', 'prog.c',
c_pch : 'pch/prog.h')
diff --git a/test cases/common/13 pch/cpp/prog.cc b/test cases/common/13 pch/cpp/prog.cc
index 629d880..ea258c6 100644
--- a/test cases/common/13 pch/cpp/prog.cc
+++ b/test cases/common/13 pch/cpp/prog.cc
@@ -1,8 +1,11 @@
+// Note: if using PGI compilers, you will need to add #include "prog.hh"
+// even though you're using precompiled headers.
void func() {
std::cout << "This is a function that fails to compile if iostream is not included."
<< std::endl;
}
int main(int argc, char **argv) {
+ func();
return 0;
}
diff --git a/test cases/common/13 pch/generated/meson.build b/test cases/common/13 pch/generated/meson.build
index 1ef771b..ba06bce 100644
--- a/test cases/common/13 pch/generated/meson.build
+++ b/test cases/common/13 pch/generated/meson.build
@@ -1,9 +1,15 @@
cc = meson.get_compiler('c')
cc_id = cc.get_id()
+
if cc_id == 'lcc'
error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.')
endif
+# PGI compiler only supports PCH for C++
+if cc_id == 'pgi'
+ subdir_done()
+endif
+
generated_customTarget = custom_target('makeheader',
output: 'generated_customTarget.h',
command : [find_program('gen_custom.py'), '@OUTPUT0@'])
diff --git a/test cases/common/13 pch/meson.build b/test cases/common/13 pch/meson.build
index 4438c9e..334afc5 100644
--- a/test cases/common/13 pch/meson.build
+++ b/test cases/common/13 pch/meson.build
@@ -1,4 +1,12 @@
-project('pch test', 'c', 'cpp')
+project('pch test', 'c', 'cpp',
+ meson_version: '>= 0.46.0')
+
+cc = meson.get_compiler('c')
+cc_id = cc.get_id()
+
+if cc_id == 'pgi'
+ error('MESON_SKIP_TEST: PGI compiler does support PCH, however, PGI cannot tolerate spaces in the --pch_dir path and Meson run_project_tests.py uses spaces in temporary build path names. If this test is run individually with no spaces in build path, it will pass.')
+endif
subdir('c')
subdir('cpp')
diff --git a/test cases/common/13 pch/mixed/meson.build b/test cases/common/13 pch/mixed/meson.build
index cbb7bac..266e7a5 100644
--- a/test cases/common/13 pch/mixed/meson.build
+++ b/test cases/common/13 pch/mixed/meson.build
@@ -1,3 +1,11 @@
+cc = meson.get_compiler('c')
+cc_id = cc.get_id()
+
+# PGI compiler only supports PCH for C++
+if cc_id == 'pgi'
+ subdir_done()
+endif
+
exe = executable(
'prog',
files('main.cc', 'func.c'),
diff --git a/test cases/common/13 pch/withIncludeDirectories/meson.build b/test cases/common/13 pch/withIncludeDirectories/meson.build
index 68e544b..95f7888 100644
--- a/test cases/common/13 pch/withIncludeDirectories/meson.build
+++ b/test cases/common/13 pch/withIncludeDirectories/meson.build
@@ -1,9 +1,15 @@
cc = meson.get_compiler('c')
cc_id = cc.get_id()
+
if cc_id == 'lcc'
error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.')
endif
+# PGI compiler only supports PCH for C++
+if cc_id == 'pgi'
+ subdir_done()
+endif
+
exe = executable('prog', 'prog.c',
include_directories: 'include',
c_pch : 'pch/prog.h')
diff --git a/test cases/common/190 openmp/meson.build b/test cases/common/190 openmp/meson.build
index 71bf697..a1154c2 100644
--- a/test cases/common/190 openmp/meson.build
+++ b/test cases/common/190 openmp/meson.build
@@ -1,4 +1,4 @@
-project('openmp', 'c', 'cpp')
+project('openmp', 'c')
cc = meson.get_compiler('c')
if cc.get_id() == 'gcc' and cc.version().version_compare('<4.2.0')
@@ -21,21 +21,22 @@ if host_machine.system() == 'darwin'
endif
openmp = dependency('openmp')
+env = environment()
+env.set('OMP_NUM_THREADS', '2')
exec = executable('exec',
'main.c',
dependencies : [openmp])
-
-execpp = executable('execpp',
- 'main.cpp',
- dependencies : [openmp])
-
-env = environment()
-env.set('OMP_NUM_THREADS', '2')
-
test('OpenMP C', exec, env : env)
-test('OpenMP C++', execpp, env : env)
+if not(build_machine.system() == 'windows' and cc.get_id() == 'pgi')
+ if add_languages('cpp', required : false)
+ execpp = executable('execpp',
+ 'main.cpp',
+ dependencies : [openmp])
+ test('OpenMP C++', execpp, env : env)
+ endif
+endif
if add_languages('fortran', required : false)
# Mixing compilers (msvc/clang with gfortran) does not seem to work on Windows.
diff --git a/test cases/common/223 source set realistic example/meson.build b/test cases/common/223 source set realistic example/meson.build
index f983e8b..2a9475a 100644
--- a/test cases/common/223 source set realistic example/meson.build
+++ b/test cases/common/223 source set realistic example/meson.build
@@ -2,6 +2,12 @@
# modules, inspired by QEMU's build system
project('sourceset-example', 'cpp')
+
+cppid = meson.get_compiler('cpp').get_id()
+if cppid == 'pgi'
+ error('MESON_SKIP_TEST: Even PGI 19.4 that claims C++17 full support, cannot handle auto x = y syntax used in this test.')
+endif
+
ss = import('sourceset')
kconfig = import('unstable-kconfig')
diff --git a/test cases/fortran/13 coarray/meson.build b/test cases/fortran/13 coarray/meson.build
index 3160aa6..3e52dde 100644
--- a/test cases/fortran/13 coarray/meson.build
+++ b/test cases/fortran/13 coarray/meson.build
@@ -1,6 +1,13 @@
project('Fortran coarray', 'fortran',
meson_version: '>=0.50')
+fc = meson.get_compiler('fortran')
+fcid = fc.get_id()
+
+if ['pgi', 'flang'].contains(fcid)
+ error('MESON_SKIP_TEST: At least through PGI 19.4 and Flang 7.1 do not support Fortran Coarrays.')
+endif
+
# coarray is required because single-image fallback is an intrinsic feature
coarray = dependency('coarray', required : true)
diff --git a/test cases/fortran/14 fortran links c/meson.build b/test cases/fortran/14 fortran links c/meson.build
index 1ac47e4..a45f06f 100644
--- a/test cases/fortran/14 fortran links c/meson.build
+++ b/test cases/fortran/14 fortran links c/meson.build
@@ -1,5 +1,6 @@
project('Fortran calling C', 'fortran', 'c',
- meson_version: '>= 0.51.0')
+ meson_version: '>= 0.51.0',
+ default_options : ['default_library=static'])
ccid = meson.get_compiler('c').get_id()
if ccid == 'msvc' or ccid == 'clang-cl'
diff --git a/test cases/fortran/2 modules/meson.build b/test cases/fortran/2 modules/meson.build
index fb58b9d..791ae63 100644
--- a/test cases/fortran/2 modules/meson.build
+++ b/test cases/fortran/2 modules/meson.build
@@ -1,4 +1,5 @@
-project('modules', 'fortran')
+project('modules', 'fortran',
+ default_options : ['default_library=static'])
commented = library('commented', 'comment_mod.f90')
diff --git a/test cases/fortran/6 dynamic/meson.build b/test cases/fortran/6 dynamic/meson.build
index 244a38b..413223b 100644
--- a/test cases/fortran/6 dynamic/meson.build
+++ b/test cases/fortran/6 dynamic/meson.build
@@ -1,9 +1,11 @@
project('dynamic_fortran', 'fortran')
-if meson.get_compiler('fortran').get_id() == 'intel-cl'
- error('MESON_SKIP_TEST: Windows ifort does not use shared_library in a sane way')
+fcid = meson.get_compiler('fortran').get_id()
+if fcid == 'intel-cl' or (host_machine.system() == 'windows' and fcid == 'pgi')
+ error('MESON_SKIP_TEST: non-Gfortran Windows Fortran compilers do not do shared libraries in a Fortran standard way')
# !DEC$ ATTRIBUTES DLLEXPORT must be used!
# https://software.intel.com/en-us/node/535306
+ # https://www.pgroup.com/resources/docs/19.4/x86/pgi-user-guide/index.htm#lib-dynlnk-bld-dll-fort
endif
dynamic = shared_library('dynamic', 'dynamic.f90')
diff --git a/test cases/unit/55 introspection/meson.build b/test cases/unit/55 introspection/meson.build
index 3f013aa..7589f3f 100644
--- a/test cases/unit/55 introspection/meson.build
+++ b/test cases/unit/55 introspection/meson.build
@@ -25,7 +25,7 @@ var2 = 2.to_string()
var3 = 'test3'
t1 = executable('test' + var1, ['t1.cpp'], link_with: [sharedlib], install: true, build_by_default: get_option('test_opt2'))
-t2 = executable('test@0@'.format('@0@'.format(var2)), 't2.cpp', link_with: [staticlib])
+t2 = executable('test@0@'.format('@0@'.format(var2)), sources: ['t2.cpp'], link_with: [staticlib])
t3 = executable(var3, 't3.cpp', link_with: [sharedlib, staticlib], dependencies: [dep1])
### BEGIN: Test inspired by taisei: https://github.com/taisei-project/taisei/blob/master/meson.build#L293