aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Custom-build-targets.md4
-rw-r--r--docs/markdown/Pkgconfig-module.md2
-rw-r--r--docs/markdown/Reference-tables.md31
-rw-r--r--docs/markdown/snippets/pkgconfig_dataonly.md15
-rw-r--r--mesonbuild/cmake/data/preload.cmake35
-rw-r--r--mesonbuild/cmake/interpreter.py64
-rw-r--r--mesonbuild/cmake/traceparser.py84
-rw-r--r--mesonbuild/compilers/compilers.py28
-rw-r--r--mesonbuild/coredata.py30
-rw-r--r--mesonbuild/environment.py26
-rw-r--r--mesonbuild/linkers.py50
-rw-r--r--mesonbuild/modules/pkgconfig.py60
-rwxr-xr-xmesonbuild/msubprojects.py8
-rwxr-xr-xrun_unittests.py27
-rw-r--r--setup.py2
-rw-r--r--test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt32
-rw-r--r--test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp3
-rw-r--r--test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp8
-rw-r--r--test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/CMakeLists.txt7
-rw-r--r--test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest.hpp5
-rw-r--r--test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest2.hpp3
-rw-r--r--test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest3.hpp3
-rw-r--r--test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest4.hpp3
-rw-r--r--test cases/common/47 pkgconfig-gen/installed_files.txt1
-rw-r--r--test cases/common/47 pkgconfig-gen/meson.build7
25 files changed, 400 insertions, 138 deletions
diff --git a/docs/markdown/Custom-build-targets.md b/docs/markdown/Custom-build-targets.md
index 9a0f2a1..f0b50d8 100644
--- a/docs/markdown/Custom-build-targets.md
+++ b/docs/markdown/Custom-build-targets.md
@@ -16,8 +16,8 @@ infile = 'source_code.txt'
outfile = 'output.bin'
mytarget = custom_target('targetname',
- output : 'output.bin',
- input : 'source_code.txt',
+ output : outfile,
+ input : infile,
command : [comp, '@INPUT@', '@OUTPUT@'],
install : true,
install_dir : 'subdir')
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-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/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/data/preload.cmake b/mesonbuild/cmake/data/preload.cmake
new file mode 100644
index 0000000..30178fb
--- /dev/null
+++ b/mesonbuild/cmake/data/preload.cmake
@@ -0,0 +1,35 @@
+if(MESON_PS_LOADED)
+ return()
+endif()
+
+set(MESON_PS_LOADED ON)
+
+# Dummy macros that have a special meaning in the meson code
+macro(meson_ps_execute_delayed_calls)
+endmacro()
+
+macro(meson_ps_reload_vars)
+endmacro()
+
+# Helper macro to inspect the current CMake state
+macro(meson_ps_inspect_vars)
+ set(MESON_PS_CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+ set(MESON_PS_CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+ meson_ps_execute_delayed_calls()
+endmacro()
+
+
+# Override some system functions with custom code and forward the args
+# to the original function
+macro(add_custom_command)
+ meson_ps_inspect_vars()
+ _add_custom_command(${ARGV})
+endmacro()
+
+macro(add_custom_target)
+ meson_ps_inspect_vars()
+ _add_custom_target(${ARGV})
+endmacro()
+
+set(MESON_PS_DELAYED_CALLS add_custom_command;add_custom_target)
+meson_ps_reload_vars()
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 4d87705..941baed 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -26,6 +26,7 @@ from ..mesonlib import MachineChoice, version_compare
from ..compilers.compilers import lang_suffixes, header_suffixes, obj_suffixes, lib_suffixes, is_header
from enum import Enum
from functools import lru_cache
+from pathlib import Path
import typing as T
import os, re
@@ -592,6 +593,8 @@ class ConverterCustomTarget:
out_counter = 0 # type: int
def __init__(self, target: CMakeGeneratorTarget):
+ assert(target.current_bin_dir is not None)
+ assert(target.current_src_dir is not None)
self.name = target.name
if not self.name:
self.name = 'custom_tgt_{}'.format(ConverterCustomTarget.tgt_counter)
@@ -605,6 +608,8 @@ class ConverterCustomTarget:
self.depends_raw = target.depends
self.inputs = []
self.depends = []
+ self.current_bin_dir = Path(target.current_bin_dir)
+ self.current_src_dir = Path(target.current_src_dir)
# Convert the target name to a valid meson target name
self.name = _sanitize_cmake_name(self.name)
@@ -612,29 +617,24 @@ class ConverterCustomTarget:
def __repr__(self) -> str:
return '<{}: {} {}>'.format(self.__class__.__name__, self.name, self.outputs)
- def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: str, subdir: str, build_dir: str, all_outputs: T.List[str]) -> None:
- # Default the working directory to the CMake build dir. This
- # is not 100% correct, since it should be the value of
- # ${CMAKE_CURRENT_BINARY_DIR} when add_custom_command is
- # called. However, keeping track of this variable is not
- # trivial and the current solution should work in most cases.
+ def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: str, subdir: str, all_outputs: T.List[str]) -> None:
+ # Default the working directory to ${CMAKE_CURRENT_BINARY_DIR}
if not self.working_dir:
- self.working_dir = build_dir
+ self.working_dir = self.current_bin_dir.as_posix()
# relative paths in the working directory are always relative
- # to ${CMAKE_CURRENT_BINARY_DIR} (see note above)
+ # to ${CMAKE_CURRENT_BINARY_DIR}
if not os.path.isabs(self.working_dir):
- self.working_dir = os.path.normpath(os.path.join(build_dir, self.working_dir))
+ self.working_dir = (self.current_bin_dir / self.working_dir).as_posix()
# Modify the original outputs if they are relative. Again,
# relative paths are relative to ${CMAKE_CURRENT_BINARY_DIR}
- # and the first disclaimer is still in effect
- def ensure_absolute(x: str):
- if os.path.isabs(x):
+ def ensure_absolute(x: Path) -> Path:
+ if x.is_absolute():
return x
else:
- return os.path.normpath(os.path.join(build_dir, x))
- self.original_outputs = [ensure_absolute(x) for x in self.original_outputs]
+ return self.current_bin_dir / x
+ self.original_outputs = [ensure_absolute(Path(x)).as_posix() for x in self.original_outputs]
# Ensure that there is no duplicate output in the project so
# that meson can handle cases where the same filename is
@@ -671,23 +671,35 @@ class ConverterCustomTarget:
self.outputs = [self.name + '.h']
# Check dependencies and input files
+ root = Path(root_src_dir)
for i in self.depends_raw:
if not i:
continue
+ raw = Path(i)
art = output_target_map.artifact(i)
tgt = output_target_map.target(i)
gen = output_target_map.generated(i)
- if art:
+ rel_to_root = None
+ try:
+ rel_to_root = raw.relative_to(root)
+ except ValueError:
+ rel_to_root = None
+
+ # First check for existing files. Only then check for existing
+ # targets, etc. This reduces the chance of misdetecting input files
+ # as outputs from other targets.
+ # See https://github.com/mesonbuild/meson/issues/6632
+ if not raw.is_absolute() and (self.current_src_dir / raw).exists():
+ self.inputs += [(self.current_src_dir / raw).relative_to(root).as_posix()]
+ elif raw.is_absolute() and raw.exists() and rel_to_root is not None:
+ self.inputs += [rel_to_root.as_posix()]
+ elif art:
self.depends += [art]
elif tgt:
self.depends += [tgt]
elif gen:
self.inputs += [gen.get_ref(i)]
- elif not os.path.isabs(i) and os.path.exists(os.path.join(root_src_dir, i)):
- self.inputs += [i]
- elif os.path.isabs(i) and os.path.exists(i) and os.path.commonpath([i, root_src_dir]) == root_src_dir:
- self.inputs += [os.path.relpath(i, root_src_dir)]
def process_inter_target_dependencies(self):
# Move the dependencies from all transfer_dependencies_from to the target
@@ -767,10 +779,19 @@ class CMakeInterpreter:
raise CMakeException('Unable to find CMake')
self.trace = CMakeTraceParser(cmake_exe.version(), self.build_dir, permissive=True)
+ preload_file = Path(__file__).resolve().parent / 'data' / 'preload.cmake'
+
+ # Prefere CMAKE_PROJECT_INCLUDE over CMAKE_TOOLCHAIN_FILE if possible,
+ # since CMAKE_PROJECT_INCLUDE was actually designed for code injection.
+ preload_var = 'CMAKE_PROJECT_INCLUDE'
+ if version_compare(cmake_exe.version(), '<3.15'):
+ preload_var = 'CMAKE_TOOLCHAIN_FILE'
+
generator = backend_generator_map[self.backend_name]
cmake_args = []
trace_args = self.trace.trace_args()
cmcmp_args = ['-DCMAKE_POLICY_WARNING_{}=OFF'.format(x) for x in disable_policy_warnings]
+ pload_args = ['-D{}={}'.format(preload_var, str(preload_file))]
if version_compare(cmake_exe.version(), '>=3.14'):
self.cmake_api = CMakeAPI.FILE
@@ -802,12 +823,13 @@ class CMakeInterpreter:
mlog.log(mlog.bold(' - build directory: '), self.build_dir)
mlog.log(mlog.bold(' - source directory: '), self.src_dir)
mlog.log(mlog.bold(' - trace args: '), ' '.join(trace_args))
+ mlog.log(mlog.bold(' - preload file: '), str(preload_file))
mlog.log(mlog.bold(' - disabled policy warnings:'), '[{}]'.format(', '.join(disable_policy_warnings)))
mlog.log()
os.makedirs(self.build_dir, exist_ok=True)
os_env = os.environ.copy()
os_env['LC_ALL'] = 'C'
- final_args = cmake_args + trace_args + cmcmp_args + [self.src_dir]
+ final_args = cmake_args + trace_args + cmcmp_args + pload_args + [self.src_dir]
cmake_exe.set_exec_mode(print_cmout=True, always_capture_stderr=self.trace.requires_stderr())
rc, _, self.raw_trace = cmake_exe.call(final_args, self.build_dir, env=os_env, disable_cache=True)
@@ -913,7 +935,7 @@ class CMakeInterpreter:
object_libs = []
custom_target_outputs = [] # type: T.List[str]
for i in self.custom_targets:
- i.postprocess(self.output_target_map, self.src_dir, self.subdir, self.build_dir, custom_target_outputs)
+ i.postprocess(self.output_target_map, self.src_dir, self.subdir, custom_target_outputs)
for i in self.targets:
i.postprocess(self.output_target_map, self.src_dir, self.subdir, self.install_prefix, self.trace)
if i.type == 'OBJECT_LIBRARY':
diff --git a/mesonbuild/cmake/traceparser.py b/mesonbuild/cmake/traceparser.py
index 7b29c86..8eb8605 100644
--- a/mesonbuild/cmake/traceparser.py
+++ b/mesonbuild/cmake/traceparser.py
@@ -47,6 +47,8 @@ class CMakeTarget:
self.imported = imported
self.tline = tline
self.depends = []
+ self.current_bin_dir = None
+ self.current_src_dir = None
def __repr__(self):
s = 'CMake TARGET:\n -- name: {}\n -- type: {}\n -- imported: {}\n -- properties: {{\n{} }}\n -- tline: {}'
@@ -83,6 +85,36 @@ class CMakeTraceParser:
self.trace_file_path = Path(build_dir) / self.trace_file
self.trace_format = 'json-v1' if version_compare(cmake_version, '>=3.17') else 'human'
+ # State for delayed command execution. Delayed command execution is realised
+ # with a custom CMake file that overrides some functions and adds some
+ # introspection information to the trace.
+ self.delayed_commands = [] # type: T.List[str]
+ self.stored_commands = [] # type: T.List[CMakeTraceLine]
+
+ # All supported functions
+ self.functions = {
+ 'set': self._cmake_set,
+ 'unset': self._cmake_unset,
+ 'add_executable': self._cmake_add_executable,
+ 'add_library': self._cmake_add_library,
+ 'add_custom_command': self._cmake_add_custom_command,
+ 'add_custom_target': self._cmake_add_custom_target,
+ 'set_property': self._cmake_set_property,
+ 'set_target_properties': self._cmake_set_target_properties,
+ 'target_compile_definitions': self._cmake_target_compile_definitions,
+ 'target_compile_options': self._cmake_target_compile_options,
+ 'target_include_directories': self._cmake_target_include_directories,
+ 'target_link_libraries': self._cmake_target_link_libraries,
+ 'target_link_options': self._cmake_target_link_options,
+ 'add_dependencies': self._cmake_add_dependencies,
+
+ # Special functions defined in the preload script.
+ # These functions do nothing in the CMake code, but have special
+ # meaning here in the trace parser.
+ 'meson_ps_execute_delayed_calls': self._meson_ps_execute_delayed_calls,
+ 'meson_ps_reload_vars': self._meson_ps_reload_vars,
+ }
+
def trace_args(self) -> T.List[str]:
arg_map = {
'human': ['--trace', '--trace-expand'],
@@ -116,28 +148,15 @@ class CMakeTraceParser:
else:
raise CMakeException('CMake: Internal error: Invalid trace format {}. Expected [human, json-v1]'.format(self.trace_format))
- # All supported functions
- functions = {
- 'set': self._cmake_set,
- 'unset': self._cmake_unset,
- 'add_executable': self._cmake_add_executable,
- 'add_library': self._cmake_add_library,
- 'add_custom_command': self._cmake_add_custom_command,
- 'add_custom_target': self._cmake_add_custom_target,
- 'set_property': self._cmake_set_property,
- 'set_target_properties': self._cmake_set_target_properties,
- 'target_compile_definitions': self._cmake_target_compile_definitions,
- 'target_compile_options': self._cmake_target_compile_options,
- 'target_include_directories': self._cmake_target_include_directories,
- 'target_link_libraries': self._cmake_target_link_libraries,
- 'target_link_options': self._cmake_target_link_options,
- 'add_dependencies': self._cmake_add_dependencies,
- }
-
# Primary pass -- parse everything
for l in lexer1:
+ # store the function if its execution should be delayed
+ if l.func in self.delayed_commands:
+ self.stored_commands += [l]
+ continue
+
# "Execute" the CMake function if supported
- fn = functions.get(l.func, None)
+ fn = self.functions.get(l.func, None)
if(fn):
fn(l)
@@ -160,6 +179,12 @@ class CMakeTraceParser:
return []
+ def var_to_str(self, var: str) -> T.Optional[str]:
+ if var in self.vars and self.vars[var]:
+ return self.vars[var][0]
+
+ return None
+
def var_to_bool(self, var):
if var not in self.vars:
return False
@@ -300,7 +325,7 @@ class CMakeTraceParser:
target = CMakeGeneratorTarget(name)
def handle_output(key: str, target: CMakeGeneratorTarget) -> None:
- target.outputs += [key]
+ target.outputs += key.split(';')
def handle_command(key: str, target: CMakeGeneratorTarget) -> None:
if key == 'ARGS':
@@ -308,7 +333,7 @@ class CMakeTraceParser:
target.command[-1] += key.split(';')
def handle_depends(key: str, target: CMakeGeneratorTarget) -> None:
- target.depends += [key]
+ target.depends += key.split(';')
def handle_working_dir(key: str, target: CMakeGeneratorTarget) -> None:
if target.working_dir is None:
@@ -337,6 +362,8 @@ class CMakeTraceParser:
if fn is not None:
fn(i, target)
+ target.current_bin_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_BINARY_DIR')
+ target.current_src_dir = self.var_to_str('MESON_PS_CMAKE_CURRENT_SOURCE_DIR')
target.outputs = self._guess_files(target.outputs)
target.depends = self._guess_files(target.depends)
target.command = [self._guess_files(x) for x in target.command]
@@ -465,7 +492,8 @@ class CMakeTraceParser:
if not target:
return self._gen_exception('add_dependencies', 'target not found', tline)
- target.depends += args[1:]
+ for i in args[1:]:
+ target.depends += i.split(';')
def _cmake_target_compile_definitions(self, tline: CMakeTraceLine) -> None:
# DOC: https://cmake.org/cmake/help/latest/command/target_compile_definitions.html
@@ -531,6 +559,18 @@ class CMakeTraceParser:
self.targets[target].properties[i[0]] += i[1]
+ def _meson_ps_execute_delayed_calls(self, tline: CMakeTraceLine) -> None:
+ for l in self.stored_commands:
+ fn = self.functions.get(l.func, None)
+ if(fn):
+ fn(l)
+
+ # clear the stored commands
+ self.stored_commands = []
+
+ def _meson_ps_reload_vars(self, tline: CMakeTraceLine) -> None:
+ self.delayed_commands = self.get_cmake_var('MESON_PS_DELAYED_CALLS')
+
def _lex_trace_human(self, trace):
# The trace format is: '<file>(<line>): <func>(<args -- can contain \n> )\n'
reg_tline = re.compile(r'\s*(.*\.(cmake|txt))\(([0-9]+)\):\s*(\w+)\(([\s\S]*?) ?\)\s*\n', re.MULTILINE)
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index e8e72cf..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]
@@ -1059,7 +1065,25 @@ class Compiler:
return self.linker.get_undefined_link_args()
def remove_linkerlike_args(self, args):
- return [x for x in args if not x.startswith('-Wl')]
+ rm_exact = ('-headerpad_max_install_names',)
+ rm_prefixes = ('-Wl,', '-L',)
+ rm_next = ('-L',)
+ ret = []
+ iargs = iter(args)
+ for arg in iargs:
+ # Remove this argument
+ if arg in rm_exact:
+ continue
+ # If the argument starts with this, but is not *exactly* this
+ # f.ex., '-L' should match ['-Lfoo'] but not ['-L', 'foo']
+ if arg.startswith(rm_prefixes) and arg not in rm_prefixes:
+ continue
+ # Ignore this argument and the one after it
+ if arg in rm_next:
+ next(iargs)
+ continue
+ ret.append(arg)
+ return ret
def get_lto_compile_args(self) -> T.List[str]:
return []
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 11b8deb..f1ce578 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -19,7 +19,7 @@ from itertools import chain
from pathlib import PurePath
from collections import OrderedDict
from .mesonlib import (
- MesonException, MachineChoice, PerMachine,
+ MesonException, MachineChoice, PerMachine, OrderedSet,
default_libdir, default_libexecdir, default_prefix, split_args
)
from .wrap import WrapMode
@@ -746,16 +746,20 @@ class CoreData:
# Some options default to environment variables if they are
# unset, set those now. These will either be overwritten
# below, or they won't. These should only be set on the first run.
- if env.first_invocation:
- p_env = os.environ.get('PKG_CONFIG_PATH')
- if p_env:
- # PKG_CONFIG_PATH may contain duplicates, which must be
- # removed, else a duplicates-in-array-option warning arises.
- pkg_config_paths = []
- for k in p_env.split(':'):
- if k not in pkg_config_paths:
- pkg_config_paths.append(k)
- options['pkg_config_path'] = pkg_config_paths
+ p_env = os.environ.get('PKG_CONFIG_PATH')
+ if p_env:
+ # PKG_CONFIG_PATH may contain duplicates, which must be
+ # removed, else a duplicates-in-array-option warning arises.
+ p_list = list(OrderedSet(p_env.split(':')))
+ if env.first_invocation:
+ options['pkg_config_path'] = p_list
+ elif options.get('pkg_config_path', []) != p_list:
+ mlog.warning(
+ 'PKG_CONFIG_PATH environment variable has changed '
+ 'between configurations, meson ignores this. '
+ 'Use -Dpkg_config_path to change pkg-config search '
+ 'path instead.'
+ )
for k, v in env.cmd_line_options.items():
if subproject:
@@ -1077,8 +1081,8 @@ builtin_options = OrderedDict([
])
builtin_options_per_machine = OrderedDict([
- ('pkg_config_path', BuiltinOption(UserArrayOption, 'T.List of additional paths for pkg-config to search', [])),
- ('cmake_prefix_path', BuiltinOption(UserArrayOption, 'T.List of additional prefixes for cmake to search', [])),
+ ('pkg_config_path', BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])),
+ ('cmake_prefix_path', BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])),
])
# Special prefix-dependent defaults for installation directories that reside in
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 310223a..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,18 +652,29 @@ 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.
"""
def __init__(self, *args, **kwargs):
- super().__init__(*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'))
@@ -672,14 +686,13 @@ class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna
return []
-
class CcrxDynamicLinker(DynamicLinker):
"""Linker for Renesis CCrx compiler."""
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:
@@ -712,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:
@@ -744,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 []
@@ -857,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]:
@@ -873,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)
@@ -883,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
@@ -940,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/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/run_unittests.py b/run_unittests.py
index 7c2ae05..033647c 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -4896,6 +4896,11 @@ class DarwinTests(BasePlatformTests):
self.build()
self.install()
+ def test_removing_unused_linker_args(self):
+ testdir = os.path.join(self.common_test_dir, '108 has arg')
+ env = {'CFLAGS': '-L/tmp -L /var/tmp -headerpad_max_install_names -Wl,-export_dynamic'}
+ self.init(testdir, override_envvars=env)
+
@unittest.skipUnless(not is_windows(), "requires something Unix-like")
class LinuxlikeTests(BasePlatformTests):
@@ -4969,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
@@ -5939,7 +5949,6 @@ class LinuxlikeTests(BasePlatformTests):
'''
testdir = os.path.join(self.common_test_dir, testdir)
subdir = os.path.join(testdir, subdir_path)
- curdir = os.getcwd()
with chdir(subdir):
# Can't distribute broken symlinks in the source tree because it breaks
# the creation of zipapps. Create it dynamically and run the test by
@@ -6056,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/setup.py b/setup.py
index b816b80..1f95be7 100644
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,7 @@ packages = ['mesonbuild',
'mesonbuild.wrap']
package_data = {
'mesonbuild.dependencies': ['data/CMakeLists.txt', 'data/CMakeListsLLVM.txt', 'data/CMakePathInfo.txt'],
- 'mesonbuild.cmake': ['data/run_ctgt.py'],
+ 'mesonbuild.cmake': ['data/run_ctgt.py', 'data/preload.cmake'],
}
data_files = []
if sys.platform != 'win32':
diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt b/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt
index 776ce52..c7797db 100644
--- a/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt
+++ b/test cases/cmake/8 custom command/subprojects/cmMod/CMakeLists.txt
@@ -22,7 +22,7 @@ add_custom_command(
COMMAND mycpy cpyBase.cpp.in cpyBase.cpp.something
COMMAND mycpy cpyBase.cpp.something cpyBase.cpp.IAmRunningOutOfIdeas
COMMAND mycpy cpyBase.cpp.IAmRunningOutOfIdeas cpyBase.cpp
- DEPENDS cpyBase.cpp.am gen
+ DEPENDS cpyBase.cpp.am;gen
)
add_custom_command(
@@ -89,7 +89,29 @@ add_custom_command(
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/s2_a_cpp"
)
-add_library(cmModLib SHARED cmMod.cpp genTest.cpp cpyBase.cpp cpyBase.hpp cpyNext.cpp cpyNext.hpp)
+# cpyTest (copy file without renaming)
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cpyTest.hpp"
+ COMMAND mycpy "${CMAKE_CURRENT_SOURCE_DIR}/cpyTest/cpyTest.hpp" "${CMAKE_CURRENT_BINARY_DIR}/cpyTest.hpp"
+ DEPENDS "cpyTest/cpyTest.hpp"
+)
+
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cpyTest2.hpp"
+ COMMAND mycpy "${CMAKE_CURRENT_SOURCE_DIR}/cpyTest/cpyTest2.hpp" "${CMAKE_CURRENT_BINARY_DIR}/cpyTest2.hpp"
+ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/cpyTest/cpyTest2.hpp"
+)
+
+add_custom_command(
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cpyTest3.hpp"
+ COMMAND mycpy cpyTest3.hpp "${CMAKE_CURRENT_BINARY_DIR}/cpyTest3.hpp"
+ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/cpyTest/cpyTest3.hpp"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/cpyTest"
+)
+
+add_subdirectory(cpyTest ccppyyTTeesstt)
+
+add_library(cmModLib SHARED cmMod.cpp genTest.cpp cpyBase.cpp cpyBase.hpp cpyNext.cpp cpyNext.hpp cpyTest.cpp cpyTest.hpp cpyTest2.hpp cpyTest3.hpp)
include(GenerateExportHeader)
generate_export_header(cmModLib)
@@ -99,9 +121,9 @@ set(ARGS_TEST ${ARGS_TEST} arg2)
add_executable(macro_name macro_name.cpp)
add_executable(args_test args_test.cpp)
add_custom_target(args_test_cmd
- COMMAND args_test ARGS ${ARGS_TEST}
+ COMMAND args_test ${ARGS_TEST}
)
add_custom_target(macro_name_cmd COMMAND macro_name)
-add_dependencies(cmModLib args_test_cmd)
-add_dependencies(args_test_cmd macro_name_cmd)
+add_dependencies(cmModLib args_test_cmd tgtCpyTest4)
+add_dependencies(args_test_cmd macro_name_cmd;gen;mycpy)
diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp b/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp
index e6236e4..e4d5318 100644
--- a/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp
+++ b/test cases/cmake/8 custom command/subprojects/cmMod/cmMod.cpp
@@ -2,6 +2,7 @@
#include "genTest.hpp"
#include "cpyBase.hpp"
#include "cpyNext.hpp"
+#include "cpyTest.hpp"
#include "cmModLib.hpp"
#ifndef FOO
@@ -19,5 +20,5 @@ string cmModClass::getStr() const {
}
string cmModClass::getOther() const {
- return "Srings:\n - " + getStrCpy() + "\n - " + getStrNext();
+ return "Srings:\n - " + getStrCpy() + "\n - " + getStrNext() + "\n - " + getStrCpyTest();
}
diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp
new file mode 100644
index 0000000..f762251
--- /dev/null
+++ b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest.cpp
@@ -0,0 +1,8 @@
+#include "cpyTest.hpp"
+#include "cpyTest2.hpp"
+#include "cpyTest3.hpp"
+#include "ccppyyTTeesstt/cpyTest4.hpp"
+
+std::string getStrCpyTest() {
+ return CPY_TEST_STR_2 CPY_TEST_STR_3 CPY_TEST_STR_4;
+}
diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/CMakeLists.txt b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/CMakeLists.txt
new file mode 100644
index 0000000..f577dcf
--- /dev/null
+++ b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_custom_command(
+ OUTPUT cpyTest4.hpp
+ COMMAND mycpy "${CMAKE_CURRENT_SOURCE_DIR}/cpyTest4.hpp" cpyTest4.hpp
+ DEPENDS cpyTest4.hpp
+)
+
+add_custom_target(tgtCpyTest4 DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/cpyTest4.hpp")
diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest.hpp b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest.hpp
new file mode 100644
index 0000000..e8dec13
--- /dev/null
+++ b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <string>
+
+std::string getStrCpyTest();
diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest2.hpp b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest2.hpp
new file mode 100644
index 0000000..bdbcc56
--- /dev/null
+++ b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest2.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+#define CPY_TEST_STR_2 "Hello "
diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest3.hpp b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest3.hpp
new file mode 100644
index 0000000..2d13376
--- /dev/null
+++ b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest3.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+#define CPY_TEST_STR_3 "CopyFile"
diff --git a/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest4.hpp b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest4.hpp
new file mode 100644
index 0000000..4124c43
--- /dev/null
+++ b/test cases/cmake/8 custom command/subprojects/cmMod/cpyTest/cpyTest4.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+#define CPY_TEST_STR_4 " test"
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
+)