aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Build-options.md21
-rw-r--r--docs/markdown/CMake-module.md2
-rw-r--r--docs/markdown/Dependencies.md2
-rw-r--r--docs/markdown/Pkgconfig-module.md2
-rw-r--r--docs/markdown/Reference-manual.md27
-rw-r--r--docs/markdown/Reference-tables.md31
-rw-r--r--docs/markdown/snippets/minstall_quiet.md11
-rw-r--r--docs/markdown/snippets/pkgconfig_dataonly.md15
-rw-r--r--mesonbuild/cmake/interpreter.py14
-rw-r--r--mesonbuild/compilers/compilers.py8
-rw-r--r--mesonbuild/coredata.py7
-rw-r--r--mesonbuild/environment.py26
-rw-r--r--mesonbuild/linkers.py59
-rw-r--r--mesonbuild/minstall.py72
-rw-r--r--mesonbuild/modules/cmake.py13
-rw-r--r--mesonbuild/modules/pkgconfig.py60
-rwxr-xr-xmesonbuild/msubprojects.py8
-rw-r--r--mesonbuild/scripts/depfixer.py21
-rwxr-xr-xrun_unittests.py21
-rw-r--r--test cases/cmake/1 basic/meson.build1
-rw-r--r--test cases/cmake/9 disabled subproject/meson.build3
-rw-r--r--test cases/common/47 pkgconfig-gen/installed_files.txt1
-rw-r--r--test cases/common/47 pkgconfig-gen/meson.build7
-rw-r--r--test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp3
-rw-r--r--test cases/failing build/4 cmake subproject isolation/main.cpp10
-rw-r--r--test cases/failing build/4 cmake subproject isolation/meson.build17
-rw-r--r--test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt10
-rw-r--r--test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp12
-rw-r--r--test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp14
29 files changed, 379 insertions, 119 deletions
diff --git a/docs/markdown/Build-options.md b/docs/markdown/Build-options.md
index 8b29afd..2d53e28 100644
--- a/docs/markdown/Build-options.md
+++ b/docs/markdown/Build-options.md
@@ -83,9 +83,9 @@ Currently supported in
- `disabled` do not look for the dependency and always return 'not-found'.
When getting the value of this type of option using `get_option()`, a special
-object is returned instead of the string representation of the option's value.
-That object has three methods returning boolean and taking no argument:
-`enabled()`, `disabled()`, and `auto()`.
+[feature option object](Reference-manual.md#feature-option-object)
+is returned instead of the string representation of the option's value.
+This object can be passed to `required`:
```meson
d = dependency('foo', required : get_option('myfeature'))
@@ -94,6 +94,21 @@ if d.found()
endif
```
+To check the value of the feature, the object has three methods
+returning a boolean and taking no argument:
+
+- `.enabled()`
+- `.disabled()`
+- `.auto()`
+
+This is useful for custom code depending on the feature:
+
+```meson
+if get_option('myfeature').enabled()
+ # ...
+endif
+```
+
If the value of a `feature` option is set to `auto`, that value is overridden by
the global `auto_features` option (which defaults to `auto`). This is intended
to be used by packagers who want to have full control on which dependencies are
diff --git a/docs/markdown/CMake-module.md b/docs/markdown/CMake-module.md
index a021396..a15e3c2 100644
--- a/docs/markdown/CMake-module.md
+++ b/docs/markdown/CMake-module.md
@@ -99,6 +99,8 @@ and supports the following methods:
- `get_variable(name)` fetches the specified variable from inside
the subproject. Usually `dependency()` or `target()` should be
preferred to extract build targets.
+ - `found` returns true if the subproject is available, otherwise false
+ *new in in 0.53.2*
## CMake configuration files
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index 50ea92f..8cffba4 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -181,7 +181,7 @@ should only be used if the CMake files are not stored in the project itself.
Additional CMake parameters can be specified with the `cmake_args` property.
-### Some notes on Dub
+## Dub
Please understand that meson is only able to find dependencies that
exist in the local Dub repository. You need to manually fetch and
diff --git a/docs/markdown/Pkgconfig-module.md b/docs/markdown/Pkgconfig-module.md
index 678090b..13fc4e6 100644
--- a/docs/markdown/Pkgconfig-module.md
+++ b/docs/markdown/Pkgconfig-module.md
@@ -56,6 +56,8 @@ keyword arguments.
D sources referred to by this pkg-config file
- `uninstalled_variables` used instead of the `variables` keyword argument, when
generating the uninstalled pkg-config file. Since *0.54.0*
+- `dataonly` field. (*since 0.54.0*) this is used for architecture-independent
+ pkg-config files in projects which also have architecture-dependent outputs.
Since 0.46 a `StaticLibrary` or `SharedLibrary` object can optionally be passed
as first positional argument. If one is provided a default value will be
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 510d443..475b711 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -846,8 +846,10 @@ configuration as-is, which may be absolute, or relative to `prefix`.
if you need the absolute path to one of these e.g. to use in a define
etc., you should use `get_option('prefix') / get_option('localstatedir')`
-For options of type `feature` a special object is returned instead of
-a string. See [`feature` options](Build-options.md#features)
+For options of type `feature` a
+[feature option object](#feature-option-object)
+is returned instead of a string.
+See [`feature` options](Build-options.md#features)
documentation for more details.
### get_variable()
@@ -1226,7 +1228,7 @@ This function is used to summarize build configuration at the end of the build
process. This function provides a way for projects (and subprojects) to report
this information in a clear way.
-The content is a serie of key/value pairs grouped into sections. If the section
+The content is a series of key/value pairs grouped into sections. If the section
keyword argument is omitted, those key/value pairs are implicitly grouped into a section
with no title. key/value pairs can optionally be grouped into a dictionary,
but keep in mind that dictionaries does not guarantee ordering. `key` must be string,
@@ -1285,7 +1287,7 @@ My Project 1.0
The first argument to this function must be a string defining the name
of this project. It is followed by programming languages that the
project uses. Supported values for languages are `c`, `cpp` (for
-`C++`), `d`, `objc`, `objcpp`, `fortran`, `java`, `cs` (for `C#`),
+`C++`), `cuda`, `d`, `objc`, `objcpp`, `fortran`, `java`, `cs` (for `C#`),
`vala` and `rust`. Since version `0.40.0` the list of languages
is optional.
@@ -1718,8 +1720,11 @@ the following methods.
given as an argument to be run during the install step, this script
will have the environment variables `MESON_SOURCE_ROOT`,
`MESON_BUILD_ROOT`, `MESON_INSTALL_PREFIX`,
- `MESON_INSTALL_DESTDIR_PREFIX`, and `MESONINTROSPECT` set. All
- additional arguments are passed as parameters.
+ `MESON_INSTALL_DESTDIR_PREFIX`, and `MESONINTROSPECT` set.
+ All positional arguments are passed as parameters.
+
+ *(added 0.54)* If `meson install` is called with the `--quiet` option, the
+ environment variable `MESON_INSTALL_QUIET` will be set.
Meson uses the `DESTDIR` environment variable as set by the
inherited environment to determine the (temporary) installation
@@ -2469,6 +2474,16 @@ library. This object has the following methods:
object will only inherit other attributes from its parent as
controlled by keyword arguments.
+### Feature option object
+
+The following methods are defined for all [`feature` options](Build-options.md#features):
+
+- `enabled()` returns whether the feature was set to `'enabled'`
+- `disabled()` returns whether the feature was set to `'disabled'`
+- `auto()` returns whether the feature was set to `'auto'`
+
+Feature options are available since 0.47.0.
+
### `generator` object
This object is returned by [`generator()`](#generator) and contains a
diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md
index 86524b7..9f432f0 100644
--- a/docs/markdown/Reference-tables.md
+++ b/docs/markdown/Reference-tables.md
@@ -33,16 +33,27 @@ These are return values of the `get_id` (Compiler family) and
## Linker ids
-These are return values of the `get_linker_id` (Linker family) method in a compiler object.
-
-| Value | Linker family |
-| ----- | --------------- |
-| ld.bfd | GNU Compiler Collection |
-| {ld.bfd,lld} | Clang non-Windows |
-| link | MSVC, Clang-cl, clang Windows |
-| pgi | Portland/Nvidia PGI |
-| {ld.bfd,gold,xild} | Intel compiler non-Windows |
-| xilink | Intel-cl Windows |
+These are return values of the `get_linker_id` method in a compiler object.
+
+| Value | Linker family |
+| ----- | --------------- |
+| ld.bfd | The GNU linker |
+| ld.gold | The GNU gold linker |
+| ld.lld | The LLVM linker, with the GNU interface |
+| ld.solaris | Solaris and illumos |
+| ld64 | Apple ld64 |
+| link | MSVC linker |
+| lld-link | The LLVM linker, with the MSVC interface |
+| xilink | Used with Intel-cl only, MSVC like |
+| optlink | optlink (used with DMD) |
+| rlink | The Renesas linker, used with CCrx only |
+| armlink | The ARM linker (arm and armclang compilers) |
+| pgi | Portland/Nvidia PGI |
+| nvlink | Nvidia Linker used with cuda |
+
+For languages that don't have separate dynamic linkers such as C# and Java, the
+`get_linker_id` will return the compiler name.
+
## Script environment variables
diff --git a/docs/markdown/snippets/minstall_quiet.md b/docs/markdown/snippets/minstall_quiet.md
new file mode 100644
index 0000000..3a7ff31
--- /dev/null
+++ b/docs/markdown/snippets/minstall_quiet.md
@@ -0,0 +1,11 @@
+## New option `--quiet` to `meson install`
+
+Now you can run `meson install --quiet` and meson will not verbosely print
+every file as it is being installed. As before, the full log is always
+available inside the builddir in `meson-logs/install-log.txt`.
+
+When this option is passed, install scripts will have the environment variable
+`MESON_INSTALL_QUIET` set.
+
+Numerous speed-ups were also made for the install step, especially on Windows
+where it is now 300% to 1200% faster than before depending on your workload.
diff --git a/docs/markdown/snippets/pkgconfig_dataonly.md b/docs/markdown/snippets/pkgconfig_dataonly.md
new file mode 100644
index 0000000..8a2564c
--- /dev/null
+++ b/docs/markdown/snippets/pkgconfig_dataonly.md
@@ -0,0 +1,15 @@
+## Introduce dataonly for the pkgconfig module
+This allows users to disable writing out the inbuilt variables to
+the pkg-config file as they might actualy not be required.
+
+One reason to have this is for architecture-independent pkg-config
+files in projects which also have architecture-dependent outputs.
+
+```
+pkgg.generate(
+ name : 'libhello_nolib',
+ description : 'A minimalistic pkgconfig file.',
+ version : libver,
+ dataonly: true
+)
+```
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 81844a0..4d87705 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -399,7 +399,19 @@ class ConverterTarget:
if not os.path.isabs(x):
x = os.path.normpath(os.path.join(self.src_dir, x))
if not os.path.exists(x) and not any([x.endswith(y) for y in obj_suffixes]) and not is_generated:
- mlog.warning('CMake: path', mlog.bold(x), 'does not exist. Ignoring. This can lead to build errors')
+ mlog.warning('CMake: path', mlog.bold(x), 'does not exist.')
+ mlog.warning(' --> Ignoring. This can lead to build errors.')
+ return None
+ if (
+ os.path.isabs(x)
+ and os.path.commonpath([x, self.env.get_source_dir()]) == self.env.get_source_dir()
+ and not (
+ os.path.commonpath([x, root_src_dir]) == root_src_dir or
+ os.path.commonpath([x, self.env.get_build_dir()]) == self.env.get_build_dir()
+ )
+ ):
+ mlog.warning('CMake: path', mlog.bold(x), 'is inside the root project but', mlog.bold('not'), 'inside the subproject.')
+ mlog.warning(' --> Ignoring. This can lead to build errors.')
return None
if os.path.isabs(x) and os.path.commonpath([x, self.env.get_build_dir()]) == self.env.get_build_dir():
if is_header:
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 03b1a33..2f1e104 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -724,7 +724,13 @@ class Compiler:
return self.id
def get_linker_id(self) -> str:
- return self.linker.id
+ # There is not guarantee that we have a dynamic linker instance, as
+ # some languages don't have separate linkers and compilers. In those
+ # cases return the compiler id
+ try:
+ return self.linker.id
+ except AttributeError:
+ return self.id
def get_version_string(self) -> str:
details = [self.id, self.version]
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 720d064..11b8deb 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -850,6 +850,9 @@ def read_cmd_line_file(build_dir, options):
# literal_eval to get it into the list of strings.
options.native_file = ast.literal_eval(properties.get('native_file', '[]'))
+def cmd_line_options_to_string(options):
+ return {k: str(v) for k, v in options.cmd_line_options.items()}
+
def write_cmd_line_file(build_dir, options):
filename = get_cmd_line_file(build_dir)
config = CmdLineFileParser()
@@ -860,7 +863,7 @@ def write_cmd_line_file(build_dir, options):
if options.native_file:
properties['native_file'] = options.native_file
- config['options'] = options.cmd_line_options
+ config['options'] = cmd_line_options_to_string(options)
config['properties'] = properties
with open(filename, 'w') as f:
config.write(f)
@@ -869,7 +872,7 @@ def update_cmd_line_file(build_dir, options):
filename = get_cmd_line_file(build_dir)
config = CmdLineFileParser()
config.read(filename)
- config['options'].update(options.cmd_line_options)
+ config['options'].update(cmd_line_options_to_string(options))
with open(filename, 'w') as f:
config.write(f)
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 554d79b..eb626b0 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -47,7 +47,8 @@ from .linkers import (
CcrxDynamicLinker,
ClangClDynamicLinker,
DynamicLinker,
- GnuDynamicLinker,
+ GnuBFDDynamicLinker,
+ GnuGoldDynamicLinker,
LLVMDynamicLinker,
MSVCDynamicLinker,
OptlinkDynamicLinker,
@@ -767,7 +768,7 @@ class Environment:
if o.startswith('LLD'):
if '(compatible with GNU linkers)' in o:
return LLVMDynamicLinker(
- compiler, for_machine, 'lld', comp_class.LINKER_PREFIX,
+ compiler, for_machine, comp_class.LINKER_PREFIX,
override, version=search_version(o))
if value is not None:
@@ -830,7 +831,7 @@ class Environment:
v = search_version(o)
if o.startswith('LLD'):
linker = LLVMDynamicLinker(
- compiler, for_machine, 'lld', comp_class.LINKER_PREFIX, override, version=v) # type: DynamicLinker
+ compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) # type: DynamicLinker
elif e.startswith('lld-link: '):
# Toolchain wrapper got in the way; this happens with e.g. https://github.com/mstorsjo/llvm-mingw
# Let's try to extract the linker invocation command to grab the version.
@@ -846,30 +847,29 @@ class Environment:
_, o, e = Popen_safe([linker_cmd, '--version'])
v = search_version(o)
- linker = LLVMDynamicLinker(compiler, for_machine, 'lld', comp_class.LINKER_PREFIX, override, version=v)
+ linker = LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
# first is for apple clang, second is for real gcc, the third is icc
elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e:
if isinstance(comp_class.LINKER_PREFIX, str):
_, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-v'] + extra_args)
else:
_, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-v'] + extra_args)
- i = 'APPLE ld'
for line in e.split('\n'):
if 'PROJECT:ld' in line:
v = line.split('-')[1]
break
else:
v = 'unknown version'
- linker = AppleDynamicLinker(compiler, for_machine, i, comp_class.LINKER_PREFIX, override, version=v)
+ linker = AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif 'GNU' in o:
if 'gold' in o:
- i = 'GNU ld.gold'
+ cls = GnuGoldDynamicLinker
else:
- i = 'GNU ld.bfd'
- linker = GnuDynamicLinker(compiler, for_machine, i, comp_class.LINKER_PREFIX, override, version=v)
+ cls = GnuBFDDynamicLinker
+ linker = cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v)
elif 'Solaris' in e or 'Solaris' in o:
linker = SolarisDynamicLinker(
- compiler, for_machine, 'solaris', comp_class.LINKER_PREFIX, override,
+ compiler, for_machine, comp_class.LINKER_PREFIX, override,
version=search_version(e))
else:
raise EnvironmentException('Unable to determine dynamic linker')
@@ -1061,7 +1061,7 @@ class Environment:
if 'PGI Compilers' in out:
cls = PGICCompiler if lang == 'c' else PGICPPCompiler
self.coredata.add_lang_args(cls.language, cls, for_machine, self)
- linker = PGIDynamicLinker(compiler, for_machine, 'pgi', cls.LINKER_PREFIX, [], version=version)
+ linker = PGIDynamicLinker(compiler, for_machine, cls.LINKER_PREFIX, [], version=version)
return cls(
ccache + compiler, version, for_machine, is_cross,
info, exe_wrap, linker=linker)
@@ -1214,7 +1214,7 @@ class Environment:
if 'PGI Compilers' in out:
cls = PGIFortranCompiler
self.coredata.add_lang_args(cls.language, cls, for_machine, self)
- linker = PGIDynamicLinker(compiler, for_machine, 'pgi',
+ linker = PGIDynamicLinker(compiler, for_machine,
cls.LINKER_PREFIX, [], version=version)
return cls(
compiler, version, for_machine, is_cross, info, exe_wrap,
@@ -1413,7 +1413,7 @@ class Environment:
linker = type(cc.linker)(for_machine, always_args, exelist=cc.linker.exelist,
version=cc.linker.version, **extra_args)
else:
- linker = type(cc.linker)(compiler, for_machine, cc.linker.id, cc.LINKER_PREFIX,
+ linker = type(cc.linker)(compiler, for_machine, cc.LINKER_PREFIX,
always_args=always_args, version=cc.linker.version,
**extra_args)
elif 'link' in override[0]:
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index dbd90b2..84eb359 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -257,8 +257,8 @@ class DynamicLinker(metaclass=abc.ABCMeta):
ret += self.prefix_arg + [arg]
return ret
- def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
- id_: str, prefix_arg: T.Union[str, T.List[str]],
+ def __init__(self, id_: str, exelist: T.List[str],
+ for_machine: mesonlib.MachineChoice, prefix_arg: T.Union[str, T.List[str]],
always_args: T.List[str], *, version: str = 'unknown version'):
self.exelist = exelist
self.for_machine = for_machine
@@ -570,6 +570,9 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Apple's ld implementation."""
+ def __init__(self, *args, **kwargs):
+ super().__init__('ld64', *args, **kwargs)
+
def get_asneeded_args(self) -> T.List[str]:
return self._apply_prefix('-dead_strip_dylibs')
@@ -649,17 +652,38 @@ class GnuDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dynam
"""Representation of GNU ld.bfd and ld.gold."""
- pass
+
+class GnuGoldDynamicLinker(GnuDynamicLinker):
+
+ def __init__(self, *args, **kwargs):
+ super().__init__('ld.gold', *args, **kwargs)
+
+
+class GnuBFDDynamicLinker(GnuDynamicLinker):
+
+ def __init__(self, *args, **kwargs):
+ super().__init__('ld.bfd', *args, **kwargs)
class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker):
- """Representation of LLVM's lld (not lld-link) linker.
+ """Representation of LLVM's ld.lld linker.
- This is only the posix-like linker.
+ This is only the gnu-like linker, not the apple like or link.exe like
+ linkers.
"""
- pass
+ def __init__(self, *args, **kwargs):
+ super().__init__('ld.lld', *args, **kwargs)
+
+ # Some targets don't seem to support this argument (windows, wasm, ...)
+ _, _, e = mesonlib.Popen_safe(self.exelist + self._apply_prefix('--allow-shlib-undefined'))
+ self.has_allow_shlib_undefined = not ('unknown argument: --allow-shlib-undefined' in e)
+
+ def get_allow_undefined_args(self) -> T.List[str]:
+ if self.has_allow_shlib_undefined:
+ return self._apply_prefix('--allow-shlib-undefined')
+ return []
class CcrxDynamicLinker(DynamicLinker):
@@ -668,7 +692,7 @@ class CcrxDynamicLinker(DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
- super().__init__(['rlink.exe'], for_machine, 'rlink', '', [],
+ super().__init__('rlink', ['rlink.exe'], for_machine, '', [],
version=version)
def get_accepts_rsp(self) -> bool:
@@ -701,7 +725,7 @@ class ArmDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
- super().__init__(['armlink'], for_machine, 'armlink', '', [],
+ super().__init__('armlink', ['armlink'], for_machine, '', [],
version=version)
def get_accepts_rsp(self) -> bool:
@@ -733,6 +757,9 @@ class PGIDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""PGI linker."""
+ def __init__(self, *args, **kwargs):
+ super().__init__('pgi', *args, **kwargs)
+
def get_allow_undefined_args(self) -> T.List[str]:
return []
@@ -846,7 +873,7 @@ class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version',
direct: bool = True):
- super().__init__(exelist or ['link.exe'], for_machine, 'link',
+ super().__init__('link', exelist or ['link.exe'], for_machine,
prefix, always_args, machine=machine, version=version, direct=direct)
def get_always_args(self) -> T.List[str]:
@@ -862,7 +889,7 @@ class ClangClDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
prefix: T.Union[str, T.List[str]] = '',
machine: str = 'x86', version: str = 'unknown version',
direct: bool = True):
- super().__init__(exelist or ['lld-link.exe'], for_machine, 'lld-link',
+ super().__init__('lld-link', exelist or ['lld-link.exe'], for_machine,
prefix, always_args, machine=machine, version=version, direct=direct)
@@ -872,13 +899,16 @@ class XilinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
def __init__(self, for_machine: mesonlib.MachineChoice, always_args: T.List[str],
*, version: str = 'unknown version'):
- super().__init__(['xilink.exe'], for_machine, 'xilink', '', always_args, version=version)
+ super().__init__('xilink', ['xilink.exe'], for_machine, '', always_args, version=version)
class SolarisDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Sys-V derived linker used on Solaris and OpenSolaris."""
+ def __init__(self, *args, **kwargs):
+ super().__init__('ld.solaris', *args, **kwargs)
+
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
if not args:
return args
@@ -929,13 +959,18 @@ class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
*, version: str = 'unknown version'):
# Use optlink instead of link so we don't interfer with other link.exe
# implementations.
- super().__init__(['optlink.exe'], for_machine, 'optlink', '', [], version=version)
+ super().__init__('optlink', ['optlink.exe'], for_machine, '', [], version=version)
def get_allow_undefined_args(self) -> T.List[str]:
return []
+
class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Cuda linker (nvlink)"""
+
+ def __init__(self, *args, **kwargs):
+ super().__init__('nvlink', *args, **kwargs)
+
@staticmethod
def parse_version():
version_cmd = ['nvlink', '--version']
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index cc6ea0a..64bcca2 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -13,6 +13,7 @@
# limitations under the License.
import sys, pickle, os, shutil, subprocess, errno
+import argparse
import shlex
from glob import glob
from .scripts import depfixer
@@ -35,10 +36,14 @@ selinux_updates = []
def add_arguments(parser):
parser.add_argument('-C', default='.', dest='wd',
help='directory to cd into before running')
+ parser.add_argument('--profile-self', action='store_true', dest='profile',
+ help=argparse.SUPPRESS)
parser.add_argument('--no-rebuild', default=False, action='store_true',
help='Do not rebuild before installing.')
parser.add_argument('--only-changed', default=False, action='store_true',
help='Only overwrite files that are older than the copied file.')
+ parser.add_argument('--quiet', default=False, action='store_true',
+ help='Do not print every file that was installed.')
class DirMaker:
def __init__(self, lf):
@@ -216,6 +221,10 @@ class Installer:
self.lf = lf
self.preserved_file_count = 0
+ def log(self, msg):
+ if not self.options.quiet:
+ print(msg)
+
def should_preserve_existing_file(self, from_file, to_file):
if not self.options.only_changed:
return False
@@ -226,7 +235,7 @@ class Installer:
to_time = os.stat(to_file).st_mtime
return from_time <= to_time
- def do_copyfile(self, from_file, to_file):
+ def do_copyfile(self, from_file, to_file, makedirs=None):
outdir = os.path.split(to_file)[0]
if not os.path.isfile(from_file) and not os.path.islink(from_file):
raise RuntimeError('Tried to install something that isn\'t a file:'
@@ -243,7 +252,12 @@ class Installer:
self.preserved_file_count += 1
return False
os.remove(to_file)
- print('Installing %s to %s' % (from_file, outdir))
+ elif makedirs:
+ # Unpack tuple
+ dirmaker, outdir = makedirs
+ # Create dirs if needed
+ dirmaker.makedirs(outdir, exist_ok=True)
+ self.log('Installing %s to %s' % (from_file, outdir))
if os.path.islink(from_file):
if not os.path.exists(from_file):
# Dangling symlink. Replicate as is.
@@ -318,6 +332,7 @@ class Installer:
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)
+ sys.exit(1)
parent_dir = os.path.dirname(abs_dst)
if not os.path.isdir(parent_dir):
os.mkdir(parent_dir)
@@ -347,10 +362,10 @@ class Installer:
restore_selinux_contexts()
self.run_install_script(d)
if not self.did_install_something:
- print('Nothing to install.')
- if self.preserved_file_count > 0:
- print('Preserved {} unchanged files, see {} for the full list'
- .format(self.preserved_file_count, os.path.normpath(self.lf.name)))
+ self.log('Nothing to install.')
+ if not self.options.quiet and self.preserved_file_count > 0:
+ self.log('Preserved {} unchanged files, see {} for the full list'
+ .format(self.preserved_file_count, os.path.normpath(self.lf.name)))
except PermissionError:
if shutil.which('pkexec') is not None and 'PKEXEC_UID' not in os.environ:
print('Installation failed due to insufficient permissions.')
@@ -364,42 +379,39 @@ class Installer:
for (src_dir, dst_dir, mode, exclude) in d.install_subdirs:
self.did_install_something = True
full_dst_dir = get_destdir_path(d, dst_dir)
- print('Installing subdir %s to %s' % (src_dir, full_dst_dir))
+ self.log('Installing subdir %s to %s' % (src_dir, full_dst_dir))
d.dirmaker.makedirs(full_dst_dir, exist_ok=True)
self.do_copydir(d, src_dir, full_dst_dir, exclude, mode)
def install_data(self, d):
for i in d.data:
- self.did_install_something = True
fullfilename = i[0]
outfilename = get_destdir_path(d, i[1])
mode = i[2]
outdir = os.path.dirname(outfilename)
- d.dirmaker.makedirs(outdir, exist_ok=True)
- self.do_copyfile(fullfilename, outfilename)
+ if self.do_copyfile(fullfilename, outfilename, makedirs=(d.dirmaker, outdir)):
+ self.did_install_something = True
set_mode(outfilename, mode, d.install_umask)
def install_man(self, d):
for m in d.man:
- self.did_install_something = True
full_source_filename = m[0]
outfilename = get_destdir_path(d, m[1])
outdir = os.path.dirname(outfilename)
- d.dirmaker.makedirs(outdir, exist_ok=True)
install_mode = m[2]
- self.do_copyfile(full_source_filename, outfilename)
+ if self.do_copyfile(full_source_filename, outfilename, makedirs=(d.dirmaker, outdir)):
+ self.did_install_something = True
set_mode(outfilename, install_mode, d.install_umask)
def install_headers(self, d):
for t in d.headers:
- self.did_install_something = True
fullfilename = t[0]
fname = os.path.basename(fullfilename)
outdir = get_destdir_path(d, t[1])
outfilename = os.path.join(outdir, fname)
install_mode = t[2]
- d.dirmaker.makedirs(outdir, exist_ok=True)
- self.do_copyfile(fullfilename, outfilename)
+ if self.do_copyfile(fullfilename, outfilename, makedirs=(d.dirmaker, outdir)):
+ self.did_install_something = True
set_mode(outfilename, install_mode, d.install_umask)
def run_install_script(self, d):
@@ -409,6 +421,8 @@ class Installer:
'MESON_INSTALL_DESTDIR_PREFIX': d.fullprefix,
'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in d.mesonintrospect]),
}
+ if self.options.quiet:
+ env['MESON_INSTALL_QUIET'] = '1'
child_env = os.environ.copy()
child_env.update(env)
@@ -418,7 +432,7 @@ class Installer:
script = i['exe']
args = i['args']
name = ' '.join(script + args)
- print('Running custom install script {!r}'.format(name))
+ self.log('Running custom install script {!r}'.format(name))
try:
rc = subprocess.call(script + args, env=child_env)
if rc != 0:
@@ -429,14 +443,14 @@ class Installer:
def install_targets(self, d):
for t in d.targets:
- self.did_install_something = True
if not os.path.exists(t.fname):
# For example, import libraries of shared modules are optional
if t.optional:
- print('File {!r} not found, skipping'.format(t.fname))
+ self.log('File {!r} not found, skipping'.format(t.fname))
continue
else:
raise RuntimeError('File {!r} could not be found'.format(t.fname))
+ file_copied = False # not set when a directory is copied
fname = check_for_stampfile(t.fname)
outdir = get_destdir_path(d, t.outdir)
outname = os.path.join(outdir, os.path.basename(fname))
@@ -446,17 +460,16 @@ class Installer:
install_rpath = t.install_rpath
install_name_mappings = t.install_name_mappings
install_mode = t.install_mode
- 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):
- self.do_copyfile(fname, outname)
+ file_copied = self.do_copyfile(fname, outname, makedirs=(d.dirmaker, outdir))
set_mode(outname, install_mode, d.install_umask)
if should_strip and d.strip_bin is not None:
if fname.endswith('.jar'):
- print('Not stripping jar target:', os.path.basename(fname))
+ self.log('Not stripping jar target:', os.path.basename(fname))
continue
- print('Stripping target {!r} using {}.'.format(fname, d.strip_bin[0]))
+ self.log('Stripping target {!r} using {}.'.format(fname, d.strip_bin[0]))
ps, stdo, stde = Popen_safe(d.strip_bin + [outname])
if ps.returncode != 0:
print('Could not strip file.\n')
@@ -469,10 +482,11 @@ class Installer:
wasm_source = os.path.splitext(fname)[0] + '.wasm'
if os.path.exists(wasm_source):
wasm_output = os.path.splitext(outname)[0] + '.wasm'
- self.do_copyfile(wasm_source, wasm_output)
+ file_copied = self.do_copyfile(wasm_source, wasm_output)
elif os.path.isdir(fname):
fname = os.path.join(d.build_dir, fname.rstrip('/'))
outname = os.path.join(outdir, os.path.basename(fname))
+ d.dirmaker.makedirs(outdir, exist_ok=True)
self.do_copydir(d, fname, outname, None, install_mode)
else:
raise RuntimeError('Unknown file type for {!r}'.format(fname))
@@ -491,7 +505,8 @@ class Installer:
print("Symlink creation does not work on this platform. "
"Skipping all symlinking.")
printed_symlink_error = True
- if os.path.isfile(outname):
+ if file_copied:
+ self.did_install_something = True
try:
depfixer.fix_rpath(outname, install_rpath, final_path,
install_name_mappings, verbose=False)
@@ -515,5 +530,10 @@ def run(opts):
installer = Installer(opts, lf)
append_to_log(lf, '# List of files installed by Meson')
append_to_log(lf, '# Does not contain files installed by custom scripts.')
- installer.do_install(datafilename)
+ if opts.profile:
+ import cProfile as profile
+ fname = os.path.join(private_dir, 'profile-installer.log')
+ profile.runctx('installer.do_install(datafilename)', globals(), locals(), filename=fname)
+ else:
+ installer.do_install(datafilename)
return 0
diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py
index 21f144f..6c4098b 100644
--- a/mesonbuild/modules/cmake.py
+++ b/mesonbuild/modules/cmake.py
@@ -18,7 +18,7 @@ import shutil
from . import ExtensionModule, ModuleReturnValue
from .. import build, dependencies, mesonlib, mlog
-from ..interpreterbase import permittedKwargs, FeatureNew, stringArgs, InterpreterObject, ObjectHolder
+from ..interpreterbase import permittedKwargs, FeatureNew, stringArgs, InterpreterObject, ObjectHolder, noPosargs
from ..interpreter import ConfigurationDataHolder, InterpreterException, SubprojectHolder
@@ -66,6 +66,7 @@ class CMakeSubprojectHolder(InterpreterObject, ObjectHolder):
'target': self.target,
'target_type': self.target_type,
'target_list': self.target_list,
+ 'found': self.found_method,
})
def _args_to_info(self, args):
@@ -105,12 +106,18 @@ class CMakeSubprojectHolder(InterpreterObject, ObjectHolder):
info = self._args_to_info(args)
return info['func']
+ @noPosargs
@permittedKwargs({})
def target_list(self, args, kwargs):
- if len(args) > 0:
- raise InterpreterException('target_list does not take any parameters.')
return self.held_object.cm_interpreter.target_list()
+ @noPosargs
+ @permittedKwargs({})
+ @FeatureNew('CMakeSubproject.found()', '0.53.2')
+ def found_method(self, args, kwargs):
+ return self.held_object is not None
+
+
class CmakeModule(ExtensionModule):
cmake_detected = False
cmake_root = None
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index da0a60e..cfdae4f 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -266,7 +266,7 @@ class PkgConfigModule(ExtensionModule):
def generate_pkgconfig_file(self, state, deps, subdirs, name, description,
url, version, pcfile, conflicts, variables,
- uninstalled=False):
+ uninstalled=False, dataonly=False):
deps.remove_dups()
coredata = state.environment.get_coredata()
if uninstalled:
@@ -283,12 +283,13 @@ class PkgConfigModule(ExtensionModule):
incdir = PurePath(coredata.get_builtin_option('includedir'))
fname = os.path.join(outdir, pcfile)
with open(fname, 'w', encoding='utf-8') as ofile:
- ofile.write('prefix={}\n'.format(self._escape(prefix)))
- if uninstalled:
- ofile.write('srcdir={}\n'.format(self._escape(srcdir)))
- else:
- ofile.write('libdir={}\n'.format(self._escape('${prefix}' / libdir)))
- ofile.write('includedir={}\n'.format(self._escape('${prefix}' / incdir)))
+ if not dataonly:
+ ofile.write('prefix={}\n'.format(self._escape(prefix)))
+ if uninstalled:
+ ofile.write('srcdir={}\n'.format(self._escape(srcdir)))
+ else:
+ ofile.write('libdir={}\n'.format(self._escape('${prefix}' / libdir)))
+ ofile.write('includedir={}\n'.format(self._escape('${prefix}' / incdir)))
if variables:
ofile.write('\n')
for k, v in variables:
@@ -370,27 +371,28 @@ class PkgConfigModule(ExtensionModule):
ofile.write('Libs: {}\n'.format(' '.join(generate_libs_flags(deps.pub_libs))))
if len(deps.priv_libs) > 0:
ofile.write('Libs.private: {}\n'.format(' '.join(generate_libs_flags(deps.priv_libs))))
+
+ def generate_compiler_flags():
+ cflags_buf = []
+ for f in deps.cflags:
+ cflags_buf.append(self._escape(f))
+ return cflags_buf
+
+ cflags = generate_compiler_flags()
ofile.write('Cflags:')
if uninstalled:
ofile.write(' '.join(generate_uninstalled_cflags(deps.pub_libs + deps.priv_libs)))
- else:
- for h in subdirs:
- ofile.write(' ')
- if h == '.':
- ofile.write('-I${includedir}')
- else:
- ofile.write(self._escape(PurePath('-I${includedir}') / h))
- for f in deps.cflags:
- ofile.write(' ')
- ofile.write(self._escape(f))
- ofile.write('\n')
+ elif not dataonly and cflags:
+ ofile.write('{}\n'.format(' '.join(cflags)))
@FeatureNewKwargs('pkgconfig.generate', '0.54.0', ['uninstalled_variables'])
@FeatureNewKwargs('pkgconfig.generate', '0.42.0', ['extra_cflags'])
@FeatureNewKwargs('pkgconfig.generate', '0.41.0', ['variables'])
+ @FeatureNewKwargs('pkgconfig.generate', '0.54.0', ['dataonly'])
@permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase',
'subdirs', 'requires', 'requires_private', 'libraries_private',
- 'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions'})
+ 'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions',
+ 'dataonly'})
def generate(self, state, args, kwargs):
if 'variables' in kwargs:
FeatureNew('custom pkgconfig variables', '0.41.0').use(state.subproject)
@@ -399,6 +401,7 @@ class PkgConfigModule(ExtensionModule):
default_description = None
default_name = None
mainlib = None
+ default_subdirs = ['.']
if not args and 'version' not in kwargs:
FeatureNew('pkgconfig.generate implicit version keyword', '0.46.0').use(state.subproject)
elif len(args) == 1:
@@ -414,7 +417,14 @@ class PkgConfigModule(ExtensionModule):
elif len(args) > 1:
raise mesonlib.MesonException('Too many positional arguments passed to Pkgconfig_gen.')
- subdirs = mesonlib.stringlistify(kwargs.get('subdirs', ['.']))
+ dataonly = kwargs.get('dataonly', False)
+ if dataonly:
+ default_subdirs = []
+ blocked_vars = ['libraries', 'libraries_private', 'require_private', 'extra_cflags', 'subdirs']
+ if len(set(kwargs) & set(blocked_vars)) > 0:
+ raise mesonlib.MesonException('Cannot combine dataonly with any of {}'.format(blocked_vars))
+
+ subdirs = mesonlib.stringlistify(kwargs.get('subdirs', default_subdirs))
version = kwargs.get('version', default_version)
if not isinstance(version, str):
raise mesonlib.MesonException('Version must be specified.')
@@ -440,6 +450,11 @@ class PkgConfigModule(ExtensionModule):
libraries = [mainlib] + libraries
deps = DependenciesHelper(state, filebase)
+ for d in subdirs:
+ if d == '.':
+ deps.add_cflags(['-I${includedir}'])
+ else:
+ deps.add_cflags(self._escape(PurePath('-I${includedir}') / d))
deps.add_pub_libs(libraries)
deps.add_priv_libs(kwargs.get('libraries_private', []))
deps.add_pub_reqs(kwargs.get('requires', []))
@@ -488,13 +503,14 @@ class PkgConfigModule(ExtensionModule):
if not isinstance(pkgroot, str):
raise mesonlib.MesonException('Install_dir must be a string.')
self.generate_pkgconfig_file(state, deps, subdirs, name, description, url,
- version, pcfile, conflicts, variables)
+ version, pcfile, conflicts, variables,
+ False, dataonly)
res = build.Data(mesonlib.File(True, state.environment.get_scratch_dir(), pcfile), pkgroot)
variables = parse_variable_list(mesonlib.stringlistify(kwargs.get('uninstalled_variables', [])))
pcfile = filebase + '-uninstalled.pc'
self.generate_pkgconfig_file(state, deps, subdirs, name, description, url,
version, pcfile, conflicts, variables,
- uninstalled=True)
+ uninstalled=True, dataonly=dataonly)
# Associate the main library with this generated pc file. If the library
# is used in any subsequent call to the generated, it will generate a
# 'Requires:' or 'Requires.private:'.
diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py
index d6f0715..b1c79b8 100755
--- a/mesonbuild/msubprojects.py
+++ b/mesonbuild/msubprojects.py
@@ -60,7 +60,7 @@ def update_git(wrap, repo_dir, options):
git_output(['fetch'], repo_dir)
git_output(['checkout', revision], repo_dir)
except subprocess.CalledProcessError as e:
- out = e.output.decode().strip()
+ out = e.output.strip()
mlog.log(' -> Could not checkout revision', mlog.cyan(revision))
mlog.log(mlog.red(out))
mlog.log(mlog.red(str(e)))
@@ -70,7 +70,7 @@ def update_git(wrap, repo_dir, options):
# We are in the same branch, pull latest commits
git_output(['-c', 'rebase.autoStash=true', 'pull', '--rebase'], repo_dir)
except subprocess.CalledProcessError as e:
- out = e.output.decode().strip()
+ out = e.output.strip()
mlog.log(' -> Could not rebase', mlog.bold(repo_dir), 'please fix and try again.')
mlog.log(mlog.red(out))
mlog.log(mlog.red(str(e)))
@@ -83,7 +83,7 @@ def update_git(wrap, repo_dir, options):
git_output(['fetch'], repo_dir)
git_output(['-c', 'rebase.autoStash=true', 'rebase', revision], repo_dir)
except subprocess.CalledProcessError as e:
- out = e.output.decode().strip()
+ out = e.output.strip()
mlog.log(' -> Could not rebase', mlog.bold(repo_dir), 'please fix and try again.')
mlog.log(mlog.red(out))
mlog.log(mlog.red(str(e)))
@@ -153,7 +153,7 @@ def checkout(wrap, repo_dir, options):
git_output(cmd, repo_dir)
git_show(repo_dir)
except subprocess.CalledProcessError as e:
- out = e.output.decode().strip()
+ out = e.output.strip()
mlog.log(' -> ', mlog.red(out))
def download(wrap, repo_dir, options):
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index 5be7d40..5ba3a97 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -26,6 +26,9 @@ DT_STRTAB = 5
DT_SONAME = 14
DT_MIPS_RLD_MAP_REL = 1879048245
+# Global cache for tools
+INSTALL_NAME_TOOL = False
+
class DataSizes:
def __init__(self, ptrsize, is_le):
if is_le:
@@ -428,11 +431,11 @@ def fix_jar(fname):
subprocess.check_call(['jar', 'ufm', fname, 'META-INF/MANIFEST.MF'])
def fix_rpath(fname, new_rpath, final_path, install_name_mappings, verbose=True):
- # Static libraries never have rpaths
- if fname.endswith('.a'):
- return
- # DLLs and EXE never have rpaths
- if fname.endswith('.dll') or fname.endswith('.exe'):
+ global INSTALL_NAME_TOOL
+ # Static libraries, import libraries, debug information, headers, etc
+ # never have rpaths
+ # DLLs and EXE currently do not need runtime path fixing
+ if fname.endswith(('.a', '.lib', '.pdb', '.h', '.hpp', '.dll', '.exe')):
return
try:
if fname.endswith('.jar'):
@@ -445,5 +448,11 @@ def fix_rpath(fname, new_rpath, final_path, install_name_mappings, verbose=True)
pass
else:
raise
- if shutil.which('install_name_tool'):
+ # We don't look for this on import because it will do a useless PATH lookup
+ # on non-mac platforms. That can be expensive on some Windows machines
+ # (upto 30ms), which is significant with --only-changed. For details, see:
+ # https://github.com/mesonbuild/meson/pull/6612#discussion_r378581401
+ if INSTALL_NAME_TOOL is False:
+ INSTALL_NAME_TOOL = shutil.which('install_name_tool')
+ if INSTALL_NAME_TOOL:
fix_darwin(fname, new_rpath, final_path, install_name_mappings)
diff --git a/run_unittests.py b/run_unittests.py
index 56618df..033647c 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -4974,6 +4974,11 @@ class LinuxlikeTests(BasePlatformTests):
self.assertEqual(foo_dep.get_pkgconfig_variable('foo', {}), 'bar')
self.assertPathEqual(foo_dep.get_pkgconfig_variable('datadir', {}), '/usr/data')
+ libhello_nolib = PkgConfigDependency('libhello_nolib', env, kwargs)
+ self.assertTrue(libhello_nolib.found())
+ self.assertEqual(libhello_nolib.get_link_args(), [])
+ self.assertEqual(libhello_nolib.get_compile_args(), [])
+
def test_pkgconfig_gen_deps(self):
'''
Test that generated pkg-config files correctly handle dependencies
@@ -6060,30 +6065,30 @@ c = ['{0}']
self.assertEqual(comp.linker.id, expected)
def test_ld_environment_variable_bfd(self):
- self._check_ld('ld.bfd', 'bfd', 'c', 'GNU ld.bfd')
+ self._check_ld('ld.bfd', 'bfd', 'c', 'ld.bfd')
def test_ld_environment_variable_gold(self):
- self._check_ld('ld.gold', 'gold', 'c', 'GNU ld.gold')
+ self._check_ld('ld.gold', 'gold', 'c', 'ld.gold')
def test_ld_environment_variable_lld(self):
- self._check_ld('ld.lld', 'lld', 'c', 'lld')
+ self._check_ld('ld.lld', 'lld', 'c', 'ld.lld')
@skipIfNoExecutable('rustc')
def test_ld_environment_variable_rust(self):
- self._check_ld('ld.gold', 'gold', 'rust', 'GNU ld.gold')
+ self._check_ld('ld.gold', 'gold', 'rust', 'ld.gold')
def test_ld_environment_variable_cpp(self):
- self._check_ld('ld.gold', 'gold', 'cpp', 'GNU ld.gold')
+ self._check_ld('ld.gold', 'gold', 'cpp', 'ld.gold')
def test_ld_environment_variable_objc(self):
- self._check_ld('ld.gold', 'gold', 'objc', 'GNU ld.gold')
+ self._check_ld('ld.gold', 'gold', 'objc', 'ld.gold')
def test_ld_environment_variable_objcpp(self):
- self._check_ld('ld.gold', 'gold', 'objcpp', 'GNU ld.gold')
+ self._check_ld('ld.gold', 'gold', 'objcpp', 'ld.gold')
@skipIfNoExecutable('gfortran')
def test_ld_environment_variable_fortran(self):
- self._check_ld('ld.gold', 'gold', 'fortran', 'GNU ld.gold')
+ self._check_ld('ld.gold', 'gold', 'fortran', 'ld.gold')
def compute_sha256(self, filename):
with open(filename, 'rb') as f:
diff --git a/test cases/cmake/1 basic/meson.build b/test cases/cmake/1 basic/meson.build
index 8e1671a..19c87c4 100644
--- a/test cases/cmake/1 basic/meson.build
+++ b/test cases/cmake/1 basic/meson.build
@@ -5,6 +5,7 @@ cm = import('cmake')
sub_pro = cm.subproject('cmMod')
sub_dep = sub_pro.dependency('cmModLib++')
+assert(sub_pro.found(), 'found() method reports not found, but should be found')
assert(sub_pro.target_list() == ['cmModLib++'], 'There should be exactly one target')
assert(sub_pro.target_type('cmModLib++') == 'shared_library', 'Target type should be shared_library')
diff --git a/test cases/cmake/9 disabled subproject/meson.build b/test cases/cmake/9 disabled subproject/meson.build
index ba38410..c153fa3 100644
--- a/test cases/cmake/9 disabled subproject/meson.build
+++ b/test cases/cmake/9 disabled subproject/meson.build
@@ -2,4 +2,5 @@ project('cmakeSubTest', ['c', 'cpp'])
cm = import('cmake')
-sub_pro = cm.subproject('nothinig', required: false) \ No newline at end of file
+sub_pro = cm.subproject('nothinig', required: false)
+assert(not sub_pro.found(), 'subproject found() reports wrong value')
diff --git a/test cases/common/47 pkgconfig-gen/installed_files.txt b/test cases/common/47 pkgconfig-gen/installed_files.txt
index 94de704..9e1a40a 100644
--- a/test cases/common/47 pkgconfig-gen/installed_files.txt
+++ b/test cases/common/47 pkgconfig-gen/installed_files.txt
@@ -2,3 +2,4 @@ usr/include/simple.h
usr/lib/pkgconfig/simple.pc
usr/lib/pkgconfig/libfoo.pc
usr/lib/pkgconfig/libhello.pc
+usr/lib/pkgconfig/libhello_nolib.pc \ No newline at end of file
diff --git a/test cases/common/47 pkgconfig-gen/meson.build b/test cases/common/47 pkgconfig-gen/meson.build
index 09c46c5..c251b9f 100644
--- a/test cases/common/47 pkgconfig-gen/meson.build
+++ b/test cases/common/47 pkgconfig-gen/meson.build
@@ -51,3 +51,10 @@ pkgg.generate(
description : 'A minimalistic pkgconfig file.',
version : libver,
)
+
+pkgg.generate(
+ name : 'libhello_nolib',
+ description : 'A minimalistic pkgconfig file.',
+ version : libver,
+ dataonly: true
+)
diff --git a/test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp b/test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp
new file mode 100644
index 0000000..a5f09be
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+#define SOME_DEFINE " World"
diff --git a/test cases/failing build/4 cmake subproject isolation/main.cpp b/test cases/failing build/4 cmake subproject isolation/main.cpp
new file mode 100644
index 0000000..9507961
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/main.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+#include <cmMod.hpp>
+
+using namespace std;
+
+int main(void) {
+ cmModClass obj("Hello");
+ cout << obj.getStr() << endl;
+ return 0;
+}
diff --git a/test cases/failing build/4 cmake subproject isolation/meson.build b/test cases/failing build/4 cmake subproject isolation/meson.build
new file mode 100644
index 0000000..e606335
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/meson.build
@@ -0,0 +1,17 @@
+project('subproject isolation', ['c', 'cpp'])
+
+if not find_program('cmake', required: false).found()
+ error('MESON_SKIP_TEST CMake is not installed')
+endif
+
+incdir = meson.source_root() / 'incDir'
+
+cm = import('cmake')
+
+# This should generate a warning and the include dir should be skipped.
+sub_pro = cm.subproject('cmMod', cmake_options : [ '-DMESON_INC_DIR=' + incdir ])
+sub_dep = sub_pro.dependency('cmModLib++')
+
+# Since the include dir is skipped, the compilation of this project should fail.
+exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep])
+test('test1', exe1)
diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt
new file mode 100644
index 0000000..852dd09
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(cmMod)
+set (CMAKE_CXX_STANDARD 14)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${MESON_INC_DIR})
+
+add_library(cmModLib++ SHARED cmMod.cpp)
+include(GenerateExportHeader)
+generate_export_header(cmModLib++)
diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp
new file mode 100644
index 0000000..a668203
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp
@@ -0,0 +1,12 @@
+#include "cmMod.hpp"
+#include "fileA.hpp"
+
+using namespace std;
+
+cmModClass::cmModClass(string foo) {
+ str = foo + SOME_DEFINE;
+}
+
+string cmModClass::getStr() const {
+ return str;
+}
diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp
new file mode 100644
index 0000000..0e6dc04
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "cmmodlib++_export.h"
+#include <string>
+
+class CMMODLIB___EXPORT cmModClass {
+private:
+ std::string str;
+
+public:
+ cmModClass(std::string foo);
+
+ std::string getStr() const;
+};