diff options
| author | Daniel Mensinger <daniel@mensinger-ka.de> | 2021-11-27 19:58:04 +0100 |
|---|---|---|
| committer | Jussi Pakkanen <jpakkane@gmail.com> | 2021-12-01 21:03:36 +0200 |
| commit | 45c5300496486ff9f1f3d47a01cdf19b8fa7e877 (patch) | |
| tree | 97f3c7c077df90cc60e83ee4e0bf85e5379f9a4e /mesonbuild/cmake/tracetargets.py | |
| parent | 4f882ff8ec81cbc42b097d3aee8ca4a8013f538b (diff) | |
| download | meson-45c5300496486ff9f1f3d47a01cdf19b8fa7e877.tar.gz | |
cmake: Fix old style dependency lookup with imported targets
This also includes some refactoring, since the alternaticve would
have been to duplicate the huge traceparser target code block again.
fixes #9581
Diffstat (limited to 'mesonbuild/cmake/tracetargets.py')
| -rw-r--r-- | mesonbuild/cmake/tracetargets.py | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/mesonbuild/cmake/tracetargets.py b/mesonbuild/cmake/tracetargets.py new file mode 100644 index 000000000..21aad8676 --- /dev/null +++ b/mesonbuild/cmake/tracetargets.py @@ -0,0 +1,117 @@ +# SPDX-License-Identifer: Apache-2.0 +# Copyright 2021 The Meson development team + +from .common import cmake_is_debug +from .. import mlog + +from pathlib import Path +import re +import typing as T + +if T.TYPE_CHECKING: + from .traceparser import CMakeTraceParser + from ..environment import Environment + from ..compilers import Compiler + +class ResolvedTarget: + def __init__(self) -> None: + self.include_directories: T.List[str] = [] + self.link_flags: T.List[str] = [] + self.public_compile_opts: T.List[str] = [] + self.libraries: T.List[str] = [] + +def resolve_cmake_trace_targets(target_name: str, + trace: 'CMakeTraceParser', + env: 'Environment', + *, + clib_compiler: T.Optional['Compiler'] = None, + not_found_warning: T.Callable[[str], None] = lambda x: None) -> ResolvedTarget: + res = ResolvedTarget() + targets = [target_name] + + # recognise arguments we should pass directly to the linker + reg_is_lib = re.compile(r'^(-l[a-zA-Z0-9_]+|-l?pthread)$') + reg_is_maybe_bare_lib = re.compile(r'^[a-zA-Z0-9_]+$') + + is_debug = cmake_is_debug(env) + + processed_targets: T.List[str] = [] + while len(targets) > 0: + curr = targets.pop(0) + + # Skip already processed targets + if curr in processed_targets: + continue + + if curr not in trace.targets: + if reg_is_lib.match(curr): + res.libraries += [curr] + elif Path(curr).is_absolute() and Path(curr).exists(): + res.libraries += [curr] + elif env.machines.build.is_windows() and reg_is_maybe_bare_lib.match(curr) and clib_compiler is not None: + # On Windows, CMake library dependencies can be passed as bare library names, + # CMake brute-forces a combination of prefix/suffix combinations to find the + # right library. Assume any bare argument passed which is not also a CMake + # target must be a system library we should try to link against. + res.libraries += clib_compiler.find_library(curr, env, []) + else: + not_found_warning(curr) + continue + + tgt = trace.targets[curr] + cfgs = [] + cfg = '' + mlog.debug(tgt) + + if 'INTERFACE_INCLUDE_DIRECTORIES' in tgt.properties: + res.include_directories += [x for x in tgt.properties['INTERFACE_INCLUDE_DIRECTORIES'] if x] + + if 'INTERFACE_LINK_OPTIONS' in tgt.properties: + res.link_flags += [x for x in tgt.properties['INTERFACE_LINK_OPTIONS'] if x] + + if 'INTERFACE_COMPILE_DEFINITIONS' in tgt.properties: + res.public_compile_opts += ['-D' + re.sub('^-D', '', x) for x in tgt.properties['INTERFACE_COMPILE_DEFINITIONS'] if x] + + if 'INTERFACE_COMPILE_OPTIONS' in tgt.properties: + res.public_compile_opts += [x for x in tgt.properties['INTERFACE_COMPILE_OPTIONS'] if x] + + if 'IMPORTED_CONFIGURATIONS' in tgt.properties: + cfgs = [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x] + cfg = cfgs[0] + + if is_debug: + if 'DEBUG' in cfgs: + cfg = 'DEBUG' + elif 'RELEASE' in cfgs: + cfg = 'RELEASE' + else: + if 'RELEASE' in cfgs: + cfg = 'RELEASE' + + if f'IMPORTED_IMPLIB_{cfg}' in tgt.properties: + res.libraries += [x for x in tgt.properties[f'IMPORTED_IMPLIB_{cfg}'] if x] + elif 'IMPORTED_IMPLIB' in tgt.properties: + res.libraries += [x for x in tgt.properties['IMPORTED_IMPLIB'] if x] + elif f'IMPORTED_LOCATION_{cfg}' in tgt.properties: + res.libraries += [x for x in tgt.properties[f'IMPORTED_LOCATION_{cfg}'] if x] + elif 'IMPORTED_LOCATION' in tgt.properties: + res.libraries += [x for x in tgt.properties['IMPORTED_LOCATION'] if x] + + if 'LINK_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['LINK_LIBRARIES'] if x] + if 'INTERFACE_LINK_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['INTERFACE_LINK_LIBRARIES'] if x] + + if f'IMPORTED_LINK_DEPENDENT_LIBRARIES_{cfg}' in tgt.properties: + targets += [x for x in tgt.properties[f'IMPORTED_LINK_DEPENDENT_LIBRARIES_{cfg}'] if x] + elif 'IMPORTED_LINK_DEPENDENT_LIBRARIES' in tgt.properties: + targets += [x for x in tgt.properties['IMPORTED_LINK_DEPENDENT_LIBRARIES'] if x] + + processed_targets += [curr] + + res.include_directories = sorted(set(res.include_directories)) + res.link_flags = sorted(set(res.link_flags)) + res.public_compile_opts = sorted(set(res.public_compile_opts)) + res.libraries = sorted(set(res.libraries)) + + return res |
