Merge pull request #6356 from dcbaker/fix-d-compiler-abstractions

Fix d compiler abstractions
pull/6772/head
Jussi Pakkanen 5 years ago committed by GitHub
commit 88e40c7081
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .travis.yml
  2. 39
      docs/markdown/Contributing.md
  3. 19
      mesonbuild/compilers/compilers.py
  4. 85
      mesonbuild/compilers/d.py
  5. 4
      mesonbuild/compilers/mixins/visualstudio.py
  6. 90
      mesonbuild/environment.py
  7. 15
      mesonbuild/linkers.py
  8. 79
      run_project_tests.py
  9. 3
      test cases/d/1 simple/test.json
  10. 1
      test cases/d/2 static library/test.json
  11. 20
      test cases/d/3 shared library/lld-test.py
  12. 7
      test cases/d/3 shared library/meson.build
  13. 14
      test cases/d/3 shared library/sub/libstuff.d
  14. 2
      test cases/d/3 shared library/sub/meson.build
  15. 6
      test cases/d/3 shared library/test.json
  16. 38
      test cases/d/4 library versions/test.json
  17. 8
      test cases/d/5 mixed/test.json
  18. 3
      test cases/d/6 unittest/test.json
  19. 23
      test cases/d/7 multilib/test.json

@ -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

@ -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:

@ -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

@ -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

@ -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']

@ -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)

@ -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)"""

@ -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)

@ -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"}
]
}

@ -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"}
]
}

@ -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()

@ -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

@ -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;
}

@ -0,0 +1,2 @@
ldyn = shared_library('stuff', 'libstuff.d', install : true)

@ -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"}
]
}

@ -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"}
]
}

@ -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"}
]
}

@ -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"}
]
}

@ -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"}
]
}

Loading…
Cancel
Save