diff options
| author | L. E. Segovia <amy@amyspark.me> | 2023-08-30 20:16:08 -0300 |
|---|---|---|
| committer | Jussi Pakkanen <jpakkane@gmail.com> | 2024-02-25 01:59:39 +0200 |
| commit | 05f4e0d6c5e74d5dfc1f1b32ac2ee26af664c950 (patch) | |
| tree | 63966dfb09d0b2ea8e6270ec3602575db2a6d6d6 | |
| parent | 6a119256a1b87f22a6afe59b494ac50e52e24f07 (diff) | |
| download | meson-05f4e0d6c5e74d5dfc1f1b32ac2ee26af664c950.tar.gz | |
cmake: Allow recasting a CMake dependency into an Apple framework
Fixes #12160
| -rw-r--r-- | mesonbuild/cmake/tracetargets.py | 50 | ||||
| -rw-r--r-- | mesonbuild/dependencies/framework.py | 2 | ||||
| -rw-r--r-- | test cases/osx/9 framework recasting/main.cpp | 1 | ||||
| -rw-r--r-- | test cases/osx/9 framework recasting/meson.build | 5 |
4 files changed, 51 insertions, 7 deletions
diff --git a/mesonbuild/cmake/tracetargets.py b/mesonbuild/cmake/tracetargets.py index 69d88a88c..aee67ea59 100644 --- a/mesonbuild/cmake/tracetargets.py +++ b/mesonbuild/cmake/tracetargets.py @@ -4,6 +4,7 @@ from __future__ import annotations from .common import cmake_is_debug from .. import mlog +from ..mesonlib import Version from pathlib import Path import re @@ -15,6 +16,28 @@ if T.TYPE_CHECKING: from ..compilers import Compiler from ..dependencies import MissingCompiler +# Small duplication of ExtraFramework to parse full +# framework paths as exposed by CMake +def _get_framework_latest_version(path: Path) -> str: + versions: list[Version] = [] + for each in path.glob('Versions/*'): + # macOS filesystems are usually case-insensitive + if each.name.lower() == 'current': + continue + versions.append(Version(each.name)) + if len(versions) == 0: + # most system frameworks do not have a 'Versions' directory + return 'Headers' + return 'Versions/{}/Headers'.format(sorted(versions)[-1]._s) + +def _get_framework_include_path(path: Path) -> T.Optional[str]: + trials = ('Headers', 'Versions/Current/Headers', _get_framework_latest_version(path)) + for each in trials: + trial = path / each + if trial.is_dir(): + return trial.as_posix() + return None + class ResolvedTarget: def __init__(self) -> None: self.include_directories: T.List[str] = [] @@ -46,10 +69,25 @@ def resolve_cmake_trace_targets(target_name: str, continue if curr not in trace.targets: + curr_path = Path(curr) if reg_is_lib.match(curr): res.libraries += [curr] - elif Path(curr).is_absolute() and Path(curr).exists(): - res.libraries += [curr] + elif curr_path.is_absolute() and curr_path.exists(): + if any(x.endswith('.framework') for x in curr_path.parts): + # Frameworks detected by CMake are passed as absolute paths + # Split into -F/path/to/ and -framework name + path_to_framework = [] + # Try to slice off the `Versions/X/name.tbd` + for x in curr_path.parts: + path_to_framework.append(x) + if x.endswith('.framework'): + break + curr_path = Path(*path_to_framework) + framework_path = curr_path.parent + framework_name = curr_path.stem + res.libraries += [f'-F{framework_path}', '-framework', framework_name] + else: + res.libraries += [curr] elif reg_is_maybe_bare_lib.match(curr) and clib_compiler: # CMake library dependencies can be passed as bare library names, # CMake brute-forces a combination of prefix/suffix combinations to find the @@ -115,9 +153,9 @@ def resolve_cmake_trace_targets(target_name: str, 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)) + # Do not sort flags here -- this breaks + # semantics of eg. `-framework CoreAudio` + # or `-Lpath/to/root -llibrary` + # see eg. #11113 return res diff --git a/mesonbuild/dependencies/framework.py b/mesonbuild/dependencies/framework.py index cd53ff718..3c880c743 100644 --- a/mesonbuild/dependencies/framework.py +++ b/mesonbuild/dependencies/framework.py @@ -79,7 +79,7 @@ class ExtraFrameworkDependency(ExternalDependency): return None def _get_framework_latest_version(self, path: Path) -> str: - versions = [] + versions: T.List[Version] = [] for each in path.glob('Versions/*'): # macOS filesystems are usually case-insensitive if each.name.lower() == 'current': diff --git a/test cases/osx/9 framework recasting/main.cpp b/test cases/osx/9 framework recasting/main.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/test cases/osx/9 framework recasting/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/test cases/osx/9 framework recasting/meson.build b/test cases/osx/9 framework recasting/meson.build new file mode 100644 index 000000000..f139485ac --- /dev/null +++ b/test cases/osx/9 framework recasting/meson.build @@ -0,0 +1,5 @@ +project('framework recasting', 'c', 'cpp') + +x = dependency('openal') + +y = executable('tt', files('main.cpp'), dependencies: x) |
