aboutsummaryrefslogtreecommitdiffstats
path: root/meson/mesonbuild/dependencies/__init__.py
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /meson/mesonbuild/dependencies/__init__.py
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'meson/mesonbuild/dependencies/__init__.py')
-rw-r--r--meson/mesonbuild/dependencies/__init__.py275
1 files changed, 275 insertions, 0 deletions
diff --git a/meson/mesonbuild/dependencies/__init__.py b/meson/mesonbuild/dependencies/__init__.py
new file mode 100644
index 000000000..bd90c90e9
--- /dev/null
+++ b/meson/mesonbuild/dependencies/__init__.py
@@ -0,0 +1,275 @@
+# Copyright 2017 The Meson development team
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from .boost import BoostDependency
+from .cuda import CudaDependency
+from .hdf5 import hdf5_factory
+from .base import Dependency, InternalDependency, ExternalDependency, NotFoundDependency
+from .base import (
+ ExternalLibrary, DependencyException, DependencyMethods,
+ BuiltinDependency, SystemDependency)
+from .cmake import CMakeDependency
+from .configtool import ConfigToolDependency
+from .dub import DubDependency
+from .framework import ExtraFrameworkDependency
+from .pkgconfig import PkgConfigDependency
+from .factory import DependencyFactory
+from .detect import find_external_dependency, get_dep_identifier, packages, _packages_accept_language
+from .dev import (
+ ValgrindDependency, JDKSystemDependency, gmock_factory, gtest_factory,
+ llvm_factory, zlib_factory)
+from .coarrays import coarray_factory
+from .mpi import mpi_factory
+from .scalapack import scalapack_factory
+from .misc import (
+ BlocksDependency, OpenMPDependency, cups_factory, curses_factory, gpgme_factory,
+ libgcrypt_factory, libwmf_factory, netcdf_factory, pcap_factory, python3_factory,
+ shaderc_factory, threads_factory, ThreadDependency, intl_factory,
+)
+from .platform import AppleFrameworks
+from .qt import qt4_factory, qt5_factory, qt6_factory
+from .ui import GnuStepDependency, WxDependency, gl_factory, sdl2_factory, vulkan_factory
+
+__all__ = [
+ 'Dependency',
+ 'InternalDependency',
+ 'ExternalDependency',
+ 'SystemDependency',
+ 'BuiltinDependency',
+ 'NotFoundDependency',
+ 'ExternalLibrary',
+ 'DependencyException',
+ 'DependencyMethods',
+
+ 'CMakeDependency',
+ 'ConfigToolDependency',
+ 'DubDependency',
+ 'ExtraFrameworkDependency',
+ 'PkgConfigDependency',
+
+ 'DependencyFactory',
+
+ 'ThreadDependency',
+
+ 'find_external_dependency',
+ 'get_dep_identifier',
+]
+
+"""Dependency representations and discovery logic.
+
+Meson attempts to largely abstract away dependency discovery information, and
+to encapsulate that logic itself so that the DSL doesn't have too much direct
+information. There are some cases where this is impossible/undesirable, such
+as the `get_variable()` method.
+
+Meson has four primary dependency types:
+ 1. pkg-config
+ 2. apple frameworks
+ 3. CMake
+ 4. system
+
+Plus a few more niche ones.
+
+When a user calls `dependency('foo')` Meson creates a list of candidates, and
+tries those candidates in order to find one that matches the criteria
+provided by the user (such as version requirements, or optional components
+that are required.)
+
+Except to work around bugs or handle odd corner cases, pkg-config and CMake
+generally just work™, though there are exceptions. Most of this package is
+concerned with dependencies that don't (always) provide CMake and/or
+pkg-config files.
+
+For these cases one needs to write a `system` dependency. These dependencies
+descend directly from `ExternalDependency`, in their constructor they
+manually set up the necessary link and compile args (and additional
+dependencies as necessary).
+
+For example, imagine a dependency called Foo, it uses an environment variable
+called `$FOO_ROOT` to point to its install root, which looks like this:
+```txt
+$FOOROOT
+→ include/
+→ lib/
+```
+To use Foo, you need its include directory, and you need to link to
+`lib/libfoo.ext`.
+
+You could write code that looks like:
+
+```python
+class FooSystemDependency(ExternalDependency):
+
+ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+ super().__init__(name, environment, kwargs)
+ root = os.environ.get('FOO_ROOT')
+ if root is None:
+ mlog.debug('$FOO_ROOT is unset.')
+ self.is_found = False
+ return
+
+ lib = self.clib_compiler.find_library('foo', environment, [os.path.join(root, 'lib')])
+ if lib is None:
+ mlog.debug('Could not find lib.')
+ self.is_found = False
+ return
+
+ self.compile_args.append(f'-I{os.path.join(root, "include")}')
+ self.link_args.append(lib)
+ self.is_found = True
+```
+
+This code will look for `FOO_ROOT` in the environment, handle `FOO_ROOT` being
+undefined gracefully, then set its `compile_args` and `link_args` gracefully.
+It will also gracefully handle not finding the required lib (hopefully that
+doesn't happen, but it could if, for example, the lib is only static and
+shared linking is requested).
+
+There are a couple of things about this that still aren't ideal. For one, we
+don't want to be reading random environment variables at this point. Those
+should actually be added to `envconfig.Properties` and read in
+`environment.Environment._set_default_properties_from_env` (see how
+`BOOST_ROOT` is handled). We can also handle the `static` keyword. So
+now that becomes:
+
+```python
+class FooSystemDependency(ExternalDependency):
+
+ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]):
+ super().__init__(name, environment, kwargs)
+ root = environment.properties[self.for_machine].foo_root
+ if root is None:
+ mlog.debug('foo_root is unset.')
+ self.is_found = False
+ return
+
+ static = Mesonlib.LibType.STATIC if kwargs.get('static', False) else Mesonlib.LibType.SHARED
+ lib = self.clib_compiler.find_library(
+ 'foo', environment, [os.path.join(root, 'lib')], libtype=static)
+ if lib is None:
+ mlog.debug('Could not find lib.')
+ self.is_found = False
+ return
+
+ self.compile_args.append(f'-I{os.path.join(root, "include")}')
+ self.link_args.append(lib)
+ self.is_found = True
+```
+
+This is nicer in a couple of ways. First we can properly cross compile as we
+are allowed to set `FOO_ROOT` for both the build and host machines, it also
+means that users can override this in their machine files, and if that
+environment variables changes during a Meson reconfigure Meson won't re-read
+it, this is important for reproducibility. Finally, Meson will figure out
+whether it should be finding `libfoo.so` or `libfoo.a` (or the platform
+specific names). Things are looking pretty good now, so it can be added to
+the `packages` dict below:
+
+```python
+packages.update({
+ 'foo': FooSystemDependency,
+})
+```
+
+Now, what if foo also provides pkg-config, but it's only shipped on Unices,
+or only included in very recent versions of the dependency? We can use the
+`DependencyFactory` class:
+
+```python
+foo_factory = DependencyFactory(
+ 'foo',
+ [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM],
+ system_class=FooSystemDependency,
+)
+```
+
+This is a helper function that will generate a default pkg-config based
+dependency, and use the `FooSystemDependency` as well. It can also handle
+custom finders for pkg-config and cmake based dependencies that need some
+extra help. You would then add the `foo_factory` to packages instead of
+`FooSystemDependency`:
+
+```python
+packages.update({
+ 'foo': foo_factory,
+})
+```
+
+If you have a dependency that is very complicated, (such as having multiple
+implementations) you may need to write your own factory function. There are a
+number of examples in this package.
+
+_Note_ before we moved to factory functions it was common to use an
+`ExternalDependency` class that would instantiate different types of
+dependencies and hold the one it found. There are a number of drawbacks to
+this approach, and no new dependencies should do this.
+"""
+
+# This is a dict where the keys should be strings, and the values must be one
+# of:
+# - An ExternalDependency subclass
+# - A DependencyFactory object
+# - A callable with a signature of (Environment, MachineChoice, Dict[str, Any]) -> List[Callable[[], ExternalDependency]]
+packages.update({
+ # From dev:
+ 'gtest': gtest_factory,
+ 'gmock': gmock_factory,
+ 'llvm': llvm_factory,
+ 'valgrind': ValgrindDependency,
+ 'zlib': zlib_factory,
+ 'jdk': JDKSystemDependency,
+
+ 'boost': BoostDependency,
+ 'cuda': CudaDependency,
+
+ # per-file
+ 'coarray': coarray_factory,
+ 'hdf5': hdf5_factory,
+ 'mpi': mpi_factory,
+ 'scalapack': scalapack_factory,
+
+ # From misc:
+ 'blocks': BlocksDependency,
+ 'curses': curses_factory,
+ 'netcdf': netcdf_factory,
+ 'openmp': OpenMPDependency,
+ 'python3': python3_factory,
+ 'threads': threads_factory,
+ 'pcap': pcap_factory,
+ 'cups': cups_factory,
+ 'libwmf': libwmf_factory,
+ 'libgcrypt': libgcrypt_factory,
+ 'gpgme': gpgme_factory,
+ 'shaderc': shaderc_factory,
+ 'intl': intl_factory,
+
+ # From platform:
+ 'appleframeworks': AppleFrameworks,
+
+ # From ui:
+ 'gl': gl_factory,
+ 'gnustep': GnuStepDependency,
+ 'qt4': qt4_factory,
+ 'qt5': qt5_factory,
+ 'qt6': qt6_factory,
+ 'sdl2': sdl2_factory,
+ 'wxwidgets': WxDependency,
+ 'vulkan': vulkan_factory,
+})
+_packages_accept_language.update({
+ 'hdf5',
+ 'mpi',
+ 'netcdf',
+ 'openmp',
+})