diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2020-01-27 18:29:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-27 18:29:22 +0200 |
commit | a51c9af921d0ba05aa173b8a1a4351eacb575be0 (patch) | |
tree | 8207935e73c6c8e82f8c38c1ff130cbfe5642249 | |
parent | 9e07f8d8e6bb088252ac11b3e663ff3d93c8020a (diff) | |
parent | 202c89d0b665a536a738c59dcde1f374047a346e (diff) | |
download | meson-a51c9af921d0ba05aa173b8a1a4351eacb575be0.zip meson-a51c9af921d0ba05aa173b8a1a4351eacb575be0.tar.gz meson-a51c9af921d0ba05aa173b8a1a4351eacb575be0.tar.bz2 |
Merge pull request #6423 from dcbaker/declare-dependency-variables
Add ability to set and query arbitrary variables on declare_dependency objects
-rw-r--r-- | docs/markdown/Dependencies.md | 24 | ||||
-rw-r--r-- | docs/markdown/Reference-manual.md | 9 | ||||
-rw-r--r-- | docs/markdown/Subprojects.md | 22 | ||||
-rw-r--r-- | mesonbuild/build.py | 2 | ||||
-rw-r--r-- | mesonbuild/dependencies/base.py | 28 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 14 | ||||
-rw-r--r-- | mesonbuild/modules/gnome.py | 2 | ||||
-rw-r--r-- | test cases/common/218 dependency get_variable method/meson.build | 13 |
8 files changed, 89 insertions, 25 deletions
diff --git a/docs/markdown/Dependencies.md b/docs/markdown/Dependencies.md index e029a84..d21bb97 100644 --- a/docs/markdown/Dependencies.md +++ b/docs/markdown/Dependencies.md @@ -67,6 +67,7 @@ page](#dependencies-with-custom-lookup-functionality). # Arbitrary variables from dependencies that can be found multiple ways *Note* new in 0.51.0 +*new in 0.54.0, the `internal` keyword* When you need to get an arbitrary variables from a dependency that can be found multiple ways and you don't want to constrain the type you can use @@ -79,13 +80,14 @@ var = foo.get_variable(cmake : 'CMAKE_VAR', pkgconfig : 'pkg-config-var', config ``` It accepts the keywords 'cmake', 'pkgconfig', 'pkgconfig_define', -'configtool', and 'default_value'. 'pkgconfig_define' works just like the -'define_variable' argument to `get_pkgconfig_variable`. When this method is -invoked the keyword corresponding to the underlying type of the dependency -will be used to look for a variable. If that variable cannot be found or if -the caller does not provide an argument for the type of dependency, one of -the following will happen: If 'default_value' was provided that value will be -returned, if 'default_value' was not provided then an error will be raised. +'configtool', 'internal', and 'default_value'. 'pkgconfig_define' works just +like the 'define_variable' argument to `get_pkgconfig_variable`. When this +method is invoked the keyword corresponding to the underlying type of the +dependency will be used to look for a variable. If that variable cannot be +found or if the caller does not provide an argument for the type of +dependency, one of the following will happen: If 'default_value' was provided +that value will be returned, if 'default_value' was not provided then an +error will be raised. # Declaring your own @@ -289,16 +291,16 @@ libraries that have been compiled for single-threaded use instead. *(added 0.53.0)* -Enables compiling and linking against the CUDA Toolkit. The `version` -and `modules` keywords may be passed to request the use of a specific +Enables compiling and linking against the CUDA Toolkit. The `version` +and `modules` keywords may be passed to request the use of a specific CUDA Toolkit version and/or additional CUDA libraries, correspondingly: ```meson dep = dependency('cuda', version : '>=10', modules : ['cublas']) ``` -Note that explicitly adding this dependency is only necessary if you are -using CUDA Toolkit from a C/C++ file or project, or if you are utilizing +Note that explicitly adding this dependency is only necessary if you are +using CUDA Toolkit from a C/C++ file or project, or if you are utilizing additional toolkit libraries that need to be explicitly linked to. ## CUPS diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 6699d75..57fc1f7 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -413,6 +413,9 @@ keyword arguments. - `sources`, sources to add to targets (or generated header files that should be built before sources including them are built) - `version`, the version of this dependency, such as `1.2.3` + - `variables`, a dictionary of arbitrary strings, this is meant to be used + in subprojects where special variables would be provided via cmake or + pkg-config. Since 0.54.0 ### dependency() @@ -2373,14 +2376,16 @@ an external dependency with the following methods: - sources: any compiled or static sources the dependency has - `get_variable(cmake : str, pkgconfig : str, configtool : str, - default_value : str, pkgconfig_define : [str, str])` *(Added in - 0.51.0)* A generic variable getter method, which replaces the + internal: str, default_value : str, pkgconfig_define : [str, str])` + *(Added in 0.51.0)* A generic variable getter method, which replaces the get_*type*_variable methods. This allows one to get the variable from a dependency without knowing specifically how that dependency was found. If default_value is set and the value cannot be gotten from the object then default_value is returned, if it is not set then an error is raised. + *New in 0.54.0, the `internal` keyword* + ### `disabler` object A disabler object is an object that behaves in much the same way as diff --git a/docs/markdown/Subprojects.md b/docs/markdown/Subprojects.md index 91b1843..8232da9 100644 --- a/docs/markdown/Subprojects.md +++ b/docs/markdown/Subprojects.md @@ -55,6 +55,28 @@ should be named as `<project_name>_dep` (e.g. `gtest_dep`), and others can have There may be exceptions to these rules where common sense should be applied. +### Adding variables to the dependency + +*New in 0.54.0* + +In some cases a project may define special variables via pkg-config or cmake +that a caller needs to know about. Meson provides a `dependency.get_variable` +method to hide what kind of dependency is provided, and this is available to +subprojects as well. Use the `variables` keyword to add a dict of strings: + +```meson +my_dep = declare_dependency(..., variables : {'var': 'value', 'number': '3'}) +``` + +Which another project can access via: + +```meson +var = my_dep.get_variable(internal : 'var', cmake : 'CMAKE_VAR') +``` + +The values of the dict must be strings, as pkg-config and cmake will return +variables as strings. + ### Build options in subproject All Meson features of the subproject, such as project options keep diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 0eb930b..1db930e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1053,7 +1053,7 @@ This will become a hard error in a future Meson release.''') [], dep.get_compile_args(), dep.get_link_args(), - [], [], [], []) + [], [], [], [], {}) self.external_deps.append(extpart) # Deps of deps. self.add_deps(dep.ext_deps) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 282c314..e9cf9ac 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -223,7 +223,8 @@ class Dependency: self.ext_deps.append(dep_type(env, kwargs)) def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, - configtool: T.Optional[str] = None, default_value: T.Optional[str] = None, + configtool: T.Optional[str] = None, internal: T.Optional[str] = None, + default_value: T.Optional[str] = None, pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: if default_value is not None: return default_value @@ -235,7 +236,8 @@ class Dependency: return new_dep class InternalDependency(Dependency): - def __init__(self, version, incdirs, compile_args, link_args, libraries, whole_libraries, sources, ext_deps): + def __init__(self, version, incdirs, compile_args, link_args, libraries, + whole_libraries, sources, ext_deps, variables: T.Dict[str, T.Any]): super().__init__('internal', {}) self.version = version self.is_found = True @@ -246,6 +248,7 @@ class InternalDependency(Dependency): self.whole_libraries = whole_libraries self.sources = sources self.ext_deps = ext_deps + self.variables = variables def get_pkgconfig_variable(self, variable_name, kwargs): raise DependencyException('Method "get_pkgconfig_variable()" is ' @@ -270,7 +273,17 @@ class InternalDependency(Dependency): return InternalDependency( self.version, final_includes, final_compile_args, final_link_args, final_libraries, final_whole_libraries, - final_sources, final_deps) + final_sources, final_deps, self.variables) + + def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, + configtool: T.Optional[str] = None, internal: T.Optional[str] = None, + default_value: T.Optional[str] = None, + pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: + val = self.variables.get(internal, default_value) + if val is not None: + return val + raise DependencyException('Could not get an internal variable and no default provided for {!r}'.format(self)) + class HasNativeKwarg: def __init__(self, kwargs): @@ -554,7 +567,8 @@ class ConfigToolDependency(ExternalDependency): return self.type_name def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, - configtool: T.Optional[str] = None, default_value: T.Optional[str] = None, + configtool: T.Optional[str] = None, internal: T.Optional[str] = None, + default_value: T.Optional[str] = None, pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: if configtool: # In the not required case '' (empty string) will be returned if the @@ -1013,7 +1027,8 @@ class PkgConfigDependency(ExternalDependency): return self.type_name def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, - configtool: T.Optional[str] = None, default_value: T.Optional[str] = None, + configtool: T.Optional[str] = None, internal: T.Optional[str] = None, + default_value: T.Optional[str] = None, pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: if pkgconfig: kwargs = {} @@ -1550,7 +1565,8 @@ project(MesonTemp LANGUAGES {}) return '' def get_variable(self, *, cmake: T.Optional[str] = None, pkgconfig: T.Optional[str] = None, - configtool: T.Optional[str] = None, default_value: T.Optional[str] = None, + configtool: T.Optional[str] = None, internal: T.Optional[str] = None, + default_value: T.Optional[str] = None, pkgconfig_define: T.Optional[T.List[str]] = None) -> T.Union[str, T.List[str]]: if cmake: try: diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index f1ed2d4..908a555 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -483,7 +483,8 @@ class DependencyHolder(InterpreterObject, ObjectHolder): @FeatureNew('dep.get_variable', '0.51.0') @noPosargs - @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'default_value', 'pkgconfig_define'}) + @permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'internal', 'default_value', 'pkgconfig_define'}) + @FeatureNewKwargs('dep.get_variable', '0.54.0', ['internal']) def variable_method(self, args, kwargs): return self.held_object.get_variable(**kwargs) @@ -2087,6 +2088,7 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'}, 'link_args', 'link_whole', 'version', + 'variables', }, 'executable': build.known_exe_kwargs, 'find_program': {'required', 'native', 'version', 'dirs'}, @@ -2385,6 +2387,7 @@ class Interpreter(InterpreterBase): return [mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, fname) for fname in args] @FeatureNewKwargs('declare_dependency', '0.46.0', ['link_whole']) + @FeatureNewKwargs('declare_dependency', '0.54.0', ['variables']) @permittedKwargs(permitted_kwargs['declare_dependency']) @noPosargs def func_declare_dependency(self, node, args, kwargs): @@ -2399,6 +2402,12 @@ class Interpreter(InterpreterBase): deps = extract_as_list(kwargs, 'dependencies', unholder=True) compile_args = mesonlib.stringlistify(kwargs.get('compile_args', [])) link_args = mesonlib.stringlistify(kwargs.get('link_args', [])) + variables = kwargs.get('variables', {}) + if not isinstance(variables, dict): + raise InterpreterException('variables must be a dict.') + if not all(isinstance(v, str) for v in variables.values()): + # Because that is how they will come from pkg-config and cmake + raise InterpreterException('variables values be strings.') final_deps = [] for d in deps: try: @@ -2413,7 +2422,8 @@ class Interpreter(InterpreterBase): raise InterpreterException('''Entries in "link_with" may only be self-built targets, external dependencies (including libraries) must go to "dependencies".''') dep = dependencies.InternalDependency(version, incs, compile_args, - link_args, libs, libs_whole, sources, final_deps) + link_args, libs, libs_whole, sources, final_deps, + variables) return DependencyHolder(dep, self.subproject) @noKwargs diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 9bd7a99..3d5d718 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -1692,7 +1692,7 @@ G_END_DECLS''' # - add relevant directories to include dirs incs = [build.IncludeDirs(state.subdir, ['.'] + vapi_includes, False)] sources = [vapi_target] + vapi_depends - rv = InternalDependency(None, incs, [], [], link_with, [], sources, []) + rv = InternalDependency(None, incs, [], [], link_with, [], sources, [], {}) created_values.append(rv) return ModuleReturnValue(rv, created_values) diff --git a/test cases/common/218 dependency get_variable method/meson.build b/test cases/common/218 dependency get_variable method/meson.build index 72e65ee..8c189bb 100644 --- a/test cases/common/218 dependency get_variable method/meson.build +++ b/test cases/common/218 dependency get_variable method/meson.build @@ -47,6 +47,15 @@ else 'cmake config-tool got default when we shouldn\'t have.') endif +idep = declare_dependency(variables : {'foo' : 'value'}) +assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', + internal : 'foo', default_value : default) == 'value', + 'internal got default when it shouldn\'t have.') +assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', + internal : 'bar', default_value : default) == default, + 'internal didn\'t default when it should have.') + idep = declare_dependency() -assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', default_value : default) == default, - 'Got something other than default from an internal dependency') +assert(idep.get_variable(pkgconfig : 'foo', cmake : 'foo', configtool : 'foo', + default_value : default) == default, + 'something went wrong with an InternalDependency with no variables.') |