aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--docs/markdown/Contributing.md39
-rw-r--r--mesonbuild/compilers/compilers.py19
-rw-r--r--mesonbuild/compilers/d.py85
-rw-r--r--mesonbuild/compilers/mixins/visualstudio.py4
-rw-r--r--mesonbuild/environment.py90
-rw-r--r--mesonbuild/linkers.py15
-rwxr-xr-xrun_project_tests.py79
-rw-r--r--test cases/d/1 simple/test.json3
-rw-r--r--test cases/d/2 static library/test.json1
-rw-r--r--test cases/d/3 shared library/lld-test.py20
-rw-r--r--test cases/d/3 shared library/meson.build7
-rw-r--r--test cases/d/3 shared library/sub/libstuff.d14
-rw-r--r--test cases/d/3 shared library/sub/meson.build2
-rw-r--r--test cases/d/3 shared library/test.json6
-rw-r--r--test cases/d/4 library versions/test.json38
-rw-r--r--test cases/d/5 mixed/test.json8
-rw-r--r--test cases/d/6 unittest/test.json3
-rw-r--r--test cases/d/7 multilib/test.json23
19 files changed, 325 insertions, 133 deletions
diff --git a/.travis.yml b/.travis.yml
index ed59a85..34303b4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -41,7 +41,7 @@ matrix:
before_install:
- python ./skip_ci.py --base-branch-env=TRAVIS_BRANCH --is-pull-env=TRAVIS_PULL_REQUEST
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install qt llvm ninja; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install qt ldc llvm ninja; fi
# # Run one macOS build without pkg-config available, and the other (unity=on) with pkg-config
- if [[ "$TRAVIS_OS_NAME" == "osx" && "$MESON_ARGS" =~ .*unity=on.* ]]; then brew install pkg-config; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull jpakkane/mesonci:eoan; fi
diff --git a/docs/markdown/Contributing.md b/docs/markdown/Contributing.md
index 26f3512..49b485b 100644
--- a/docs/markdown/Contributing.md
+++ b/docs/markdown/Contributing.md
@@ -190,6 +190,7 @@ Exanple `test.json`:
"installed": [
{ "type": "exe", "file": "usr/bin/testexe" },
{ "type": "pdb", "file": "usr/bin/testexe" },
+ { "type": "shared_lib", "file": "usr/lib/z", "version": "1.2.3" },
],
"matrix": {
"options": {
@@ -226,6 +227,8 @@ to be installed. Each dict contains the following keys:
- `file`
- `type`
- `platform` (optional)
+- `version` (optional)
+- `language` (optional)
The `file` entry contains the relative path (from the install root) to the
actually installed file.
@@ -233,17 +236,37 @@ actually installed file.
The `type` entry specifies how the `file` path should be interpreted based on the
current platform. The following values are currently supported:
-| `type` | Description |
-| :-----------: | -------------------------------------------------------------------------------- |
-| `file` | No postprocessing, just use the provided path |
-| `exe` | For executables. On Windows the `.exe` suffix is added to the path in `file` |
-| `pdb` | For Windows PDB files. PDB entries are ignored on non Windows platforms |
-| `implib` | For Windows import libraries. These entries are ignored on non Windows platforms |
-| `implibempty` | Like `implib`, but no symbols are exported in the library |
-| `expr` | `file` is an expression. This type should be avoided and removed if possible |
+| `type` | Description |
+| :-----------: | ------------------------------------------------------------------------------------------------------- |
+| `file` | No postprocessing, just use the provided path |
+| `exe` | For executables. On Windows the `.exe` suffix is added to the path in `file` |
+| `shared_lib` | For shared libraries, always written as `name`. The appropriate suffix and prefix are added by platform |
+| `pdb` | For Windows PDB files. PDB entries are ignored on non Windows platforms |
+| `implib` | For Windows import libraries. These entries are ignored on non Windows platforms |
+| `implibempty` | Like `implib`, but no symbols are exported in the library |
+| `expr` | `file` is an expression. This type should be avoided and removed if possible |
Except for the `file` and `expr` types, all paths should be provided *without* a suffix.
+| Argument | Applies to | Description |
+| :---------:|----------------------------|-------------------------------------------------------------------------------|
+| `version` | `shared_lib`, `pdb` | Sets the version to look for appropriately per-platform |
+| `language` | `pdb` | Determines which compiler/linker determines the existence of this file |
+
+The `shared_lib` and `pdb` types takes an optional additional parameter, `version`, this is us a string in `X.Y.Z` format that will be applied to the library. Each version to be tested must have a single version. The harness will apply this correctly per platform:
+
+`pdb` takes an optional `language` argument. This determines which compiler/linker should generate the pdb file. Because it's possible to mix compilers that do and don't generate pdb files (dmd's optlink doesn't). Currently this is only needed when mixing D and C code.
+
+```json
+{
+ "type": "shared_lib", "file": "usr/lib/lib",
+ "type": "shared_lib", "file": "usr/lib/lib", "version": "1",
+ "type": "shared_lib", "file": "usr/lib/lib", "version": "1.2.3.",
+}
+```
+
+This will be applied appropriatly per platform. On windows this expects `lib.dll` and `lib-1.dll`. on MacOS it expects `liblib.dylib` and `liblib.1.dylib`. On other Unices it expects `liblib.so`, `liblib.so.1`, and `liblib.so.1.2.3`.
+
If the `platform` key is present, the installed file entry is only considered if
the platform matches. The following values for `platform` are currently supported:
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 366bb50..e13256e 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -536,6 +536,15 @@ class CompilerArgs(collections.abc.MutableSequence):
# both of which are invalid.
if arg in cls.dedup2_prefixes:
return 0
+ if arg.startswith('-L='):
+ # DMD and LDC proxy all linker arguments using -L=; in conjunction
+ # with ld64 on macOS this can lead to command line arguments such
+ # as: `-L=-compatibility_version -L=0 -L=current_version -L=0`.
+ # These cannot be combined, ld64 insists they must be passed with
+ # spaces and quoting does not work. if we deduplicate these then
+ # one of the -L=0 arguments will be removed and the version
+ # argument will consume the next argument instead.
+ return 0
if arg in cls.dedup2_args or \
arg.startswith(cls.dedup2_prefixes) or \
arg.endswith(cls.dedup2_suffixes):
@@ -571,7 +580,17 @@ class CompilerArgs(collections.abc.MutableSequence):
isinstance(self.compiler.linker, (GnuLikeDynamicLinkerMixin, SolarisDynamicLinker))):
group_start = -1
group_end = -1
+ is_soname = False
for i, each in enumerate(new):
+ if is_soname:
+ is_soname = False
+ continue
+ elif '-soname' in each:
+ # To proxy these arguments with D you need to split the
+ # arguments, thus you get `-L=-soname -L=lib.so` we don't
+ # want to put the lib in a link -roup
+ is_soname = True
+ continue
if not each.startswith(('-Wl,-l', '-l')) and not each.endswith('.a') and \
not soregex.match(each):
continue
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index b974504..9a46a4e 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -28,7 +28,6 @@ from .compilers import (
CompilerArgs,
)
from .mixins.gnu import GnuCompiler
-from .mixins.islinker import LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin
if T.TYPE_CHECKING:
from ..envconfig import MachineInfo
@@ -69,7 +68,7 @@ dmd_optimization_args = {'0': [],
class DmdLikeCompilerMixin:
- LINKER_PREFIX = '-L'
+ LINKER_PREFIX = '-L='
def get_output_args(self, target):
return ['-of=' + target]
@@ -214,26 +213,30 @@ class DmdLikeCompilerMixin:
return []
def gen_import_library_args(self, implibname):
- return ['-Wl,--out-implib=' + implibname]
+ return self.linker.import_library_args(implibname)
def build_rpath_args(self, env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
if self.info.is_windows():
return []
- # This method is to be used by LDC and DMD.
- # GDC can deal with the verbatim flags.
- if not rpath_paths and not install_rpath:
- return []
- paths = ':'.join([os.path.join(build_dir, p) for p in rpath_paths])
- if build_rpath != '':
- paths += ':' + build_rpath
- if len(paths) < len(install_rpath):
- padding = 'X' * (len(install_rpath) - len(paths))
- if not paths:
- paths = padding
- else:
- paths = paths + ':' + padding
- return ['-Wl,-rpath,{}'.format(paths)]
+ # GNU ld, solaris ld, and lld acting like GNU ld
+ if self.linker.id.startswith('ld'):
+ # The way that dmd and ldc pass rpath to gcc is different than we would
+ # do directly, each argument -rpath and the value to rpath, need to be
+ # split into two separate arguments both prefaced with the -L=.
+ args = []
+ for r in super().build_rpath_args(
+ env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath):
+ if ',' in r:
+ a, b = r.split(',', maxsplit=1)
+ args.append(a)
+ args.append(self.LINKER_PREFIX + b)
+ else:
+ args.append(r)
+ return args
+
+ return super().build_rpath_args(
+ env, build_dir, from_dir, rpath_paths, build_rpath, install_rpath)
def translate_args_to_nongnu(self, args):
dcargs = []
@@ -391,15 +394,33 @@ class DmdLikeCompilerMixin:
def get_soname_args(self, *args, **kwargs) -> T.List[str]:
# LDC and DMD actually do use a linker, but they proxy all of that with
# their own arguments
- soargs = []
- for arg in Compiler.get_soname_args(self, *args, **kwargs):
- soargs.append('-L=' + arg)
- return soargs
+ if self.linker.id.startswith('ld.'):
+ soargs = []
+ for arg in super().get_soname_args(*args, **kwargs):
+ a, b = arg.split(',', maxsplit=1)
+ soargs.append(a)
+ soargs.append(self.LINKER_PREFIX + b)
+ return soargs
+ elif self.linker.id.startswith('ld64'):
+ soargs = []
+ for arg in super().get_soname_args(*args, **kwargs):
+ if not arg.startswith(self.LINKER_PREFIX):
+ soargs.append(self.LINKER_PREFIX + arg)
+ else:
+ soargs.append(arg)
+ return soargs
+ else:
+ return super().get_soname_args(*args, **kwargs)
def get_allow_undefined_link_args(self) -> T.List[str]:
- args = []
- for arg in self.linker.get_allow_undefined_args():
- args.append('-L=' + arg)
+ args = self.linker.get_allow_undefined_args()
+ if self.info.is_darwin():
+ # On macOS we're passing these options to the C compiler, but
+ # they're linker options and need -Wl, so clang/gcc knows what to
+ # do with them. I'm assuming, but don't know for certain, that
+ # ldc/dmd do some kind of mapping internally for arguments they
+ # understand, but pass arguments they don't understand directly.
+ args = [a.replace('-L=', '-Xcc=-Wl,') for a in args]
return args
@@ -600,7 +621,7 @@ class DCompiler(Compiler):
return []
def thread_link_flags(self, env):
- return ['-pthread']
+ return self.linker.thread_flags(env)
def name_string(self):
return ' '.join(self.exelist)
@@ -658,7 +679,7 @@ class GnuDCompiler(DCompiler, GnuCompiler):
return self.linker.get_allow_undefined_args()
-class LLVMDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin, DCompiler):
+class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
info: 'MachineInfo', arch, **kwargs):
@@ -687,9 +708,6 @@ class LLVMDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompi
def get_pic_args(self):
return ['-relocation-model=pic']
- def get_std_shared_lib_link_args(self):
- return ['-shared']
-
def get_crt_link_args(self, crt_val, buildtype):
return self.get_crt_args(crt_val, buildtype)
@@ -699,8 +717,12 @@ class LLVMDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompi
def get_optimization_args(self, optimization_level):
return ldc_optimization_args[optimization_level]
+ @classmethod
+ def use_linker_args(cls, linker: str) -> T.List[str]:
+ return ['-linker={}'.format(linker)]
+
-class DmdDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompilerMixin, DCompiler):
+class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
info: 'MachineInfo', arch, **kwargs):
@@ -760,3 +782,6 @@ class DmdDCompiler(DmdLikeCompilerMixin, LinkerEnvVarsMixin, BasicLinkerIsCompil
def get_optimization_args(self, optimization_level):
return dmd_optimization_args[optimization_level]
+
+ def can_linker_accept_rsp(self) -> bool:
+ return False
diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py
index a994379..44aefc8 100644
--- a/mesonbuild/compilers/mixins/visualstudio.py
+++ b/mesonbuild/compilers/mixins/visualstudio.py
@@ -205,10 +205,6 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
objname = os.path.splitext(pchname)[0] + '.obj'
return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname]
- def gen_import_library_args(self, implibname: str) -> T.List[str]:
- "The name of the outputted import library"
- return ['/IMPLIB:' + implibname]
-
def openmp_flags(self) -> T.List[str]:
return ['/openmp']
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index b995a59..f25c671 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -752,7 +752,8 @@ class Environment:
def _guess_win_linker(self, compiler: T.List[str], comp_class: Compiler,
for_machine: MachineChoice, *,
- use_linker_prefix: bool = True) -> 'DynamicLinker':
+ use_linker_prefix: bool = True, invoked_directly: bool = True,
+ extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker':
self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
# Explicitly pass logo here so that we can get the version of link.exe
@@ -771,25 +772,29 @@ class Environment:
override = comp_class.use_linker_args(value[0])
check_args += override
+ if extra_args is not None:
+ check_args.extend(extra_args)
+
p, o, _ = Popen_safe(compiler + check_args)
if o.startswith('LLD'):
if '(compatible with GNU linkers)' in o:
return LLVMDynamicLinker(
compiler, for_machine, comp_class.LINKER_PREFIX,
- override, version=search_version(o))
-
- if value is not None:
+ override, version=search_version(o), direct=invoked_directly)
+
+ if value is not None and invoked_directly:
compiler = value
+ # We've already hanedled the non-direct case above
p, o, e = Popen_safe(compiler + check_args)
if o.startswith('LLD'):
return ClangClDynamicLinker(
for_machine, [],
prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
- exelist=compiler, version=search_version(o))
+ exelist=compiler, version=search_version(o), direct=invoked_directly)
elif 'OPTLINK' in o:
# Opltink's stdout *may* beging with a \r character.
- return OptlinkDynamicLinker(for_machine, version=search_version(o))
+ return OptlinkDynamicLinker(compiler, for_machine, version=search_version(o))
elif o.startswith('Microsoft') or e.startswith('Microsoft'):
out = o or e
match = re.search(r'.*(X86|X64|ARM|ARM64).*', out)
@@ -801,7 +806,7 @@ class Environment:
return MSVCDynamicLinker(
for_machine, [], machine=target, exelist=compiler,
prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [],
- version=search_version(out))
+ version=search_version(out), direct=invoked_directly)
elif 'GNU coreutils' in o:
raise EnvironmentException(
"Found GNU link.exe instead of MSVC link.exe. This link.exe "
@@ -1496,28 +1501,31 @@ class Environment:
if 'LLVM D compiler' in out:
# LDC seems to require a file
- if info.is_windows() or info.is_cygwin():
- # Getting LDC on windows to give useful linker output when
- # not doing real work is painfully hard. It ships with a
- # version of lld-link, so unless we think the user wants
- # link.exe, just assume that we're going to use lld-link
- # with it.
- linker = self._guess_win_linker(
- ['link' if is_msvc else 'lld-link'],
- compilers.LLVMDCompiler, for_machine, use_linker_prefix=False)
- else:
- with tempfile.NamedTemporaryFile(suffix='.d') as f:
+ # We cannot use NamedTemproraryFile on windows, its documented
+ # to not work for our uses. So, just use mkstemp and only have
+ # one path for simplicity.
+ o, f = tempfile.mkstemp('.d')
+ os.close(o)
+
+ try:
+ if info.is_windows() or info.is_cygwin():
+ objfile = os.path.basename(f)[:-1] + 'obj'
+ linker = self._guess_win_linker(
+ exelist,
+ compilers.LLVMDCompiler, for_machine,
+ use_linker_prefix=True, invoked_directly=False,
+ extra_args=[f])
+ else:
# LDC writes an object file to the current working directory.
# Clean it up.
- objectfile = os.path.basename(f.name)[:-1] + 'o'
+ objfile = os.path.basename(f)[:-1] + 'o'
linker = self._guess_nix_linker(
exelist, compilers.LLVMDCompiler, for_machine,
- extra_args=[f.name])
- try:
- os.unlink(objectfile)
- except Exception:
- # Thank you Windows file system semantics and virus scanners.
- pass
+ extra_args=[f])
+ finally:
+ mesonlib.windows_proof_rm(f)
+ mesonlib.windows_proof_rm(objfile)
+
return compilers.LLVMDCompiler(
exelist, version, for_machine, info, arch,
full_version=full_version, linker=linker)
@@ -1528,20 +1536,30 @@ class Environment:
full_version=full_version, linker=linker)
elif 'The D Language Foundation' in out or 'Digital Mars' in out:
# DMD seems to require a file
- if info.is_windows() or info.is_cygwin():
- if is_msvc:
- linker_cmd = ['link']
- elif arch == 'x86':
- linker_cmd = ['optlink']
+ # We cannot use NamedTemproraryFile on windows, its documented
+ # to not work for our uses. So, just use mkstemp and only have
+ # one path for simplicity.
+ o, f = tempfile.mkstemp('.d')
+ os.close(o)
+
+ # DMD as different detection logic for x86 and x86_64
+ arch_arg = '-m64' if arch == 'x86_64' else '-m32'
+
+ try:
+ if info.is_windows() or info.is_cygwin():
+ objfile = os.path.basename(f)[:-1] + 'obj'
+ linker = self._guess_win_linker(
+ exelist, compilers.DmdDCompiler, for_machine,
+ invoked_directly=False, extra_args=[f, arch_arg])
else:
- linker_cmd = ['lld-link']
- linker = self._guess_win_linker(linker_cmd, compilers.DmdDCompiler, for_machine,
- use_linker_prefix=False)
- else:
- with tempfile.NamedTemporaryFile(suffix='.d') as f:
+ objfile = os.path.basename(f)[:-1] + 'o'
linker = self._guess_nix_linker(
exelist, compilers.DmdDCompiler, for_machine,
- extra_args=[f.name])
+ extra_args=[f, arch_arg])
+ finally:
+ mesonlib.windows_proof_rm(f)
+ mesonlib.windows_proof_rm(objfile)
+
return compilers.DmdDCompiler(
exelist, version, for_machine, info, arch,
full_version=full_version, linker=linker)
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index 73cdeef..e4fffe3 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -901,6 +901,10 @@ class VisualStudioLikeLinkerMixin:
is_shared_module: bool) -> T.List[str]:
return []
+ def import_library_args(self, implibname: str) -> T.List[str]:
+ """The command to generate the import library."""
+ return self._apply_prefix(['/IMPLIB:' + implibname])
+
class MSVCDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
@@ -993,15 +997,22 @@ class OptlinkDynamicLinker(VisualStudioLikeLinkerMixin, DynamicLinker):
"""Digital Mars dynamic linker for windows."""
- def __init__(self, for_machine: mesonlib.MachineChoice,
+ def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
# Use optlink instead of link so we don't interfer with other link.exe
# implementations.
- super().__init__('optlink', ['optlink.exe'], for_machine, '', [], version=version)
+ super().__init__('optlink', exelist, for_machine, '', [], version=version)
def get_allow_undefined_args(self) -> T.List[str]:
return []
+ def get_debugfile_args(self, targetfile: str) -> T.List[str]:
+ # Optlink does not generate pdb files.
+ return []
+
+ def get_always_args(self) -> T.List[str]:
+ return []
+
class CudaLinker(PosixDynamicLinkerMixin, DynamicLinker):
"""Cuda linker (nvlink)"""
diff --git a/run_project_tests.py b/run_project_tests.py
index 86db599..3b20025 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -14,19 +14,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import typing as T
+from concurrent.futures import ProcessPoolExecutor, CancelledError
+from enum import Enum
+from io import StringIO
+from pathlib import Path, PurePath
+import argparse
import functools
import itertools
+import json
+import multiprocessing
import os
-import subprocess
+import re
+import shlex
import shutil
-import sys
import signal
-import shlex
-from io import StringIO
-from enum import Enum
+import subprocess
+import sys
import tempfile
-from pathlib import Path, PurePath
+import time
+import typing as T
+import xml.etree.ElementTree as ET
+
from mesonbuild import build
from mesonbuild import environment
from mesonbuild import compilers
@@ -35,13 +43,7 @@ from mesonbuild import mlog
from mesonbuild import mtest
from mesonbuild.mesonlib import MachineChoice, Popen_safe
from mesonbuild.coredata import backendlist
-import argparse
-import json
-import xml.etree.ElementTree as ET
-import time
-import multiprocessing
-from concurrent.futures import ProcessPoolExecutor, CancelledError
-import re
+
from run_tests import get_fake_options, run_configure, get_meson_script
from run_tests import get_backend_commands, get_backend_args_for_dir, Backend
from run_tests import ensure_backend_detects_changes
@@ -94,13 +96,29 @@ class InstalledFile:
self.path = raw['file']
self.typ = raw['type']
self.platform = raw.get('platform', None)
+ self.language = raw.get('language', 'c') # type: str
+
+ version = raw.get('version', '') # type: str
+ if version:
+ self.version = version.split('.') # type: T.List[str]
+ else:
+ # split on '' will return [''], we want an empty list though
+ self.version = []
def get_path(self, compiler: str, env: environment.Environment) -> T.Optional[Path]:
p = Path(self.path)
canonical_compiler = compiler
- if (compiler in ['clang-cl', 'intel-cl']) or (env.machines.host.is_windows() and compiler == 'pgi'):
+ if ((compiler in ['clang-cl', 'intel-cl']) or
+ (env.machines.host.is_windows() and compiler in {'pgi', 'dmd', 'ldc'})):
canonical_compiler = 'msvc'
+ has_pdb = False
+ if self.language in {'c', 'cpp'}:
+ has_pdb = canonical_compiler == 'msvc'
+ elif self.language == 'd':
+ # dmd's optlink does not genearte pdb iles
+ has_pdb = env.coredata.compilers.host['d'].linker.id in {'link', 'lld-link'}
+
# Abort if the platform does not match
matches = {
'msvc': canonical_compiler == 'msvc',
@@ -114,11 +132,38 @@ class InstalledFile:
# Handle the different types
if self.typ == 'file':
return p
+ elif self.typ == 'shared_lib':
+ if env.machines.host.is_windows() or env.machines.host.is_cygwin():
+ # Windows only has foo.dll and foo-X.dll
+ if len(self.version) > 1:
+ return None
+ if self.version:
+ p = p.with_name('{}-{}'.format(p.name, self.version[0]))
+ return p.with_suffix('.dll')
+
+ p = p.with_name('lib{}'.format(p.name))
+ if env.machines.host.is_darwin():
+ # MacOS only has libfoo.dylib and libfoo.X.dylib
+ if len(self.version) > 1:
+ return None
+
+ # pathlib.Path.with_suffix replaces, not appends
+ suffix = '.dylib'
+ if self.version:
+ suffix = '.{}{}'.format(self.version[0], suffix)
+ else:
+ # pathlib.Path.with_suffix replaces, not appends
+ suffix = '.so'
+ if self.version:
+ suffix = '{}.{}'.format(suffix, '.'.join(self.version))
+ return p.with_suffix(suffix)
elif self.typ == 'exe':
if env.machines.host.is_windows() or env.machines.host.is_cygwin():
return p.with_suffix('.exe')
elif self.typ == 'pdb':
- return p.with_suffix('.pdb') if canonical_compiler == 'msvc' else None
+ if self.version:
+ p = p.with_name('{}-{}'.format(p.name, self.version[0]))
+ return p.with_suffix('.pdb') if has_pdb else None
elif self.typ == 'implib' or self.typ == 'implibempty':
if env.machines.host.is_windows() and canonical_compiler == 'msvc':
# only MSVC doesn't generate empty implibs
@@ -208,7 +253,7 @@ def setup_commands(optbackend):
uninstall_commands = get_backend_commands(backend, do_debug)
# TODO try to eliminate or at least reduce this function
-def platform_fix_name(fname: str, canonical_compiler: str, env: environment.EnvironmentException) -> str:
+def platform_fix_name(fname: str, canonical_compiler: str, env: environment.Environment) -> str:
if '?lib' in fname:
if env.machines.host.is_windows() and canonical_compiler == 'msvc':
fname = re.sub(r'lib/\?lib(.*)\.', r'bin/\1.', fname)
diff --git a/test cases/d/1 simple/test.json b/test cases/d/1 simple/test.json
index 7ec2783..62f907a 100644
--- a/test cases/d/1 simple/test.json
+++ b/test cases/d/1 simple/test.json
@@ -1,5 +1,6 @@
{
"installed": [
- {"type": "exe", "file": "usr/bin/dsimpleapp"}
+ {"type": "exe", "file": "usr/bin/dsimpleapp"},
+ {"type": "pdb", "file": "usr/bin/dsimpleapp", "language": "d"}
]
}
diff --git a/test cases/d/2 static library/test.json b/test cases/d/2 static library/test.json
index 50d5cdf..6abb934 100644
--- a/test cases/d/2 static library/test.json
+++ b/test cases/d/2 static library/test.json
@@ -1,6 +1,7 @@
{
"installed": [
{"type": "exe", "file": "usr/bin/app_s"},
+ {"type": "pdb", "file": "usr/bin/app_s", "language": "d"},
{"type": "file", "file": "usr/lib/libstuff.a"}
]
}
diff --git a/test cases/d/3 shared library/lld-test.py b/test cases/d/3 shared library/lld-test.py
new file mode 100644
index 0000000..3f32f59
--- /dev/null
+++ b/test cases/d/3 shared library/lld-test.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+
+import argparse
+import subprocess
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('ldd')
+ parser.add_argument('bin')
+ args = parser.parse_args()
+
+ p, o, _ = subprocess.run([args.ldd, args.bin], stdout=subprocess.PIPE)
+ assert p == 0
+ o = o.decode()
+ assert 'libstuff.so =>' in o, 'libstuff so not in linker path.'
+ assert 'libstuff.so => not found' not in o, 'libstuff.so not found correctly'
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test cases/d/3 shared library/meson.build b/test cases/d/3 shared library/meson.build
index b37b700..fa41779 100644
--- a/test cases/d/3 shared library/meson.build
+++ b/test cases/d/3 shared library/meson.build
@@ -7,7 +7,7 @@ if dc.get_id() == 'gcc'
endif
endif
-ldyn = shared_library('stuff', 'libstuff.d', install : true)
+subdir('sub')
ed = executable('app_d', 'app.d', link_with : ldyn, install : true)
test('linktest_dyn', ed)
@@ -19,3 +19,8 @@ pkgc.generate(name: 'test',
description: 'A test of D attributes to pkgconfig.generate.',
d_module_versions: ['Use_Static']
)
+
+ldd = find_program('ldd', required : false)
+if ldd.found()
+ test('ldd-test.py', ed)
+endif
diff --git a/test cases/d/3 shared library/sub/libstuff.d b/test cases/d/3 shared library/sub/libstuff.d
new file mode 100644
index 0000000..8205490
--- /dev/null
+++ b/test cases/d/3 shared library/sub/libstuff.d
@@ -0,0 +1,14 @@
+import std.stdio;
+import std.string : format;
+
+export int printLibraryString (string str)
+{
+ writeln ("Library says: %s".format (str));
+ return 4;
+}
+
+version (Windows)
+{
+ import core.sys.windows.dll;
+ mixin SimpleDllMain;
+}
diff --git a/test cases/d/3 shared library/sub/meson.build b/test cases/d/3 shared library/sub/meson.build
new file mode 100644
index 0000000..fb4b996
--- /dev/null
+++ b/test cases/d/3 shared library/sub/meson.build
@@ -0,0 +1,2 @@
+ldyn = shared_library('stuff', 'libstuff.d', install : true)
+
diff --git a/test cases/d/3 shared library/test.json b/test cases/d/3 shared library/test.json
index 66c546b..50eb9cb 100644
--- a/test cases/d/3 shared library/test.json
+++ b/test cases/d/3 shared library/test.json
@@ -1,9 +1,11 @@
{
"installed": [
{"type": "exe", "file": "usr/bin/app_d"},
- {"type": "file", "platform": "msvc", "file": "usr/bin/stuff.dll"},
+ {"type": "pdb", "file": "usr/bin/app_d", "language": "d"},
+ {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/stuff"},
+ {"type": "pdb", "file": "usr/bin/stuff", "language": "d"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/stuff"},
{"type": "file", "platform": "msvc", "file": "usr/lib/stuff.lib"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff.so"},
{"type": "file", "file": "usr/lib/pkgconfig/test.pc"}
]
}
diff --git a/test cases/d/4 library versions/test.json b/test cases/d/4 library versions/test.json
index 2a3433e..23c95dd 100644
--- a/test cases/d/4 library versions/test.json
+++ b/test cases/d/4 library versions/test.json
@@ -1,21 +1,25 @@
{
"installed": [
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsome.so"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsome.so.0"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsome.so.1.2.3"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libnoversion.so"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libonlyversion.so"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libonlyversion.so.1"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libonlyversion.so.1.4.5"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libonlysoversion.so"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libonlysoversion.so.5"},
- {"type": "file", "platform": "msvc", "file": "usr/bin/noversion.dll"},
- {"type": "file", "platform": "msvc", "file": "usr/bin/onlysoversion-5.dll"},
- {"type": "file", "platform": "msvc", "file": "usr/bin/onlyversion-1.dll"},
- {"type": "file", "platform": "msvc", "file": "usr/bin/some-0.dll"},
- {"type": "file", "platform": "msvc", "file": "usr/lib/noversion.lib"},
- {"type": "file", "platform": "msvc", "file": "usr/lib/onlysoversion.lib"},
- {"type": "file", "platform": "msvc", "file": "usr/lib/onlyversion.lib"},
- {"type": "file", "platform": "msvc", "file": "usr/lib/some.lib"}
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/some"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/some", "version": "0"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/some", "version": "1.2.3"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/noversion"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlyversion"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlyversion", "version": "1"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlyversion", "version": "1.4.5"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlysoversion"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/onlysoversion", "version": "5"},
+ {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/noversion"},
+ {"type": "pdb", "file": "usr/bin/noversion", "language": "d"},
+ {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/onlysoversion", "version": "5"},
+ {"type": "pdb", "file": "usr/bin/onlysoversion", "version": "5", "language": "d"},
+ {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/onlyversion", "version": "1"},
+ {"type": "pdb", "file": "usr/bin/onlyversion", "version": "1", "language": "d"},
+ {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/some", "version": "0"},
+ {"type": "pdb", "file": "usr/bin/some", "version": "0", "language": "d"},
+ {"type": "implib", "file": "usr/lib/noversion"},
+ {"type": "implib", "file": "usr/lib/onlysoversion"},
+ {"type": "implib", "file": "usr/lib/onlyversion"},
+ {"type": "implib", "file": "usr/lib/some"}
]
}
diff --git a/test cases/d/5 mixed/test.json b/test cases/d/5 mixed/test.json
index a63a19b..c95d0ca 100644
--- a/test cases/d/5 mixed/test.json
+++ b/test cases/d/5 mixed/test.json
@@ -1,11 +1,13 @@
{
"installed": [
{"type": "exe", "file": "usr/bin/appdc_d"},
+ {"type": "pdb", "file": "usr/bin/appdc_d", "language": "d"},
{"type": "exe", "file": "usr/bin/appdc_s"},
+ {"type": "pdb", "file": "usr/bin/appdc_s", "language": "d"},
{"type": "file", "file": "usr/lib/libstuff.a"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libstuff.so"},
- {"type": "file", "platform": "msvc", "file": "usr/bin/stuff.dll"},
- {"type": "pdb", "file": "usr/bin/stuff"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/stuff"},
+ {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/stuff"},
+ {"type": "pdb", "file": "usr/bin/stuff", "language": "c"},
{"type": "file", "platform": "msvc", "file": "usr/lib/stuff.lib"}
]
}
diff --git a/test cases/d/6 unittest/test.json b/test cases/d/6 unittest/test.json
index 433e4b0..adc4d75 100644
--- a/test cases/d/6 unittest/test.json
+++ b/test cases/d/6 unittest/test.json
@@ -1,5 +1,6 @@
{
"installed": [
- {"type": "exe", "file": "usr/bin/dapp"}
+ {"type": "exe", "file": "usr/bin/dapp"},
+ {"type": "pdb", "file": "usr/bin/dapp", "language": "d"}
]
}
diff --git a/test cases/d/7 multilib/test.json b/test cases/d/7 multilib/test.json
index 408c4f2..5944ae0 100644
--- a/test cases/d/7 multilib/test.json
+++ b/test cases/d/7 multilib/test.json
@@ -1,15 +1,18 @@
{
"installed": [
{"type": "exe", "file": "usr/bin/app_d"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsay1.so"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsay1.so.0"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsay1.so.1.2.3"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsay2.so"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsay2.so.1"},
- {"type": "file", "platform": "gcc", "file": "usr/lib/libsay2.so.1.2.4"},
- {"type": "file", "platform": "msvc", "file": "usr/bin/say1-0.dll"},
- {"type": "file", "platform": "msvc", "file": "usr/bin/say2-1.dll"},
- {"type": "file", "platform": "msvc", "file": "usr/lib/say1.lib"},
- {"type": "file", "platform": "msvc", "file": "usr/lib/say2.lib"}
+ {"type": "pdb", "file": "usr/bin/app_d", "language": "d"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say1"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say1", "version": "0"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say1", "version": "1.2.3"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say2"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say2", "version": "1"},
+ {"type": "shared_lib", "platform": "gcc", "file": "usr/lib/say2", "version": "1.2.4"},
+ {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/say1", "version": "0"},
+ {"type": "pdb", "file": "usr/bin/say1", "version": "0", "language": "d"},
+ {"type": "shared_lib", "platform": "msvc", "file": "usr/bin/say2", "version": "1"},
+ {"type": "pdb", "file": "usr/bin/say2", "version": "1", "language": "d"},
+ {"type": "implib", "file": "usr/lib/say1"},
+ {"type": "implib", "file": "usr/lib/say2"}
]
}