aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Custom-build-targets.md4
-rw-r--r--docs/markdown/Dependencies.md2
-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/interpreter.py14
-rw-r--r--mesonbuild/compilers/compilers.py28
-rw-r--r--mesonbuild/coredata.py37
-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--test cases/common/47 pkgconfig-gen/installed_files.txt1
-rw-r--r--test cases/common/47 pkgconfig-gen/meson.build7
-rw-r--r--test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp3
-rw-r--r--test cases/failing build/4 cmake subproject isolation/main.cpp10
-rw-r--r--test cases/failing build/4 cmake subproject isolation/meson.build17
-rw-r--r--test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt10
-rw-r--r--test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp12
-rw-r--r--test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp14
21 files changed, 286 insertions, 92 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/Dependencies.md b/docs/markdown/Dependencies.md
index 50ea92f..8cffba4 100644
--- a/docs/markdown/Dependencies.md
+++ b/docs/markdown/Dependencies.md
@@ -181,7 +181,7 @@ should only be used if the CMake files are not stored in the project itself.
Additional CMake parameters can be specified with the `cmake_args` property.
-### Some notes on Dub
+## Dub
Please understand that meson is only able to find dependencies that
exist in the local Dub repository. You need to manually fetch and
diff --git a/docs/markdown/Pkgconfig-module.md b/docs/markdown/Pkgconfig-module.md
index 678090b..13fc4e6 100644
--- a/docs/markdown/Pkgconfig-module.md
+++ b/docs/markdown/Pkgconfig-module.md
@@ -56,6 +56,8 @@ keyword arguments.
D sources referred to by this pkg-config file
- `uninstalled_variables` used instead of the `variables` keyword argument, when
generating the uninstalled pkg-config file. Since *0.54.0*
+- `dataonly` field. (*since 0.54.0*) this is used for architecture-independent
+ pkg-config files in projects which also have architecture-dependent outputs.
Since 0.46 a `StaticLibrary` or `SharedLibrary` object can optionally be passed
as first positional argument. If one is provided a default value will be
diff --git a/docs/markdown/Reference-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/interpreter.py b/mesonbuild/cmake/interpreter.py
index 41999ba..941baed 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -400,7 +400,19 @@ class ConverterTarget:
if not os.path.isabs(x):
x = os.path.normpath(os.path.join(self.src_dir, x))
if not os.path.exists(x) and not any([x.endswith(y) for y in obj_suffixes]) and not is_generated:
- mlog.warning('CMake: path', mlog.bold(x), 'does not exist. Ignoring. This can lead to build errors')
+ mlog.warning('CMake: path', mlog.bold(x), 'does not exist.')
+ mlog.warning(' --> Ignoring. This can lead to build errors.')
+ return None
+ if (
+ os.path.isabs(x)
+ and os.path.commonpath([x, self.env.get_source_dir()]) == self.env.get_source_dir()
+ and not (
+ os.path.commonpath([x, root_src_dir]) == root_src_dir or
+ os.path.commonpath([x, self.env.get_build_dir()]) == self.env.get_build_dir()
+ )
+ ):
+ mlog.warning('CMake: path', mlog.bold(x), 'is inside the root project but', mlog.bold('not'), 'inside the subproject.')
+ mlog.warning(' --> Ignoring. This can lead to build errors.')
return None
if os.path.isabs(x) and os.path.commonpath([x, self.env.get_build_dir()]) == self.env.get_build_dir():
if is_header:
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 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 720d064..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:
@@ -850,6 +854,9 @@ def read_cmd_line_file(build_dir, options):
# literal_eval to get it into the list of strings.
options.native_file = ast.literal_eval(properties.get('native_file', '[]'))
+def cmd_line_options_to_string(options):
+ return {k: str(v) for k, v in options.cmd_line_options.items()}
+
def write_cmd_line_file(build_dir, options):
filename = get_cmd_line_file(build_dir)
config = CmdLineFileParser()
@@ -860,7 +867,7 @@ def write_cmd_line_file(build_dir, options):
if options.native_file:
properties['native_file'] = options.native_file
- config['options'] = options.cmd_line_options
+ config['options'] = cmd_line_options_to_string(options)
config['properties'] = properties
with open(filename, 'w') as f:
config.write(f)
@@ -869,7 +876,7 @@ def update_cmd_line_file(build_dir, options):
filename = get_cmd_line_file(build_dir)
config = CmdLineFileParser()
config.read(filename)
- config['options'].update(options.cmd_line_options)
+ config['options'].update(cmd_line_options_to_string(options))
with open(filename, 'w') as f:
config.write(f)
@@ -1074,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/test cases/common/47 pkgconfig-gen/installed_files.txt b/test cases/common/47 pkgconfig-gen/installed_files.txt
index 94de704..9e1a40a 100644
--- a/test cases/common/47 pkgconfig-gen/installed_files.txt
+++ b/test cases/common/47 pkgconfig-gen/installed_files.txt
@@ -2,3 +2,4 @@ usr/include/simple.h
usr/lib/pkgconfig/simple.pc
usr/lib/pkgconfig/libfoo.pc
usr/lib/pkgconfig/libhello.pc
+usr/lib/pkgconfig/libhello_nolib.pc \ No newline at end of file
diff --git a/test cases/common/47 pkgconfig-gen/meson.build b/test cases/common/47 pkgconfig-gen/meson.build
index 09c46c5..c251b9f 100644
--- a/test cases/common/47 pkgconfig-gen/meson.build
+++ b/test cases/common/47 pkgconfig-gen/meson.build
@@ -51,3 +51,10 @@ pkgg.generate(
description : 'A minimalistic pkgconfig file.',
version : libver,
)
+
+pkgg.generate(
+ name : 'libhello_nolib',
+ description : 'A minimalistic pkgconfig file.',
+ version : libver,
+ dataonly: true
+)
diff --git a/test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp b/test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp
new file mode 100644
index 0000000..a5f09be
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/incDir/fileA.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+#define SOME_DEFINE " World"
diff --git a/test cases/failing build/4 cmake subproject isolation/main.cpp b/test cases/failing build/4 cmake subproject isolation/main.cpp
new file mode 100644
index 0000000..9507961
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/main.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+#include <cmMod.hpp>
+
+using namespace std;
+
+int main(void) {
+ cmModClass obj("Hello");
+ cout << obj.getStr() << endl;
+ return 0;
+}
diff --git a/test cases/failing build/4 cmake subproject isolation/meson.build b/test cases/failing build/4 cmake subproject isolation/meson.build
new file mode 100644
index 0000000..e606335
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/meson.build
@@ -0,0 +1,17 @@
+project('subproject isolation', ['c', 'cpp'])
+
+if not find_program('cmake', required: false).found()
+ error('MESON_SKIP_TEST CMake is not installed')
+endif
+
+incdir = meson.source_root() / 'incDir'
+
+cm = import('cmake')
+
+# This should generate a warning and the include dir should be skipped.
+sub_pro = cm.subproject('cmMod', cmake_options : [ '-DMESON_INC_DIR=' + incdir ])
+sub_dep = sub_pro.dependency('cmModLib++')
+
+# Since the include dir is skipped, the compilation of this project should fail.
+exe1 = executable('main', ['main.cpp'], dependencies: [sub_dep])
+test('test1', exe1)
diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt
new file mode 100644
index 0000000..852dd09
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(cmMod)
+set (CMAKE_CXX_STANDARD 14)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${MESON_INC_DIR})
+
+add_library(cmModLib++ SHARED cmMod.cpp)
+include(GenerateExportHeader)
+generate_export_header(cmModLib++)
diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp
new file mode 100644
index 0000000..a668203
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.cpp
@@ -0,0 +1,12 @@
+#include "cmMod.hpp"
+#include "fileA.hpp"
+
+using namespace std;
+
+cmModClass::cmModClass(string foo) {
+ str = foo + SOME_DEFINE;
+}
+
+string cmModClass::getStr() const {
+ return str;
+}
diff --git a/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp
new file mode 100644
index 0000000..0e6dc04
--- /dev/null
+++ b/test cases/failing build/4 cmake subproject isolation/subprojects/cmMod/cmMod.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "cmmodlib++_export.h"
+#include <string>
+
+class CMMODLIB___EXPORT cmModClass {
+private:
+ std::string str;
+
+public:
+ cmModClass(std::string foo);
+
+ std::string getStr() const;
+};