diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2018-01-06 15:33:07 -0800 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2018-04-17 23:33:31 +0300 |
commit | 92487ea33db9d882929d755308853d2ed82abd0d (patch) | |
tree | 0272fa81d53e2f08b72e70e906bdc4d0df65f23e | |
parent | 1952ef5ae13376084dc277de38ff3a6dafb8e595 (diff) | |
download | meson-92487ea33db9d882929d755308853d2ed82abd0d.zip meson-92487ea33db9d882929d755308853d2ed82abd0d.tar.gz meson-92487ea33db9d882929d755308853d2ed82abd0d.tar.bz2 |
Add partial_dependency method to dependencies
This adds a new method, partial_dependency to all dependencies. These
sub dependencies are copies of the original dependency, but with one or
more of the attributes replaced with an empty list. This allows creating
a sub dependency that has only cflags or drops link_arguments, for
example.
15 files changed, 356 insertions, 2 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 42abe75..74e7ff2 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1827,6 +1827,32 @@ an external dependency with the following methods: - `version()` is the version number as a string, for example `1.2.8` + - `partial_dependency(compile_args : false, link_args : false, links : false, + includes : false, source : false)` (*added 0.46.0) returns a new dependency + object with the same name, version, found status, type name, and methods as + the object that called it. This new object will only inherit other + attributes from its parent as controlled by keyword arguments. + + If the parent has any dependencies, those will be applied to the new + partial dependency with the same rules. So , given: + + ```meson + dep1 = declare_dependency(compiler_args : '-Werror=foo', link_with : 'libfoo') + dep2 = declare_dependency(compiler_args : '-Werror=bar', dependencies : dep1) + dep3 = dep2.partial_dependency(compile_args : true) + ``` + + dep3 will add `['-Werror=foo', '-Werror=bar']` to the compiler args of + any target it is added to, but libfoo will not be added to the link_args. + + The following arguments will add the following attributes: + + - compile_args: any arguments passed to the compiler + - link_args: any arguments passed to the linker + - links: anything passed via link_with or link_whole + - includes: any include_directories + - sources: any compiled or static sources the dependency has + ### `disabler` object A disabler object is an object that behaves in much the same way as diff --git a/docs/markdown/snippets/partial-dependencies.md b/docs/markdown/snippets/partial-dependencies.md new file mode 100644 index 0000000..8d2136a --- /dev/null +++ b/docs/markdown/snippets/partial-dependencies.md @@ -0,0 +1,25 @@ +## Added new partial_dependency method to dependencies and libraries + +It is now possible to use only part of a dependency in a target. This allows, +for example, to only use headers with convenience libraries to avoid linking +to the same library multiple times. + +```meson + +dep = dependency('xcb') + +helper = static_library( + 'helper', + ['helper1.c', 'helper2.c'], + dependencies : dep.partial_dependency(includes : true), +] + +final = shared_library( + 'final', + ['final.c'], + dependencyes : dep, +) +``` + +A partial dependency will have the same name version as the full dependency it +is derived from, as well as any values requested. diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 2a19544..27a5fcb 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -1,4 +1,4 @@ -# Copyright 2013-2017 The Meson development team +# Copyright 2013-2018 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. @@ -15,6 +15,7 @@ # This file contains the detection logic for external dependencies. # Custom logic for several other packages are in separate files. +import copy import os import re import stat @@ -146,6 +147,23 @@ class Dependency: def get_configtool_variable(self, variable_name): raise DependencyException('{!r} is not a config-tool dependency'.format(self.name)) + def get_partial_dependency(self, *, compile_args=False, link_args=False, + links=False, includes=False, sources=False): + """Create a new dependency that contains part of the parent dependency. + + The following options can be inherited: + links -- all link_with arguemnts + includes -- all include_directory and -I/-isystem calls + sources -- any source, header, or generated sources + compile_args -- any compile args + link_args -- any link args + + Additionally the new dependency will have the version parameter of it's + parent (if any) and the requested values of any dependencies will be + added as well. + """ + RuntimeError('Unreachable code in partial_dependency called') + class InternalDependency(Dependency): def __init__(self, version, incdirs, compile_args, link_args, libraries, whole_libraries, sources, ext_deps): @@ -168,6 +186,21 @@ class InternalDependency(Dependency): raise DependencyException('Method "get_configtool_variable()" is ' 'invalid for an internal dependency') + def get_partial_dependency(self, *, compile_args=False, link_args=False, + links=False, includes=False, sources=False): + compile_args = self.compile_args.copy() if compile_args else [] + link_args = self.link_args.copy() if link_args else [] + libraries = self.libraries.copy() if links else [] + whole_libraries = self.whole_libraries.copy() if links else [] + sources = self.sources.copy() if sources else [] + includes = self.include_directories.copy() if includes else [] + deps = [d.get_partial_dependency( + compile_args=compile_args, link_args=link_args, links=links, + includes=includes, sources=sources) for d in self.ext_deps] + return InternalDependency( + self.version, includes, compile_args, link_args, libraries, + whole_libraries, sources, deps) + class ExternalDependency(Dependency): def __init__(self, type_name, environment, language, kwargs): @@ -211,6 +244,18 @@ class ExternalDependency(Dependency): def get_compiler(self): return self.compiler + def get_partial_dependency(self, *, compile_args=False, link_args=False, + links=False, includes=False, sources=False): + new = copy.copy(self) + if not compile_args: + new.compile_args = [] + if not link_args: + new.link_args = [] + if not sources: + new.sources = [] + + return new + class ConfigToolDependency(ExternalDependency): @@ -887,6 +932,15 @@ class ExternalLibrary(ExternalDependency): return [] return self.link_args + def get_partial_dependency(self, *, compile_args=False, link_args=False, + links=False, includes=False, sources=False): + # External library only has link_args, so ignore the rest of the + # interface. + new = copy.copy(self) + if not link_args: + new.link_args = [] + return new + class ExtraFrameworkDependency(ExternalDependency): def __init__(self, name, required, path, env, lang, kwargs): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 4e4ba5c..c7841a8 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -275,6 +275,7 @@ class DependencyHolder(InterpreterObject, ObjectHolder): 'version': self.version_method, 'get_pkgconfig_variable': self.pkgconfig_method, 'get_configtool_variable': self.configtool_method, + 'partial_dependency': self.partial_dependency_method, }) def type_name_method(self, args, kwargs): @@ -306,12 +307,18 @@ class DependencyHolder(InterpreterObject, ObjectHolder): raise InterpreterException('Variable name must be a string.') return self.held_object.get_configtool_variable(varname) + def partial_dependency_method(self, args, kwargs): + if args: + raise InterpreterException('partial_dependency takes no positional arguments') + return DependencyHolder(self.held_object.get_partial_dependency(**kwargs)) + class InternalDependencyHolder(InterpreterObject, ObjectHolder): def __init__(self, dep): InterpreterObject.__init__(self) ObjectHolder.__init__(self, dep) self.methods.update({'found': self.found_method, 'version': self.version_method, + 'partial_dependency': self.partial_dependency_method, }) def found_method(self, args, kwargs): @@ -320,6 +327,11 @@ class InternalDependencyHolder(InterpreterObject, ObjectHolder): def version_method(self, args, kwargs): return self.held_object.get_version() + def partial_dependency_method(self, args, kwargs): + if args: + raise InterpreterException('get_partial_dependency takes no positional arguments') + return DependencyHolder(self.held_object.get_partial_dependency(**kwargs)) + class ExternalProgramHolder(InterpreterObject, ObjectHolder): def __init__(self, ep): InterpreterObject.__init__(self) @@ -346,7 +358,9 @@ class ExternalLibraryHolder(InterpreterObject, ObjectHolder): def __init__(self, el): InterpreterObject.__init__(self) ObjectHolder.__init__(self, el) - self.methods.update({'found': self.found_method}) + self.methods.update({'found': self.found_method, + 'partial_dependency': self.partial_dependency_method, + }) def found(self): return self.held_object.found() @@ -366,6 +380,11 @@ class ExternalLibraryHolder(InterpreterObject, ObjectHolder): def get_exe_args(self): return self.held_object.get_exe_args() + def partial_dependency_method(self, args, kwargs): + if args: + raise InterpreterException('partial_dependency takes no positional arguments') + return DependencyHolder(self.held_object.get_partial_dependency(**kwargs)) + class GeneratorHolder(InterpreterObject, ObjectHolder): def __init__(self, interpreter, args, kwargs): InterpreterObject.__init__(self) diff --git a/test cases/common/191 partial dependency/declare_dependency/headers/foo.c b/test cases/common/191 partial dependency/declare_dependency/headers/foo.c new file mode 100644 index 0000000..215112c --- /dev/null +++ b/test cases/common/191 partial dependency/declare_dependency/headers/foo.c @@ -0,0 +1,16 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#error "Included C sources that shouldn't be." diff --git a/test cases/common/191 partial dependency/declare_dependency/headers/foo.h b/test cases/common/191 partial dependency/declare_dependency/headers/foo.h new file mode 100644 index 0000000..28c81c9 --- /dev/null +++ b/test cases/common/191 partial dependency/declare_dependency/headers/foo.h @@ -0,0 +1,16 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +int foo(void); diff --git a/test cases/common/191 partial dependency/declare_dependency/main.c b/test cases/common/191 partial dependency/declare_dependency/main.c new file mode 100644 index 0000000..e9ed032 --- /dev/null +++ b/test cases/common/191 partial dependency/declare_dependency/main.c @@ -0,0 +1,25 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#include "foo.h" + +int main() { + int a = foo(); + if (a == 1) { + return 0; + } else { + return 1; + } +} diff --git a/test cases/common/191 partial dependency/declare_dependency/meson.build b/test cases/common/191 partial dependency/declare_dependency/meson.build new file mode 100644 index 0000000..86e2608 --- /dev/null +++ b/test cases/common/191 partial dependency/declare_dependency/meson.build @@ -0,0 +1,28 @@ +# Copyright © 2018 Intel Corporation +# +# 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. + +dec_dep = declare_dependency( + sources : files('headers/foo.c'), + include_directories : include_directories('headers'), +) + +sub_dep = dec_dep.partial_dependency(includes : true) + +dec_exe = executable( + 'declare_dep', + files('main.c', 'other.c'), + dependencies : sub_dep, +) + +test('Declare Dependency', dec_exe) diff --git a/test cases/common/191 partial dependency/declare_dependency/other.c b/test cases/common/191 partial dependency/declare_dependency/other.c new file mode 100644 index 0000000..b1e199e --- /dev/null +++ b/test cases/common/191 partial dependency/declare_dependency/other.c @@ -0,0 +1,20 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#include "foo.h" + +int foo(void) { + return 1; +} diff --git a/test cases/common/191 partial dependency/meson.build b/test cases/common/191 partial dependency/meson.build new file mode 100644 index 0000000..e908487 --- /dev/null +++ b/test cases/common/191 partial dependency/meson.build @@ -0,0 +1,17 @@ +# Copyright © 2018 Intel Corporation +# +# 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. + +project('partial dependency', ['c', 'cpp']) + +subdir('declare_dependency') diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build index df55b30..9399598 100644 --- a/test cases/frameworks/1 boost/meson.build +++ b/test cases/frameworks/1 boost/meson.build @@ -31,3 +31,5 @@ test('Boost statictest', staticexe) test('Boost UTF test', unitexe) test('Boost nomod', nomodexe) test('Boost extralib test', extralibexe) + +subdir('partial_dep') diff --git a/test cases/frameworks/1 boost/partial_dep/foo.cpp b/test cases/frameworks/1 boost/partial_dep/foo.cpp new file mode 100644 index 0000000..da58703 --- /dev/null +++ b/test cases/frameworks/1 boost/partial_dep/foo.cpp @@ -0,0 +1,20 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#include "foo.hpp" + +vec Foo::vector() { + return myvec; +} diff --git a/test cases/frameworks/1 boost/partial_dep/foo.hpp b/test cases/frameworks/1 boost/partial_dep/foo.hpp new file mode 100644 index 0000000..393d3f6 --- /dev/null +++ b/test cases/frameworks/1 boost/partial_dep/foo.hpp @@ -0,0 +1,27 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#include <boost/fusion/container/vector.hpp> + +typedef boost::fusion::vector<int> vec; + + +class Foo { + public: + Foo() {}; + vec vector(); + private: + const vec myvec = vec(4); +}; diff --git a/test cases/frameworks/1 boost/partial_dep/main.cpp b/test cases/frameworks/1 boost/partial_dep/main.cpp new file mode 100644 index 0000000..5138f5c --- /dev/null +++ b/test cases/frameworks/1 boost/partial_dep/main.cpp @@ -0,0 +1,28 @@ +/* Copyright © 2018 Intel Corporation + * + * 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. + */ + +#include <iostream> +#include <boost/fusion/include/at_c.hpp> +#include "foo.hpp" + + +int main() { + auto foo = Foo(); + vec v = foo.vector(); + std::cout << boost::fusion::at_c<0>(v) << std::endl; + + return 0; +} + diff --git a/test cases/frameworks/1 boost/partial_dep/meson.build b/test cases/frameworks/1 boost/partial_dep/meson.build new file mode 100644 index 0000000..9d481bb --- /dev/null +++ b/test cases/frameworks/1 boost/partial_dep/meson.build @@ -0,0 +1,31 @@ +# Copyright © 2018 Intel Corporation +# +# 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. + +dep_boost = dependency('boost') +dep_boost_headers = dep_boost.partial_dependency(compile_args : true) + +libfoo = static_library( + 'foo', + 'foo.cpp', + dependencies : dep_boost_headers, +) + +exe_external_dep = executable( + 'external_dep', + 'main.cpp', + dependencies : dep_boost, + link_with : libfoo +) + +test('External Dependency', exe_external_dep) |