aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci/ciimage/bionic/install.sh1
-rwxr-xr-xci/ciimage/ubuntu-rolling/install.sh1
-rw-r--r--docs/markdown/Dependencies.md17
-rw-r--r--docs/markdown/Wayland-module.md32
-rw-r--r--docs/markdown/howtox.md2
-rw-r--r--docs/markdown/snippets/find_program-version.md5
-rw-r--r--docs/markdown/snippets/jni-system-dep-modules.md10
-rw-r--r--docs/markdown/snippets/merge_file_sanity.md15
-rw-r--r--docs/yaml/objects/external_program.yaml8
-rw-r--r--mesonbuild/backend/backends.py19
-rw-r--r--mesonbuild/backend/ninjabackend.py3
-rw-r--r--mesonbuild/build.py14
-rw-r--r--mesonbuild/cmake/generator.py61
-rw-r--r--mesonbuild/cmake/interpreter.py4
-rw-r--r--mesonbuild/cmake/toolchain.py2
-rw-r--r--mesonbuild/cmake/traceparser.py40
-rw-r--r--mesonbuild/dependencies/cmake.py4
-rw-r--r--mesonbuild/dependencies/dev.py61
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py12
-rw-r--r--mesonbuild/minstall.py10
-rw-r--r--mesonbuild/mintro.py20
-rw-r--r--mesonbuild/modules/i18n.py49
-rw-r--r--mesonbuild/modules/java.py46
-rw-r--r--mesonbuild/modules/unstable_wayland.py32
-rw-r--r--mesonbuild/scripts/gettext.py19
-rw-r--r--mesonbuild/scripts/itstool.py7
-rw-r--r--mesonbuild/scripts/msgfmthelper.py3
-rw-r--r--test cases/cmake/12 generator expressions/subprojects/cmMod/CMakeLists.txt10
-rw-r--r--test cases/cmake/12 generator expressions/subprojects/cmMod/include/cmMod.hpp32
-rw-r--r--test cases/cmake/12 generator expressions/test.json5
-rw-r--r--test cases/common/26 find program/meson.build3
-rw-r--r--test cases/frameworks/6 gettext/data/meson.build1
-rw-r--r--test cases/frameworks/6 gettext/data2/meson.build1
-rw-r--r--test cases/java/9 jni/meson.build2
-rw-r--r--test cases/unit/99 install all targets/meson.build6
-rw-r--r--test cases/wayland/1 client/both.c11
-rw-r--r--test cases/wayland/1 client/client.c (renamed from test cases/wayland/1 client/main.c)4
-rw-r--r--test cases/wayland/1 client/local.c (renamed from test cases/wayland/3 local/main.c)0
-rw-r--r--test cases/wayland/1 client/meson.build38
-rw-r--r--test cases/wayland/1 client/server.c9
-rw-r--r--test cases/wayland/1 client/test.xml (renamed from test cases/wayland/3 local/test.xml)0
-rw-r--r--test cases/wayland/2 server/main.c9
-rw-r--r--test cases/wayland/2 server/meson.build16
-rw-r--r--test cases/wayland/3 local/meson.build11
-rw-r--r--unittests/allplatformstests.py21
45 files changed, 514 insertions, 162 deletions
diff --git a/ci/ciimage/bionic/install.sh b/ci/ciimage/bionic/install.sh
index 74b407f..23e0774 100755
--- a/ci/ciimage/bionic/install.sh
+++ b/ci/ciimage/bionic/install.sh
@@ -27,6 +27,7 @@ pkgs=(
libblocksruntime-dev
libperl-dev libscalapack-mpi-dev libncurses-dev
itstool
+ openjdk-11-jre
)
boost_pkgs=(atomic chrono date-time filesystem log regex serialization system test thread)
diff --git a/ci/ciimage/ubuntu-rolling/install.sh b/ci/ciimage/ubuntu-rolling/install.sh
index aa73cbc..550d311 100755
--- a/ci/ciimage/ubuntu-rolling/install.sh
+++ b/ci/ciimage/ubuntu-rolling/install.sh
@@ -26,6 +26,7 @@ pkgs=(
liblapack-dev libscalapack-mpi-dev
bindgen
itstool
+ openjdk-11-jre
)
sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list"
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md
index a7e34e5..8165955 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -494,23 +494,34 @@ Deprecated name for JNI. `dependency('jdk')` instead of `dependency('jni')`.
*(added 0.62.0)*
+`modules` is an optional list of strings containing any of `jvm` and `awt`.
+
Provides access to compiling with the Java Native Interface (JNI). The lookup
will first check if `JAVA_HOME` is set in the environment, and if not will use
the resolved path of `javac`. Systems will usually link your preferred JDK to
well known paths like `/usr/bin/javac` on Linux for instance. Using the path
from `JAVA_HOME` or the resolved `javac`, this dependency will place the JDK
installation's `include` directory and its platform-dependent subdirectory on
-the compiler's include path.
+the compiler's include path. If `modules` is non-empty, then the proper linker
+arguments will also be added.
```meson
-dep = dependency('jni', version: '>= 1.8.0')
+dep = dependency('jni', version: '>= 1.8.0', modules: ['jvm'])
```
**Note**: Due to usage of a resolved path, upgrading the JDK may cause the
-various headers to not be found. In that case, please reconfigure the build
+various paths to not be found. In that case, please reconfigure the build
directory. One workaround is to explicitly set `JAVA_HOME` instead of relying on
the fallback `javac` resolved path behavior.
+**Note**: Include paths might be broken on platforms other than `linux`,
+`windows`, `darwin`, and `sunos`. Please submit a PR or open an issue in this
+case.
+
+**Note**: Use of the `modules` argument on a JDK `<= 1.8` may be broken if your
+system is anything other than `x86_64`. Please submit a PR or open an issue in
+this case.
+
## libgcrypt
*(added 0.49.0)*
diff --git a/docs/markdown/Wayland-module.md b/docs/markdown/Wayland-module.md
index d30627c..345c4e3 100644
--- a/docs/markdown/Wayland-module.md
+++ b/docs/markdown/Wayland-module.md
@@ -26,7 +26,6 @@ executable('hw', 'main.c', xdg_shell, dependencies : wl_dep)
## Methods
### find_protocol
-
```meson
xml = wl_mod.find_protocol(
'xdg-decoration',
@@ -35,28 +34,37 @@ xml = wl_mod.find_protocol(
)
```
This function requires one positional argument: the protocol base name.
+
+It takes the following keyword arguments:
- `state` Optional arg that specifies the current state of the protocol.
-Either stable, staging, or unstable.
-The default is stable.
-- `version` The backwards incompatible version number.
-Required for staging or unstable. An error is raised for stable.
+ Either `'stable'`, `'staging'`, or `'unstable'`. The default is `'stable'`.
+- `version` The backwards incompatible version number as integer.
+ Required for staging and unstable, but not allowed for stable.
+
+**Returns**: a [[@file]] that can be passed to [scan_xml](#scan_xml)
### scan_xml
```meson
generated = wl_mod.scan_xml(
'my-protocol.xml',
- side : 'client',
- scope : 'private',
+ client : true,
+ server : true,
+ public : false,
)
```
This function accepts one or more arguments of either string or file type.
-- `side` Optional arg that specifies if client or server side code is generated.
-The default is client side.
-- `scope` Optional arg that specifies the scope of the generated code.
-Either public or private.
-The default is private.
+It takes the following keyword arguments:
+- `public` Optional arg that specifies the scope of the generated code.
+ The default is false.
+- `client` Optional arg that specifies if client side header file is
+ generated. The default is true.
+- `server` Optional arg that specifies if server side header file is
+ generated. The default is false.
+**Returns**: a list of [[@custom_tgt]] in the order source, client side header,
+server side header. Generated header files have the name
+`<name>-<client|server>-protocol.h`.
## Links
- [Official Wayland Documentation](https://wayland.freedesktop.org/docs/html/)
diff --git a/docs/markdown/howtox.md b/docs/markdown/howtox.md
index 91098aa..9945a6c 100644
--- a/docs/markdown/howtox.md
+++ b/docs/markdown/howtox.md
@@ -141,7 +141,7 @@ configure_file(...)
## Generate configuration data from files
-`The [fs module](#Fs-modules) offers the `read` function` which enables adding
+The [fs module](#Fs-modules) offers the `read` function which enables adding
the contents of arbitrary files to configuration data (among other uses):
```meson
diff --git a/docs/markdown/snippets/find_program-version.md b/docs/markdown/snippets/find_program-version.md
new file mode 100644
index 0000000..fe3a9a6
--- /dev/null
+++ b/docs/markdown/snippets/find_program-version.md
@@ -0,0 +1,5 @@
+## found programs now have a version method
+
+The return value of [[find_program]] can now check the exact version of the
+found program, independent of the minimum version requirement. This can be used
+e.g. to perform different actions depending on the exact version detected.
diff --git a/docs/markdown/snippets/jni-system-dep-modules.md b/docs/markdown/snippets/jni-system-dep-modules.md
new file mode 100644
index 0000000..1f2c567
--- /dev/null
+++ b/docs/markdown/snippets/jni-system-dep-modules.md
@@ -0,0 +1,10 @@
+## JNI System Dependency Modules
+
+The JNI system dependency now supports a `modules` keyword argument which is a
+list containing any of the following: `jvm`, `awt`.
+
+```meson
+jni_dep = dependency('jni', version: '>= 1.8.0', modules: ['jvm', 'awt'])
+```
+
+This will add appropriate linker arguments to your target.
diff --git a/docs/markdown/snippets/merge_file_sanity.md b/docs/markdown/snippets/merge_file_sanity.md
new file mode 100644
index 0000000..ff59c51
--- /dev/null
+++ b/docs/markdown/snippets/merge_file_sanity.md
@@ -0,0 +1,15 @@
+## i18n.merge_file no longer arbitrarily leaves your project half-built
+
+The i18n module partially accounts for builds with NLS disabled, by disabling
+gettext compiled translation catalogs if it cannot build them. Due to
+implementation details, this also disabled important data files created via
+merge_file, leading to important desktop files etc. not being installed.
+
+This overreaction has been fixed. It is no longer possible to have NLS-disabled
+builds which break the project by not installing important files which have
+nothing to do with NLS (other than including some).
+
+If you were depending on not having the Gettext tools installed and
+successfully mis-building your project, you may need to make your project
+actually work with NLS disabled, for example by providing some version of your
+files which is still installed even when merge_file cannot be run.
diff --git a/docs/yaml/objects/external_program.yaml b/docs/yaml/objects/external_program.yaml
index 02bf48f..f406477 100644
--- a/docs/yaml/objects/external_program.yaml
+++ b/docs/yaml/objects/external_program.yaml
@@ -24,6 +24,14 @@ methods:
run_command(find_program('foo'), 'arg1', 'arg2')
```
+- name: version
+ returns: str
+ since: 0.62.0
+ description: |
+ The version number as a string, for example `1.2.8`.
+
+ `unknown` if the program cannot determine the version via a `--version` argument.
+
- name: full_path
returns: str
since: 0.55.0
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index dae9c47..b98eb08 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -135,7 +135,6 @@ class TargetInstallData:
fname: str
outdir: str
outdir_name: InitVar[str]
- aliases: T.Dict[str, str]
strip: bool
install_name_mappings: T.Mapping[str, str]
rpath_dirs_to_remove: T.Set[bytes]
@@ -173,6 +172,7 @@ class InstallSymlinkData:
install_path: str
subproject: str
tag: T.Optional[str] = None
+ allow_missing: bool = False
# cannot use dataclass here because "exclude" is out of order
class SubdirInstallData(InstallDataBase):
@@ -1581,12 +1581,17 @@ class Backend:
tag = t.install_tag[0] or ('devel' if isinstance(t, build.StaticLibrary) else 'runtime')
mappings = t.get_link_deps_mapping(d.prefix, self.environment)
i = TargetInstallData(self.get_target_filename(t), outdirs[0],
- install_dir_name, t.get_aliases(),
+ install_dir_name,
should_strip, mappings, t.rpath_dirs_to_remove,
t.install_rpath, install_mode, t.subproject,
tag=tag)
d.targets.append(i)
+ for alias, to, tag in t.get_aliases():
+ alias = os.path.join(outdirs[0], alias)
+ s = InstallSymlinkData(to, alias, outdirs[0], t.subproject, tag, allow_missing=True)
+ d.symlinks.append(s)
+
if isinstance(t, (build.SharedLibrary, build.SharedModule, build.Executable)):
# On toolchains/platforms that use an import library for
# linking (separate from the shared library with all the
@@ -1602,7 +1607,7 @@ class Backend:
# Install the import library; may not exist for shared modules
i = TargetInstallData(self.get_target_filename_for_linking(t),
implib_install_dir, install_dir_name,
- {}, False, {}, set(), '', install_mode,
+ False, {}, set(), '', install_mode,
t.subproject, optional=isinstance(t, build.SharedModule),
tag='devel')
d.targets.append(i)
@@ -1611,7 +1616,7 @@ class Backend:
debug_file = os.path.join(self.get_target_dir(t), t.get_debug_filename())
i = TargetInstallData(debug_file, outdirs[0],
install_dir_name,
- {}, False, {}, set(), '',
+ False, {}, set(), '',
install_mode, t.subproject,
optional=True, tag='devel')
d.targets.append(i)
@@ -1622,7 +1627,7 @@ class Backend:
if outdir is False:
continue
f = os.path.join(self.get_target_dir(t), output)
- i = TargetInstallData(f, outdir, install_dir_name, {}, False, {}, set(), None,
+ i = TargetInstallData(f, outdir, install_dir_name, False, {}, set(), None,
install_mode, t.subproject,
tag=tag)
d.targets.append(i)
@@ -1639,7 +1644,7 @@ class Backend:
f = os.path.join(self.get_target_dir(t), output)
if not install_dir_name:
dir_name = os.path.join('{prefix}', outdirs[0])
- i = TargetInstallData(f, outdirs[0], dir_name, {},
+ i = TargetInstallData(f, outdirs[0], dir_name,
False, {}, set(), None, install_mode,
t.subproject, optional=not t.build_by_default,
tag=tag)
@@ -1653,7 +1658,7 @@ class Backend:
if not install_dir_name:
dir_name = os.path.join('{prefix}', outdir)
i = TargetInstallData(f, outdir, dir_name,
- {}, False, {}, set(), None, install_mode,
+ False, {}, set(), None, install_mode,
t.subproject, optional=not t.build_by_default,
tag=tag)
d.targets.append(i)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 560fe53..a66111b 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -3092,8 +3092,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
return self.get_target_filename(t)
def generate_shlib_aliases(self, target, outdir):
- aliases = target.get_aliases()
- for alias, to in aliases.items():
+ for alias, to, tag in target.get_aliases():
aliasfile = os.path.join(self.environment.get_build_dir(), outdir, alias)
try:
os.remove(aliasfile)
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index bd6661b..6916bcb 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1471,8 +1471,8 @@ You probably should put it in link_with instead.''')
else:
self.extra_args[language] = args
- def get_aliases(self) -> T.Dict[str, str]:
- return {}
+ def get_aliases(self) -> T.List[T.Tuple[str, str, str]]:
+ return []
def get_langs_used_by_deps(self) -> T.List[str]:
'''
@@ -2240,7 +2240,7 @@ class SharedLibrary(BuildTarget):
def get_all_link_deps(self):
return [self] + self.get_transitive_link_deps()
- def get_aliases(self) -> T.Dict[str, str]:
+ def get_aliases(self) -> T.List[T.Tuple[str, str, str]]:
"""
If the versioned library name is libfoo.so.0.100.0, aliases are:
* libfoo.so.0 (soversion) -> libfoo.so.0.100.0
@@ -2248,7 +2248,7 @@ class SharedLibrary(BuildTarget):
Same for dylib:
* libfoo.dylib (unversioned; for linking) -> libfoo.0.dylib
"""
- aliases: T.Dict[str, str] = {}
+ aliases: T.List[T.Tuple[str, str, str]] = []
# Aliases are only useful with .so and .dylib libraries. Also if
# there's no self.soversion (no versioning), we don't need aliases.
if self.suffix not in ('so', 'dylib') or not self.soversion:
@@ -2260,14 +2260,16 @@ class SharedLibrary(BuildTarget):
if self.suffix == 'so' and self.ltversion and self.ltversion != self.soversion:
alias_tpl = self.filename_tpl.replace('ltversion', 'soversion')
ltversion_filename = alias_tpl.format(self)
- aliases[ltversion_filename] = self.filename
+ tag = self.install_tag[0] or 'runtime'
+ aliases.append((ltversion_filename, self.filename, tag))
# libfoo.so.0/libfoo.0.dylib is the actual library
else:
ltversion_filename = self.filename
# Unversioned alias:
# libfoo.so -> libfoo.so.0
# libfoo.dylib -> libfoo.0.dylib
- aliases[self.basic_filename_tpl.format(self)] = ltversion_filename
+ tag = self.install_tag[0] or 'devel'
+ aliases.append((self.basic_filename_tpl.format(self), ltversion_filename, tag))
return aliases
def type_suffix(self):
diff --git a/mesonbuild/cmake/generator.py b/mesonbuild/cmake/generator.py
index 848fdf9..b68778d 100644
--- a/mesonbuild/cmake/generator.py
+++ b/mesonbuild/cmake/generator.py
@@ -13,9 +13,18 @@
# limitations under the License.
from .. import mesonlib
+from .common import cmake_is_debug
import typing as T
-def parse_generator_expressions(raw: str) -> str:
+if T.TYPE_CHECKING:
+ from .traceparser import CMakeTraceParser, CMakeTarget
+
+def parse_generator_expressions(
+ raw: str,
+ trace: 'CMakeTraceParser',
+ *,
+ context_tgt: T.Optional['CMakeTarget'] = None,
+ ) -> str:
'''Parse CMake generator expressions
Most generator expressions are simply ignored for
@@ -44,6 +53,48 @@ def parse_generator_expressions(raw: str) -> str:
else:
return '1' if mesonlib.version_compare(arg[:col_pos], '{}{}'.format(op, arg[col_pos + 1:])) else '0'
+ def target_property(arg: str) -> str:
+ # We can't really support this since we don't have any context
+ if ',' not in arg:
+ if context_tgt is None:
+ return ''
+ return ';'.join(context_tgt.properties.get(arg, []))
+
+ args = arg.split(',')
+ props = trace.targets[args[0]].properties.get(args[1], []) if args[0] in trace.targets else []
+ return ';'.join(props)
+
+ def target_file(arg: str) -> str:
+ if arg not in trace.targets:
+ return ''
+ tgt = trace.targets[arg]
+
+ cfgs = []
+ cfg = ''
+
+ if 'IMPORTED_CONFIGURATIONS' in tgt.properties:
+ cfgs = [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x]
+ cfg = cfgs[0]
+
+ if cmake_is_debug(trace.env):
+ if 'DEBUG' in cfgs:
+ cfg = 'DEBUG'
+ elif 'RELEASE' in cfgs:
+ cfg = 'RELEASE'
+ else:
+ if 'RELEASE' in cfgs:
+ cfg = 'RELEASE'
+
+ if f'IMPORTED_IMPLIB_{cfg}' in tgt.properties:
+ return ';'.join([x for x in tgt.properties[f'IMPORTED_IMPLIB_{cfg}'] if x])
+ elif 'IMPORTED_IMPLIB' in tgt.properties:
+ return ';'.join([x for x in tgt.properties['IMPORTED_IMPLIB'] if x])
+ elif f'IMPORTED_LOCATION_{cfg}' in tgt.properties:
+ return ';'.join([x for x in tgt.properties[f'IMPORTED_LOCATION_{cfg}'] if x])
+ elif 'IMPORTED_LOCATION' in tgt.properties:
+ return ';'.join([x for x in tgt.properties['IMPORTED_LOCATION'] if x])
+ return ''
+
supported = {
# Boolean functions
'BOOL': lambda x: '0' if x.upper() in ['0', 'FALSE', 'OFF', 'N', 'NO', 'IGNORE', 'NOTFOUND'] or x.endswith('-NOTFOUND') else '1',
@@ -51,6 +102,8 @@ def parse_generator_expressions(raw: str) -> str:
'OR': lambda x: '1' if any([y == '1' for y in x.split(',')]) else '0',
'NOT': lambda x: '0' if x == '1' else '1',
+ 'IF': lambda x: x.split(',')[1] if x.split(',')[0] == '1' else x.split(',')[2],
+
'0': lambda x: '',
'1': lambda x: x,
@@ -78,6 +131,12 @@ def parse_generator_expressions(raw: str) -> str:
'ANGLE-R': lambda x: '>',
'COMMA': lambda x: ',',
'SEMICOLON': lambda x: ';',
+
+ # Target related expressions
+ 'TARGET_EXISTS': lambda x: '1' if x in trace.targets else '0',
+ 'TARGET_NAME_IF_EXISTS': lambda x: x if x in trace.targets else '',
+ 'TARGET_PROPERTY': target_property,
+ 'TARGET_FILE': target_file,
} # type: T.Dict[str, T.Callable[[str], str]]
# Recursively evaluate generator expressions
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 44b7e57..a619d1a 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -784,7 +784,7 @@ class CMakeInterpreter:
self.languages = [] # type: T.List[str]
self.targets = [] # type: T.List[ConverterTarget]
self.custom_targets = [] # type: T.List[ConverterCustomTarget]
- self.trace = CMakeTraceParser('', Path('.')) # Will be replaced in analyse
+ self.trace = CMakeTraceParser('', Path('.'), self.env) # Will be replaced in analyse
self.output_target_map = OutputTargetMap(self.build_dir)
# Generated meson data
@@ -805,7 +805,7 @@ class CMakeInterpreter:
cmake_exe = CMakeExecutor(self.env, '>=3.14', MachineChoice.BUILD)
if not cmake_exe.found():
raise CMakeException('Unable to find CMake')
- self.trace = CMakeTraceParser(cmake_exe.version(), self.build_dir, permissive=True)
+ self.trace = CMakeTraceParser(cmake_exe.version(), self.build_dir, self.env, permissive=True)
preload_file = DataFile('cmake/data/preload.cmake').write_to_private(self.env)
toolchain = CMakeToolchain(cmake_exe, self.env, self.for_machine, CMakeExecScope.SUBPROJECT, self.build_dir, preload_file)
diff --git a/mesonbuild/cmake/toolchain.py b/mesonbuild/cmake/toolchain.py
index 316f57c..e30f642 100644
--- a/mesonbuild/cmake/toolchain.py
+++ b/mesonbuild/cmake/toolchain.py
@@ -232,7 +232,7 @@ class CMakeToolchain:
temp_toolchain_file.write_text(CMakeToolchain._print_vars(self.variables), encoding='utf-8')
# Configure
- trace = CMakeTraceParser(self.cmakebin.version(), build_dir)
+ trace = CMakeTraceParser(self.cmakebin.version(), build_dir, self.env)
self.cmakebin.set_exec_mode(print_cmout=False, always_capture_stderr=trace.requires_stderr())
cmake_args = []
cmake_args += trace.trace_args()
diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py
index 7909e13..7336d15 100644
--- a/mesonbuild/cmake/traceparser.py
+++ b/mesonbuild/cmake/traceparser.py
@@ -27,6 +27,9 @@ import re
import json
import textwrap
+if T.TYPE_CHECKING:
+ from ..environment import Environment
+
class CMakeTraceLine:
def __init__(self, file_str: str, line: int, func: str, args: T.List[str]) -> None:
self.file = CMakeTraceLine._to_path(file_str)
@@ -90,7 +93,7 @@ class CMakeGeneratorTarget(CMakeTarget):
self.working_dir = None # type: T.Optional[Path]
class CMakeTraceParser:
- def __init__(self, cmake_version: str, build_dir: Path, permissive: bool = True) -> None:
+ def __init__(self, cmake_version: str, build_dir: Path, env: 'Environment', permissive: bool = True) -> None:
self.vars: T.Dict[str, T.List[str]] = {}
self.vars_by_file: T.Dict[Path, T.Dict[str, T.List[str]]] = {}
self.targets: T.Dict[str, CMakeTarget] = {}
@@ -101,6 +104,7 @@ class CMakeTraceParser:
# T.List of targes that were added with add_custom_command to generate files
self.custom_targets = [] # type: T.List[CMakeGeneratorTarget]
+ self.env = env
self.permissive = permissive # type: bool
self.cmake_version = cmake_version # type: str
self.trace_file = 'cmake_trace.txt'
@@ -194,6 +198,38 @@ class CMakeTraceParser:
if fn:
fn(l)
+ # Evaluate generator expressions
+ strlist_gen: T.Callable[[T.List[str]], T.List[str]] = lambda strlist: [parse_generator_expressions(x, self) for x in strlist]
+ pathlist_gen: T.Callable[[T.List[Path]], T.List[Path]] = lambda plist: [Path(parse_generator_expressions(str(x), self)) for x in plist]
+
+ self.vars = {k: strlist_gen(v) for k, v in self.vars.items()}
+ self.vars_by_file = {
+ p: {k: strlist_gen(v) for k, v in d.items()}
+ for p, d in self.vars_by_file.items()
+ }
+ self.explicit_headers = set(Path(parse_generator_expressions(str(x), self)) for x in self.explicit_headers)
+ self.cache = {
+ k: CMakeCacheEntry(
+ strlist_gen(v.value),
+ v.type
+ )
+ for k, v in self.cache.items()
+ }
+
+ for tgt in self.targets.values():
+ tgtlist_gen: T.Callable[[T.List[str], CMakeTarget], T.List[str]] = lambda strlist, t: [parse_generator_expressions(x, self, context_tgt=t) for x in strlist]
+ tgt.name = parse_generator_expressions(tgt.name, self, context_tgt=tgt)
+ tgt.type = parse_generator_expressions(tgt.type, self, context_tgt=tgt)
+ tgt.properties = {
+ k: tgtlist_gen(v, tgt) for k, v in tgt.properties.items()
+ } if tgt.properties is not None else None
+ tgt.depends = tgtlist_gen(tgt.depends, tgt)
+
+ for ctgt in self.custom_targets:
+ ctgt.outputs = pathlist_gen(ctgt.outputs)
+ ctgt.command = [strlist_gen(x) for x in ctgt.command]
+ ctgt.working_dir = Path(parse_generator_expressions(str(ctgt.working_dir), self)) if ctgt.working_dir is not None else None
+
# Postprocess
for tgt in self.targets.values():
tgt.strip_properties()
@@ -688,7 +724,6 @@ class CMakeTraceParser:
line = mo_file_line.group(3)
func = mo_file_line.group(4)
args = mo_file_line.group(5)
- args = parse_generator_expressions(args)
argl = args.split(' ')
argl = list(map(lambda x: x.strip(), argl))
@@ -706,7 +741,6 @@ class CMakeTraceParser:
args = data['args']
for j in args:
assert isinstance(j, str)
- args = [parse_generator_expressions(x) for x in args]
yield CMakeTraceLine(data['file'], data['line'], data['cmd'], args)
def _flatten_args(self, args: T.List[str]) -> T.List[str]:
diff --git a/mesonbuild/dependencies/cmake.py b/mesonbuild/dependencies/cmake.py
index 09f7f14..cff0e58 100644
--- a/mesonbuild/dependencies/cmake.py
+++ b/mesonbuild/dependencies/cmake.py
@@ -127,7 +127,7 @@ class CMakeDependency(ExternalDependency):
return
# Setup the trace parser
- self.traceparser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir())
+ self.traceparser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir(), self.env)
cm_args = stringlistify(extract_as_list(kwargs, 'cmake_args'))
cm_args = check_cmake_args(cm_args)
@@ -166,7 +166,7 @@ class CMakeDependency(ExternalDependency):
gen_list += [CMakeDependency.class_working_generator]
gen_list += CMakeDependency.class_cmake_generators
- temp_parser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir())
+ temp_parser = CMakeTraceParser(self.cmakebin.version(), self._get_build_dir(), self.env)
toolchain = CMakeToolchain(self.cmakebin, self.env, self.for_machine, CMakeExecScope.DEPENDENCY, self._get_build_dir())
toolchain.write()
diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py
index 247dbc7..793b38a 100644
--- a/mesonbuild/dependencies/dev.py
+++ b/mesonbuild/dependencies/dev.py
@@ -15,6 +15,8 @@
# This file contains the detection logic for external dependencies useful for
# development purposes, such as testing, debugging, etc..
+from __future__ import annotations
+
import glob
import os
import re
@@ -38,6 +40,13 @@ from .pkgconfig import PkgConfigDependency
if T.TYPE_CHECKING:
from ..envconfig import MachineInfo
from .. environment import Environment
+ from typing_extensions import TypedDict
+
+ class JNISystemDependencyKW(TypedDict):
+ modules: T.List[str]
+ # FIXME: When dependency() moves to typed Kwargs, this should inherit
+ # from its TypedDict type.
+ version: T.Optional[str]
def get_shared_library_suffix(environment: 'Environment', for_machine: MachineChoice) -> str:
@@ -500,8 +509,8 @@ class ZlibSystemDependency(SystemDependency):
class JNISystemDependency(SystemDependency):
- def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
- super().__init__('jni', environment, kwargs)
+ def __init__(self, environment: 'Environment', kwargs: JNISystemDependencyKW):
+ super().__init__('jni', environment, T.cast(T.Dict[str, T.Any], kwargs))
self.feature_since = ('0.62.0', '')
@@ -512,6 +521,14 @@ class JNISystemDependency(SystemDependency):
self.javac = environment.coredata.compilers[self.for_machine]['java']
self.version = self.javac.version
+ modules: T.List[str] = mesonlib.listify(kwargs.get('modules', []))
+ for module in modules:
+ if module not in {'jvm', 'awt'}:
+ log = mlog.error if self.required else mlog.debug
+ log(f'Unknown JNI module ({module})')
+ self.is_found = False
+ return
+
if 'version' in kwargs and not version_compare(self.version, kwargs['version']):
mlog.error(f'Incorrect JDK version found ({self.version}), wanted {kwargs["version"]}')
self.is_found = False
@@ -530,6 +547,44 @@ class JNISystemDependency(SystemDependency):
java_home_include = self.java_home / 'include'
self.compile_args.append(f'-I{java_home_include}')
self.compile_args.append(f'-I{java_home_include / platform_include_dir}')
+
+ if modules:
+ if m.is_windows():
+ java_home_lib = self.java_home / 'lib'
+ java_home_lib_server = java_home_lib
+ else:
+ if version_compare(self.version, '<= 1.8.0'):
+ # The JDK and Meson have a disagreement here, so translate it
+ # over. In the event more translation needs to be done, add to
+ # following dict.
+ def cpu_translate(cpu: str) -> str:
+ java_cpus = {
+ 'x86_64': 'amd64',
+ }
+
+ return java_cpus.get(cpu, cpu)
+
+ java_home_lib = self.java_home / 'jre' / 'lib' / cpu_translate(m.cpu_family)
+ java_home_lib_server = java_home_lib / "server"
+ else:
+ java_home_lib = self.java_home / 'lib'
+ java_home_lib_server = java_home_lib / "server"
+
+ if 'jvm' in modules:
+ jvm = self.clib_compiler.find_library('jvm', environment, extra_dirs=[str(java_home_lib_server)])
+ if jvm is None:
+ mlog.debug('jvm library not found.')
+ self.is_found = False
+ else:
+ self.link_args.extend(jvm)
+ if 'awt' in modules:
+ jawt = self.clib_compiler.find_library('jawt', environment, extra_dirs=[str(java_home_lib)])
+ if jawt is None:
+ mlog.debug('jawt library not found.')
+ self.is_found = False
+ else:
+ self.link_args.extend(jawt)
+
self.is_found = True
@staticmethod
@@ -553,7 +608,7 @@ class JNISystemDependency(SystemDependency):
class JDKSystemDependency(JNISystemDependency):
- def __init__(self, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+ def __init__(self, environment: 'Environment', kwargs: JNISystemDependencyKW):
super().__init__(environment, kwargs)
self.feature_since = ('0.59.0', '')
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index a3c0bef..ef899e2 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -518,6 +518,7 @@ class ExternalProgramHolder(ObjectHolder[ExternalProgram]):
super().__init__(ep, interpreter)
self.methods.update({'found': self.found_method,
'path': self.path_method,
+ 'version': self.version_method,
'full_path': self.full_path_method})
@noPosargs
@@ -545,6 +546,17 @@ class ExternalProgramHolder(ObjectHolder[ExternalProgram]):
assert path is not None
return path
+ @noPosargs
+ @noKwargs
+ @FeatureNew('ExternalProgram.version', '0.62.0')
+ def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+ if not self.found():
+ raise InterpreterException('Unable to get the version of a not-found external program')
+ try:
+ return self.held_object.get_version(self.interpreter)
+ except MesonException:
+ return 'unknown'
+
def found(self) -> bool:
return self.held_object.found()
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 80b0239..b51d4f0 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -428,11 +428,11 @@ class Installer:
append_to_log(self.lf, to_file)
return True
- def do_symlink(self, target: str, link: str, full_dst_dir: str) -> bool:
+ def do_symlink(self, target: str, link: str, full_dst_dir: str, allow_missing: bool) -> bool:
abs_target = target
if not os.path.isabs(target):
abs_target = os.path.join(full_dst_dir, target)
- if not os.path.exists(abs_target):
+ if not os.path.exists(abs_target) and not allow_missing:
raise MesonException(f'Tried to install symlink to missing file {abs_target}')
if os.path.exists(link):
if not os.path.islink(link):
@@ -592,7 +592,7 @@ class Installer:
full_dst_dir = get_destdir_path(destdir, fullprefix, s.install_path)
full_link_name = get_destdir_path(destdir, fullprefix, s.name)
dm.makedirs(full_dst_dir, exist_ok=True)
- if self.do_symlink(s.target, full_link_name, full_dst_dir):
+ if self.do_symlink(s.target, full_link_name, full_dst_dir, s.allow_missing):
self.did_install_something = True
def install_man(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None:
@@ -676,7 +676,6 @@ class Installer:
outdir = get_destdir_path(destdir, fullprefix, t.outdir)
outname = os.path.join(outdir, os.path.basename(fname))
final_path = os.path.join(d.prefix, t.outdir, os.path.basename(fname))
- aliases = t.aliases
should_strip = t.strip
install_rpath = t.install_rpath
install_name_mappings = t.install_name_mappings
@@ -711,9 +710,6 @@ class Installer:
self.do_copydir(d, fname, outname, None, install_mode, dm)
else:
raise RuntimeError(f'Unknown file type for {fname!r}')
- for alias, target in aliases.items():
- symlinkfilename = os.path.join(outdir, alias)
- self.do_symlink(target, symlinkfilename, outdir)
if file_copied:
self.did_install_something = True
try:
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index 2ec7274..7b4f8aa 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -107,9 +107,6 @@ def list_installed(installdata: backends.InstallData) -> T.Dict[str, str]:
for t in installdata.targets:
res[os.path.join(installdata.build_dir, t.fname)] = \
os.path.join(installdata.prefix, t.outdir, os.path.basename(t.fname))
- for alias in t.aliases.keys():
- res[os.path.join(installdata.build_dir, alias)] = \
- os.path.join(installdata.prefix, t.outdir, os.path.basename(alias))
for i in installdata.data:
res[i.path] = os.path.join(installdata.prefix, i.install_path)
for i in installdata.headers:
@@ -118,6 +115,9 @@ def list_installed(installdata: backends.InstallData) -> T.Dict[str, str]:
res[i.path] = os.path.join(installdata.prefix, i.install_path)
for i in installdata.install_subdirs:
res[i.path] = os.path.join(installdata.prefix, i.install_path)
+ for s in installdata.symlinks:
+ basename = os.path.basename(s.name)
+ res[basename] = os.path.join(installdata.prefix, s.install_path, basename)
return res
def list_install_plan(installdata: backends.InstallData) -> T.Dict[str, T.Dict[str, T.Dict[str, T.Optional[str]]]]:
@@ -216,9 +216,17 @@ def list_targets(builddata: build.Build, installdata: backends.InstallData, back
# Fast lookup table for installation files
install_lookuptable = {}
for i in installdata.targets:
- out = [os.path.join(installdata.prefix, i.outdir, os.path.basename(i.fname))]
- out += [os.path.join(installdata.prefix, i.outdir, os.path.basename(x)) for x in i.aliases]
- install_lookuptable[os.path.basename(i.fname)] = [str(PurePath(x)) for x in out]
+ basename = os.path.basename(i.fname)
+ install_lookuptable[basename] = [str(PurePath(installdata.prefix, i.outdir, basename))]
+ for s in installdata.symlinks:
+ # Symlink's target must already be in the table. They share the same list
+ # to support symlinks to symlinks recursively, such as .so -> .so.0 -> .so.1.2.3
+ basename = os.path.basename(s.name)
+ try:
+ install_lookuptable[basename] = install_lookuptable[os.path.basename(s.target)]
+ install_lookuptable[basename].append(str(PurePath(installdata.prefix, s.install_path, basename)))
+ except KeyError:
+ pass
for (idname, target) in builddata.get_targets().items():
if not isinstance(target, build.Target):
diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py
index 98070d7..09703bb 100644
--- a/mesonbuild/modules/i18n.py
+++ b/mesonbuild/modules/i18n.py
@@ -11,9 +11,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import annotations
from os import path
-import shutil
import typing as T
from . import ExtensionModule, ModuleReturnValue
@@ -32,6 +32,7 @@ if T.TYPE_CHECKING:
from ..build import Target
from ..interpreter import Interpreter
from ..interpreterbase import TYPE_var
+ from ..mparser import BaseNode
from ..programs import ExternalProgram
class MergeFile(TypedDict):
@@ -131,14 +132,17 @@ class I18nModule(ExtensionModule):
'gettext': self.gettext,
'itstool_join': self.itstool_join,
})
+ self.tools: T.Dict[str, T.Optional[ExternalProgram]] = {
+ 'itstool': None,
+ 'msgfmt': None,
+ 'msginit': None,
+ 'msgmerge': None,
+ 'xgettext': None,
+ }
@staticmethod
- def nogettext_warning() -> None:
- mlog.warning('Gettext not found, all translation targets will be ignored.', once=True)
-
- @staticmethod
- def noitstool_error() -> T.NoReturn:
- raise mesonlib.MesonException('Did not find itstool. Please install it to continue.')
+ def nogettext_warning(location: BaseNode) -> None:
+ mlog.warning('Gettext not found, all translation targets will be ignored.', once=True, location=location)
@staticmethod
def _get_data_dirs(state: 'ModuleState', dirs: T.Iterable[str]) -> T.List[str]:
@@ -162,9 +166,8 @@ class I18nModule(ExtensionModule):
KwargInfo('type', str, default='xml', validator=in_set_validator({'xml', 'desktop'})),
)
def merge_file(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'MergeFile') -> ModuleReturnValue:
- if not shutil.which('xgettext'):
- self.nogettext_warning()
- return ModuleReturnValue(None, [])
+ if self.tools['msgfmt'] is None:
+ self.tools['msgfmt'] = state.find_program('msgfmt', for_machine=mesonlib.MachineChoice.BUILD)
podir = path.join(state.build_to_src, state.subdir, kwargs['po_dir'])
ddirs = self._get_data_dirs(state, kwargs['data_dirs'])
@@ -175,11 +178,11 @@ class I18nModule(ExtensionModule):
command.extend(state.environment.get_build_command())
command.extend([
'--internal', 'msgfmthelper',
- '@INPUT@', '@OUTPUT@', kwargs['type'], podir
+ '--msgfmt=' + self.tools['msgfmt'].get_path(),
])
if datadirs:
command.append(datadirs)
-
+ command.extend(['@INPUT@', '@OUTPUT@', kwargs['type'], podir])
if kwargs['args']:
command.append('--')
command.extend(kwargs['args'])
@@ -219,9 +222,13 @@ class I18nModule(ExtensionModule):
),
)
def gettext(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gettext') -> ModuleReturnValue:
- if not shutil.which('xgettext'):
- self.nogettext_warning()
- return ModuleReturnValue(None, [])
+ for tool in ['msgfmt', 'msginit', 'msgmerge', 'xgettext']:
+ if self.tools[tool] is None:
+ self.tools[tool] = state.find_program(tool, required=False, for_machine=mesonlib.MachineChoice.BUILD)
+ # still not found?
+ if not self.tools[tool].found():
+ self.nogettext_warning(state.current_node)
+ return ModuleReturnValue(None, [])
packagename = args[0]
pkg_arg = f'--pkgname={packagename}'
@@ -247,6 +254,7 @@ class I18nModule(ExtensionModule):
potargs.append(datadirs)
if extra_arg:
potargs.append(extra_arg)
+ potargs.append('--xgettext=' + self.tools['xgettext'].get_path())
pottarget = build.RunTarget(packagename + '-pot', potargs, [], state.subdir, state.subproject)
targets.append(pottarget)
@@ -262,7 +270,7 @@ class I18nModule(ExtensionModule):
f'{packagename}-{l}.mo',
path.join(state.subdir, l, 'LC_MESSAGES'),
state.subproject,
- ['msgfmt', '@INPUT@', '-o', '@OUTPUT@'],
+ [self.tools['msgfmt'], '@INPUT@', '-o', '@OUTPUT@'],
[po_file],
[f'{packagename}.mo'],
install=install,
@@ -286,6 +294,8 @@ class I18nModule(ExtensionModule):
updatepoargs.append(datadirs)
if extra_arg:
updatepoargs.append(extra_arg)
+ for tool in ['msginit', 'msgmerge']:
+ updatepoargs.append(f'--{tool}=' + self.tools[tool].get_path())
updatepotarget = build.RunTarget(packagename + '-update-po', updatepoargs, [], state.subdir, state.subproject)
targets.append(updatepotarget)
@@ -306,8 +316,8 @@ class I18nModule(ExtensionModule):
KwargInfo('mo_targets', ContainerTypeInfo(list, build.CustomTarget), required=True),
)
def itstool_join(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'ItsJoinFile') -> ModuleReturnValue:
- if not shutil.which('itstool'):
- self.noitstool_error()
+ if self.tools['itstool'] is None:
+ self.tools['itstool'] = state.find_program('itstool', for_machine=mesonlib.MachineChoice.BUILD)
mo_targets = kwargs['mo_targets']
its_files = kwargs.get('its_files', [])
@@ -321,7 +331,8 @@ class I18nModule(ExtensionModule):
command.extend([
'--internal', 'itstool', 'join',
'-i', '@INPUT@',
- '-o', '@OUTPUT@'
+ '-o', '@OUTPUT@',
+ '--itstool=' + self.tools['itstool'].get_path(),
])
if its_files:
for fname in its_files:
diff --git a/mesonbuild/modules/java.py b/mesonbuild/modules/java.py
index dc660a7..6884a22 100644
--- a/mesonbuild/modules/java.py
+++ b/mesonbuild/modules/java.py
@@ -17,66 +17,70 @@ import pathlib
import typing as T
from mesonbuild import mesonlib
from mesonbuild.build import CustomTarget
-from mesonbuild.compilers import detect_compiler_for
+from mesonbuild.compilers import detect_compiler_for, Compiler
+from mesonbuild.interpreter import Interpreter
from mesonbuild.interpreterbase.decorators import ContainerTypeInfo, FeatureDeprecated, FeatureNew, KwargInfo, typed_pos_args, typed_kwargs
-from mesonbuild.interpreter.interpreterobjects import FileHolder
from mesonbuild.mesonlib import version_compare, MachineChoice
-from . import ExtensionModule, ModuleReturnValue, ModuleState
-from ..interpreter import Interpreter
+from . import NewExtensionModule, ModuleReturnValue, ModuleState
-class JavaModule(ExtensionModule):
+class JavaModule(NewExtensionModule):
@FeatureNew('Java Module', '0.60.0')
def __init__(self, interpreter: Interpreter):
- super().__init__(interpreter)
+ super().__init__()
self.methods.update({
'generate_native_header': self.generate_native_header,
'generate_native_headers': self.generate_native_headers,
})
- if 'java' not in interpreter.environment.coredata.compilers[MachineChoice.BUILD]:
- detect_compiler_for(interpreter.environment, 'java', MachineChoice.BUILD)
- self.javac = interpreter.environment.coredata.compilers[MachineChoice.BUILD]['java']
+ def __get_java_compiler(self, state: ModuleState) -> Compiler:
+ if 'java' not in state.environment.coredata.compilers[MachineChoice.BUILD]:
+ detect_compiler_for(state.environment, 'java', MachineChoice.BUILD)
+ return state.environment.coredata.compilers[MachineChoice.BUILD]['java']
@FeatureDeprecated('java.generate_native_header', '0.62.0', 'Use java.generate_native_headers instead')
- @typed_pos_args('generate_native_header', (str, FileHolder))
+ @typed_pos_args('java.generate_native_header', (str, mesonlib.File))
@typed_kwargs('java.generate_native_header', KwargInfo('package', str, default=None))
- def generate_native_header(self, state: ModuleState, args: T.Tuple[T.Union[str, FileHolder]],
+ def generate_native_header(self, state: ModuleState, args: T.Tuple[T.Union[str, mesonlib.File]],
kwargs: T.Dict[str, T.Optional[str]]) -> ModuleReturnValue:
package = kwargs.get('package')
- file = self.interpreter.source_strings_to_files(
- [a.held_object if isinstance(a, FileHolder) else a for a in args])[0]
+ if isinstance(args[0], mesonlib.File):
+ file = args[0]
+ else:
+ file = mesonlib.File.from_source_file(state.source_root, state.subdir, args[0])
if package:
header = f'{package.replace(".", "_")}_{pathlib.Path(file.fname).stem}.h'
else:
header = f'{pathlib.Path(file.fname).stem}.h'
+ javac = self.__get_java_compiler(state)
+
target = CustomTarget(
os.path.basename(header),
state.subdir,
state.subproject,
- [
- self.javac.exelist[0],
+ mesonlib.listify([
+ javac.exelist,
'-d',
'@PRIVATE_DIR@',
'-h',
state.subdir,
'@INPUT@',
- ],
+ ]),
[file],
[header],
backend=state.backend,
)
# It is only known that 1.8.0 won't pre-create the directory. 11 and 16
# do not exhibit this behavior.
- if version_compare(self.javac.version, '1.8.0'):
+ if version_compare(javac.version, '1.8.0'):
pathlib.Path(state.backend.get_target_private_dir_abs(target)).mkdir(parents=True, exist_ok=True)
return ModuleReturnValue(target, [target])
@FeatureNew('java.generate_native_headers', '0.62.0')
- @typed_pos_args('generate_native_headers', (str, mesonlib.File), min_varargs=1)
+ @typed_pos_args('java.generate_native_headers', (str, mesonlib.File), min_varargs=1)
@typed_kwargs('java.generate_native_headers',
KwargInfo('classes', (ContainerTypeInfo(list, str)), default=[], listify=True,
required=True),
@@ -94,8 +98,10 @@ class JavaModule(ExtensionModule):
else:
headers.append(f'{underscore_clazz}.h')
+ javac = self.__get_java_compiler(state)
+
command = mesonlib.listify([
- self.javac.exelist,
+ javac.exelist,
'-d',
'@PRIVATE_DIR@',
'-h',
@@ -110,7 +116,7 @@ class JavaModule(ExtensionModule):
# It is only known that 1.8.0 won't pre-create the directory. 11 and 16
# do not exhibit this behavior.
- if version_compare(self.javac.version, '1.8.0'):
+ if version_compare(javac.version, '1.8.0'):
pathlib.Path(state.backend.get_target_private_dir_abs(target)).mkdir(parents=True, exist_ok=True)
return ModuleReturnValue(target, [target])
diff --git a/mesonbuild/modules/unstable_wayland.py b/mesonbuild/modules/unstable_wayland.py
index 85da2b7..a7653d9 100644
--- a/mesonbuild/modules/unstable_wayland.py
+++ b/mesonbuild/modules/unstable_wayland.py
@@ -39,15 +39,18 @@ class WaylandModule(ExtensionModule):
@typed_pos_args('wayland.scan_xml', varargs=(str, File), min_varargs=1)
@typed_kwargs(
'wayland.scan_xml',
- KwargInfo('side', str, default='client', validator=in_set_validator({'client', 'server'})),
- KwargInfo('scope', str, default='private', validator=in_set_validator({'private', 'public'})),
+ KwargInfo('public', bool, default=False),
+ KwargInfo('client', bool, default=True),
+ KwargInfo('server', bool, default=False),
)
def scan_xml(self, state, args, kwargs):
if self.scanner_bin is None:
self.scanner_bin = state.find_program('wayland-scanner', for_machine=MachineChoice.BUILD)
- scope = kwargs['scope']
- side = kwargs['side']
+ scope = 'public' if kwargs['public'] else 'private'
+ sides = [i for i in ['client', 'server'] if kwargs[i]]
+ if not sides:
+ raise MesonException('At least one of client or server keyword argument must be set to true.')
xml_files = self.interpreter.source_strings_to_files(args[0])
targets = []
@@ -65,16 +68,17 @@ class WaylandModule(ExtensionModule):
)
targets.append(code)
- header = CustomTarget(
- f'{name}-{side}-protocol',
- state.subdir,
- state.subproject,
- [self.scanner_bin, f'{side}-header', '@INPUT@', '@OUTPUT@'],
- [xml_file],
- [f'{name}-{side}-protocol.h'],
- backend=state.backend,
- )
- targets.append(header)
+ for side in sides:
+ header = CustomTarget(
+ f'{name}-{side}-protocol',
+ state.subdir,
+ state.subproject,
+ [self.scanner_bin, f'{side}-header', '@INPUT@', '@OUTPUT@'],
+ [xml_file],
+ [f'{name}-{side}-protocol.h'],
+ backend=state.backend,
+ )
+ targets.append(header)
return ModuleReturnValue(targets, targets)
diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py
index d6bd366..c329892 100644
--- a/mesonbuild/scripts/gettext.py
+++ b/mesonbuild/scripts/gettext.py
@@ -24,6 +24,9 @@ parser.add_argument('--datadirs', default='')
parser.add_argument('--langs', default='')
parser.add_argument('--localedir', default='')
parser.add_argument('--subdir', default='')
+parser.add_argument('--xgettext', default='xgettext')
+parser.add_argument('--msgmerge', default='msgmerge')
+parser.add_argument('--msginit', default='msginit')
parser.add_argument('--extra-args', default='')
def read_linguas(src_sub: str) -> T.List[str]:
@@ -42,7 +45,7 @@ def read_linguas(src_sub: str) -> T.List[str]:
print(f'Could not find file LINGUAS in {src_sub}')
return []
-def run_potgen(src_sub: str, pkgname: str, datadirs: str, args: T.List[str]) -> int:
+def run_potgen(src_sub: str, xgettext: str, pkgname: str, datadirs: str, args: T.List[str]) -> int:
listfile = os.path.join(src_sub, 'POTFILES.in')
if not os.path.exists(listfile):
listfile = os.path.join(src_sub, 'POTFILES')
@@ -55,18 +58,18 @@ def run_potgen(src_sub: str, pkgname: str, datadirs: str, args: T.List[str]) ->
child_env['GETTEXTDATADIRS'] = datadirs
ofile = os.path.join(src_sub, pkgname + '.pot')
- return subprocess.call(['xgettext', '--package-name=' + pkgname, '-p', src_sub, '-f', listfile,
+ return subprocess.call([xgettext, '--package-name=' + pkgname, '-p', src_sub, '-f', listfile,
'-D', os.environ['MESON_SOURCE_ROOT'], '-k_', '-o', ofile] + args,
env=child_env)
-def update_po(src_sub: str, pkgname: str, langs: T.List[str]) -> int:
+def update_po(src_sub: str, msgmerge: str, msginit: str, pkgname: str, langs: T.List[str]) -> int:
potfile = os.path.join(src_sub, pkgname + '.pot')
for l in langs:
pofile = os.path.join(src_sub, l + '.po')
if os.path.exists(pofile):
- subprocess.check_call(['msgmerge', '-q', '-o', pofile, pofile, potfile])
+ subprocess.check_call([msgmerge, '-q', '-o', pofile, pofile, potfile])
else:
- subprocess.check_call(['msginit', '--input', potfile, '--output-file', pofile, '--locale', l, '--no-translator'])
+ subprocess.check_call([msginit, '--input', potfile, '--output-file', pofile, '--locale', l, '--no-translator'])
return 0
def run(args: T.List[str]) -> int:
@@ -83,11 +86,11 @@ def run(args: T.List[str]) -> int:
langs = read_linguas(src_sub)
if subcmd == 'pot':
- return run_potgen(src_sub, options.pkgname, options.datadirs, extra_args)
+ return run_potgen(src_sub, options.xgettext, options.pkgname, options.datadirs, extra_args)
elif subcmd == 'update_po':
- if run_potgen(src_sub, options.pkgname, options.datadirs, extra_args) != 0:
+ if run_potgen(src_sub, options.xgettext, options.pkgname, options.datadirs, extra_args) != 0:
return 1
- return update_po(src_sub, options.pkgname, langs)
+ return update_po(src_sub, options.msgmerge, options.msginit, options.pkgname, langs)
else:
print('Unknown subcommand.')
return 1
diff --git a/mesonbuild/scripts/itstool.py b/mesonbuild/scripts/itstool.py
index fa3b0fa..72ac3e5 100644
--- a/mesonbuild/scripts/itstool.py
+++ b/mesonbuild/scripts/itstool.py
@@ -24,11 +24,13 @@ parser.add_argument('command')
parser.add_argument('--build-dir', default='')
parser.add_argument('-i', '--input', default='')
parser.add_argument('-o', '--output', default='')
+parser.add_argument('--itstool', default='itstool')
parser.add_argument('--its', action='append', default=[])
parser.add_argument('mo_files', nargs='+')
-def run_join(build_dir: str, its_files: T.List[str], mo_files: T.List[str], in_fname: str, out_fname: str) -> int:
+def run_join(build_dir: str, itstool: str, its_files: T.List[str], mo_files: T.List[str],
+ in_fname: str, out_fname: str) -> int:
if not mo_files:
print('No mo files specified to use for translation.')
return 1
@@ -53,7 +55,7 @@ def run_join(build_dir: str, its_files: T.List[str], mo_files: T.List[str], in_f
shutil.copy(mo_file, tmp_mo_fname)
locale_mo_files.append(tmp_mo_fname)
- cmd = ['itstool']
+ cmd = [itstool]
if its_files:
for fname in its_files:
cmd.extend(['-i', fname])
@@ -73,6 +75,7 @@ def run(args: T.List[str]) -> int:
if command == 'join':
return run_join(build_dir,
+ options.itstool,
options.its,
options.mo_files,
options.input,
diff --git a/mesonbuild/scripts/msgfmthelper.py b/mesonbuild/scripts/msgfmthelper.py
index 3ddc9e6..b308f54 100644
--- a/mesonbuild/scripts/msgfmthelper.py
+++ b/mesonbuild/scripts/msgfmthelper.py
@@ -22,6 +22,7 @@ parser.add_argument('input')
parser.add_argument('output')
parser.add_argument('type')
parser.add_argument('podir')
+parser.add_argument('--msgfmt', default='msgfmt')
parser.add_argument('--datadirs', default='')
parser.add_argument('args', default=[], metavar='extra msgfmt argument', nargs='*')
@@ -32,6 +33,6 @@ def run(args: T.List[str]) -> int:
if options.datadirs:
env = os.environ.copy()
env.update({'GETTEXTDATADIRS': options.datadirs})
- return subprocess.call(['msgfmt', '--' + options.type, '-d', options.podir,
+ return subprocess.call([options.msgfmt, '--' + options.type, '-d', options.podir,
'--template', options.input, '-o', options.output] + options.args,
env=env)
diff --git a/test cases/cmake/12 generator expressions/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/12 generator expressions/subprojects/cmMod/CMakeLists.txt
index dc4f9e4..27b3721 100644
--- a/test cases/cmake/12 generator expressions/subprojects/cmMod/CMakeLists.txt
+++ b/test cases/cmake/12 generator expressions/subprojects/cmMod/CMakeLists.txt
@@ -12,6 +12,10 @@ target_compile_options(cmModLib
INTERFACE "-DCMAKE_FLAG_REQUIRED_A"
INTERFACE $<$<AND:1,$<STREQUAL:asd,$<LOWER_CASE:AsD>>,$<NOT:$<EQUAL:4,2>>>:-DCMAKE_FLAG_REQUIRED_B>
INTERFACE $<$<VERSION_LESS:1.2.3,2.1.0>:-DCMAKE_FLAG_REQUIRED_C>
+ INTERFACE $<IF:$<NOT:$<BOOL:OFF>>,-DCMAKE_TRUE_FLAG,-DCMAKE_FALSE_FLAG>
+ INTERFACE $<IF:$<TARGET_EXISTS:cmModLib>,-DCMAKE_TGT_EXISTS,-DCMAKE_TGT_NEXISTS>
+ INTERFACE $<IF:$<TARGET_PROPERTY:IMPORTED_NO_SONAME>,-DCMAKE_PROP1_OK,-DCMAKE_PROP1_ERROR>
+ INTERFACE $<IF:$<TARGET_PROPERTY:cmModLib,IMPORT_SUFFIX>,-DCMAKE_PROP2_ERROR,-DCMAKE_PROP2_OK>
)
target_include_directories(cmModLib INTERFACE
@@ -19,4 +23,10 @@ target_include_directories(cmModLib INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
+set_target_properties(cmModLib
+ PROPERTIES
+ IMPORTED_NO_SONAME 1
+ IMPORT_SUFFIX 0
+)
+
target_compile_definitions(cmModLib INTERFACE -DCMAKE_COMPILER_DEFINE_STR="compDef")
diff --git a/test cases/cmake/12 generator expressions/subprojects/cmMod/include/cmMod.hpp b/test cases/cmake/12 generator expressions/subprojects/cmMod/include/cmMod.hpp
index 1f00107..416e5bb 100644
--- a/test cases/cmake/12 generator expressions/subprojects/cmMod/include/cmMod.hpp
+++ b/test cases/cmake/12 generator expressions/subprojects/cmMod/include/cmMod.hpp
@@ -18,6 +18,38 @@
#error "The flag CMAKE_FLAG_ERROR_A was set"
#endif
+#ifndef CMAKE_TRUE_FLAG
+#error "The flag CMAKE_TRUE_FLAG was not set"
+#endif
+
+#ifdef CMAKE_FALSE_FLAG
+#error "The flag CMAKE_FALSE_FLAG was set"
+#endif
+
+#ifndef CMAKE_TGT_EXISTS
+#error "The flag CMAKE_TGT_EXISTS was not set"
+#endif
+
+#ifdef CMAKE_TGT_NEXISTS
+#error "The flag CMAKE_TGT_NEXISTS was set"
+#endif
+
+#ifndef CMAKE_PROP1_OK
+#error "The flag CMAKE_PROP1_OK was not set"
+#endif
+
+#ifdef CMAKE_PROP1_ERROR
+#error "The flag CMAKE_PROP1_ERROR was set"
+#endif
+
+#ifndef CMAKE_PROP2_OK
+#error "The flag CMAKE_PROP2_OK was not set"
+#endif
+
+#ifdef CMAKE_PROP2_ERROR
+#error "The flag CMAKE_PROP2_ERROR was set"
+#endif
+
class cmModClass {
private:
std::string str;
diff --git a/test cases/cmake/12 generator expressions/test.json b/test cases/cmake/12 generator expressions/test.json
new file mode 100644
index 0000000..faf1ff8
--- /dev/null
+++ b/test cases/cmake/12 generator expressions/test.json
@@ -0,0 +1,5 @@
+{
+ "tools": {
+ "cmake": ">=3.19"
+ }
+}
diff --git a/test cases/common/26 find program/meson.build b/test cases/common/26 find program/meson.build
index 3b59caa..a083d69 100644
--- a/test cases/common/26 find program/meson.build
+++ b/test cases/common/26 find program/meson.build
@@ -25,6 +25,9 @@ assert(not prog.found(), 'Version should be too old')
prog = find_program('print-version.py', version : '>=1.0')
assert(prog.found(), 'Program version should match')
+prog = find_program('print-version.py')
+assert(prog.version() == '1.0', 'Program version should be detectable')
+
prog = find_program('print-version-with-prefix.py', version : '>=1.0')
assert(prog.found(), 'Program version should match')
diff --git a/test cases/frameworks/6 gettext/data/meson.build b/test cases/frameworks/6 gettext/data/meson.build
index 1afb403..698eeec 100644
--- a/test cases/frameworks/6 gettext/data/meson.build
+++ b/test cases/frameworks/6 gettext/data/meson.build
@@ -4,6 +4,7 @@ i18n.merge_file(
output: '@BASENAME@',
type: 'desktop',
po_dir: '../po',
+ data_dirs: '../po',
install: true,
install_dir: join_paths(get_option('datadir'), 'applications')
)
diff --git a/test cases/frameworks/6 gettext/data2/meson.build b/test cases/frameworks/6 gettext/data2/meson.build
index b8c90a1..9a992c9 100644
--- a/test cases/frameworks/6 gettext/data2/meson.build
+++ b/test cases/frameworks/6 gettext/data2/meson.build
@@ -3,6 +3,7 @@ i18n.merge_file(
output: 'test.plugin',
type: 'desktop',
po_dir: '../po',
+ data_dirs: '../po',
args: ['--keyword=Description'],
install: true,
install_dir: join_paths(get_option('datadir'), 'applications')
diff --git a/test cases/java/9 jni/meson.build b/test cases/java/9 jni/meson.build
index 65d7ff6..1239e19 100644
--- a/test cases/java/9 jni/meson.build
+++ b/test cases/java/9 jni/meson.build
@@ -13,7 +13,7 @@ javamod = import('java')
java = find_program('java')
-jni_dep = dependency('jni', version : '>=1.8')
+jni_dep = dependency('jni', version : '>=1.8', modules: ['jvm', 'awt'])
# generate native headers
subdir('src/com/mesonbuild')
diff --git a/test cases/unit/99 install all targets/meson.build b/test cases/unit/99 install all targets/meson.build
index 94bd1fe..3d131e6 100644
--- a/test cases/unit/99 install all targets/meson.build
+++ b/test cases/unit/99 install all targets/meson.build
@@ -43,6 +43,12 @@ both_libraries('both', 'lib.c',
install: true,
)
+# Unversioned .so file should have 'devel' tag, others should have 'runtime' tag
+shared_library('versioned_shared', 'lib.c',
+ install: true,
+ version: '1.2.3',
+)
+
# Those files should have custom tag
install_data('bar-custom.txt',
install_dir: get_option('datadir'),
diff --git a/test cases/wayland/1 client/both.c b/test cases/wayland/1 client/both.c
new file mode 100644
index 0000000..b6e1bab
--- /dev/null
+++ b/test cases/wayland/1 client/both.c
@@ -0,0 +1,11 @@
+#include "viewporter-client-protocol.h"
+#include "viewporter-server-protocol.h"
+
+int main() {
+#if defined(VIEWPORTER_CLIENT_PROTOCOL_H) && \
+ defined(VIEWPORTER_SERVER_PROTOCOL_H)
+ return 0;
+#else
+ return 1;
+#endif
+}
diff --git a/test cases/wayland/1 client/main.c b/test cases/wayland/1 client/client.c
index 6aca80d..4966721 100644
--- a/test cases/wayland/1 client/main.c
+++ b/test cases/wayland/1 client/client.c
@@ -2,8 +2,8 @@
int main() {
#ifdef XDG_SHELL_CLIENT_PROTOCOL_H
- return 0;
+ return 0;
#else
- return 1;
+ return 1;
#endif
}
diff --git a/test cases/wayland/3 local/main.c b/test cases/wayland/1 client/local.c
index 97bfa56..97bfa56 100644
--- a/test cases/wayland/3 local/main.c
+++ b/test cases/wayland/1 client/local.c
diff --git a/test cases/wayland/1 client/meson.build b/test cases/wayland/1 client/meson.build
index 7ca868b..cb13db2 100644
--- a/test cases/wayland/1 client/meson.build
+++ b/test cases/wayland/1 client/meson.build
@@ -5,12 +5,44 @@ if not wl_protocols_dep.found()
error('MESON_SKIP_TEST: wayland-protocols not installed')
endif
-wl_dep = dependency('wayland-client')
+wl_client_dep = dependency('wayland-client')
+wl_server_dep = dependency('wayland-server')
wl_mod = import('unstable-wayland')
+fs = import('fs')
+# Client side only
xdg_shell_xml = wl_mod.find_protocol('xdg-shell')
xdg_shell = wl_mod.scan_xml(xdg_shell_xml)
+assert(xdg_shell.length() == 2)
+assert(fs.name(xdg_shell[0].full_path()) == 'xdg-shell-protocol.c')
+assert(fs.name(xdg_shell[1].full_path()) == 'xdg-shell-client-protocol.h')
+exe = executable('client', 'client.c', xdg_shell, dependencies : wl_client_dep)
+test('client', exe)
-exe = executable('client', 'main.c', xdg_shell, dependencies : wl_dep)
+# Server side only
+presentation_time_xml = wl_mod.find_protocol('presentation-time')
+presentation_time = wl_mod.scan_xml(presentation_time_xml, client : false, server : true)
+assert(presentation_time.length() == 2)
+assert(fs.name(presentation_time[0].full_path()) == 'presentation-time-protocol.c')
+assert(fs.name(presentation_time[1].full_path()) == 'presentation-time-server-protocol.h')
+exe = executable('server', 'server.c', presentation_time, dependencies : wl_server_dep)
+test('server', exe)
-test('client', exe)
+# Both sides
+viewporter_xml = wl_mod.find_protocol('viewporter')
+viewporter = wl_mod.scan_xml(viewporter_xml, client : true, server : true)
+assert(viewporter.length() == 3)
+assert(fs.name(viewporter[0].full_path()) == 'viewporter-protocol.c')
+assert(fs.name(viewporter[1].full_path()) == 'viewporter-client-protocol.h')
+assert(fs.name(viewporter[2].full_path()) == 'viewporter-server-protocol.h')
+exe = executable('both', 'both.c', viewporter, dependencies : [wl_client_dep, wl_server_dep])
+test('both', exe)
+
+# Local xml
+xmls = files('test.xml')
+gen = wl_mod.scan_xml(xmls)
+assert(gen.length() == 2)
+assert(fs.name(gen[0].full_path()) == 'test-protocol.c')
+assert(fs.name(gen[1].full_path()) == 'test-client-protocol.h')
+exe = executable('local', 'local.c', gen, dependencies : wl_client_dep)
+test('local', exe)
diff --git a/test cases/wayland/1 client/server.c b/test cases/wayland/1 client/server.c
new file mode 100644
index 0000000..e073a7b
--- /dev/null
+++ b/test cases/wayland/1 client/server.c
@@ -0,0 +1,9 @@
+#include "presentation-time-server-protocol.h"
+
+int main() {
+#ifdef PRESENTATION_TIME_SERVER_PROTOCOL_H
+ return 0;
+#else
+ return 1;
+#endif
+}
diff --git a/test cases/wayland/3 local/test.xml b/test cases/wayland/1 client/test.xml
index f3c6db1..f3c6db1 100644
--- a/test cases/wayland/3 local/test.xml
+++ b/test cases/wayland/1 client/test.xml
diff --git a/test cases/wayland/2 server/main.c b/test cases/wayland/2 server/main.c
deleted file mode 100644
index 3307499..0000000
--- a/test cases/wayland/2 server/main.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "xdg-shell-server-protocol.h"
-
-int main() {
-#ifdef XDG_SHELL_SERVER_PROTOCOL_H
- return 0;
-#else
- return 1;
-#endif
-}
diff --git a/test cases/wayland/2 server/meson.build b/test cases/wayland/2 server/meson.build
deleted file mode 100644
index c93ff11..0000000
--- a/test cases/wayland/2 server/meson.build
+++ /dev/null
@@ -1,16 +0,0 @@
-project('wayland-test-server', 'c')
-
-wl_protocols_dep = dependency('wayland-protocols', required : false)
-if not wl_protocols_dep.found()
- error('MESON_SKIP_TEST: wayland-protocols not installed')
-endif
-
-wl_dep = dependency('wayland-server')
-wl_mod = import('unstable-wayland')
-
-xdg_shell_xml = wl_mod.find_protocol('xdg-shell')
-xdg_shell = wl_mod.scan_xml(xdg_shell_xml, side : 'server')
-
-exe = executable('server', 'main.c', xdg_shell, dependencies : wl_dep)
-
-test('client', exe)
diff --git a/test cases/wayland/3 local/meson.build b/test cases/wayland/3 local/meson.build
deleted file mode 100644
index 7a470d6..0000000
--- a/test cases/wayland/3 local/meson.build
+++ /dev/null
@@ -1,11 +0,0 @@
-project('wayland-test-local', 'c')
-
-wl_dep = dependency('wayland-client')
-wl_mod = import('unstable-wayland')
-
-xmls = files('test.xml')
-gen = wl_mod.scan_xml(xmls)
-
-exe = executable('local', 'main.c', gen, dependencies : wl_dep)
-
-test('local', exe)
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index 3eea9a3..665e0c6 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -3886,10 +3886,12 @@ class AllPlatformTests(BasePlatformTests):
Path(installpath, 'usr/bin/both2.pdb'),
Path(installpath, 'usr/bin/bothcustom.pdb'),
Path(installpath, 'usr/bin/shared.pdb'),
+ Path(installpath, 'usr/bin/versioned_shared-1.pdb'),
Path(installpath, 'usr/lib/both.lib'),
Path(installpath, 'usr/lib/both2.lib'),
Path(installpath, 'usr/lib/bothcustom.lib'),
Path(installpath, 'usr/lib/shared.lib'),
+ Path(installpath, 'usr/lib/versioned_shared.lib'),
}
elif is_windows() or is_cygwin():
expected_devel |= {
@@ -3897,6 +3899,11 @@ class AllPlatformTests(BasePlatformTests):
Path(installpath, 'usr/lib/libboth2.dll.a'),
Path(installpath, 'usr/lib/libshared.dll.a'),
Path(installpath, 'usr/lib/libbothcustom.dll.a'),
+ Path(installpath, 'usr/lib/libversioned_shared.dll.a'),
+ }
+ else:
+ expected_devel |= {
+ Path(installpath, 'usr/' + shared_lib_name('versioned_shared')),
}
expected_runtime = expected_common | {
@@ -3908,6 +3915,20 @@ class AllPlatformTests(BasePlatformTests):
Path(installpath, 'usr/' + shared_lib_name('both2')),
}
+ if is_windows() or is_cygwin():
+ expected_runtime |= {
+ Path(installpath, 'usr/' + shared_lib_name('versioned_shared-1')),
+ }
+ elif is_osx():
+ expected_runtime |= {
+ Path(installpath, 'usr/' + shared_lib_name('versioned_shared.1')),
+ }
+ else:
+ expected_runtime |= {
+ Path(installpath, 'usr/' + shared_lib_name('versioned_shared') + '.1'),
+ Path(installpath, 'usr/' + shared_lib_name('versioned_shared') + '.1.2.3'),
+ }
+
expected_custom = expected_common | {
Path(installpath, 'usr/share'),
Path(installpath, 'usr/share/bar-custom.txt'),