aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/interpreter.py85
-rwxr-xr-xrun_unittests.py10
-rw-r--r--test cases/common/206 subproject with features/meson.build17
-rw-r--r--test cases/common/206 subproject with features/meson_options.txt3
-rw-r--r--test cases/common/206 subproject with features/nothing.c4
-rw-r--r--test cases/common/206 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build3
-rw-r--r--test cases/common/206 subproject with features/subprojects/disabled_sub/lib/meson.build3
-rw-r--r--test cases/common/206 subproject with features/subprojects/disabled_sub/lib/sub.c5
-rw-r--r--test cases/common/206 subproject with features/subprojects/disabled_sub/lib/sub.h6
-rw-r--r--test cases/common/206 subproject with features/subprojects/disabled_sub/meson.build3
-rw-r--r--test cases/common/206 subproject with features/subprojects/sub/lib/meson.build2
-rw-r--r--test cases/common/206 subproject with features/subprojects/sub/lib/sub.c5
-rw-r--r--test cases/common/206 subproject with features/subprojects/sub/lib/sub.h6
-rw-r--r--test cases/common/206 subproject with features/subprojects/sub/meson.build3
14 files changed, 140 insertions, 15 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 4fbb837..358dd8f 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -383,6 +383,9 @@ class DependencyHolder(InterpreterObject, ObjectHolder):
'partial_dependency': self.partial_dependency_method,
})
+ def found(self):
+ return self.found_method([], {})
+
@noPosargs
@permittedKwargs({})
def type_name_method(self, args, kwargs):
@@ -916,16 +919,30 @@ class Test(InterpreterObject):
class SubprojectHolder(InterpreterObject, ObjectHolder):
- def __init__(self, subinterpreter):
+ def __init__(self, subinterpreter, subproject_dir, name):
InterpreterObject.__init__(self)
ObjectHolder.__init__(self, subinterpreter)
+ self.name = name
+ self.subproject_dir = subproject_dir
self.methods.update({'get_variable': self.get_variable_method,
+ 'found': self.found_method,
})
+ @noPosargs
+ @permittedKwargs({})
+ def found_method(self, args, kwargs):
+ return self.found()
+
+ def found(self):
+ return self.held_object is not None
+
@permittedKwargs({})
def get_variable_method(self, args, kwargs):
if len(args) != 1:
raise InterpreterException('Get_variable takes one argument.')
+ if not self.found():
+ raise InterpreterException('Subproject "%s/%s" disabled can\'t get_variable on it.' % (
+ self.subproject_dir, self.name))
varname = args[0]
if not isinstance(varname, str):
raise InterpreterException('Get_variable takes a string argument.')
@@ -1838,7 +1855,7 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'},
'both_libraries': known_library_kwargs,
'library': known_library_kwargs,
'subdir': {'if_found'},
- 'subproject': {'version', 'default_options'},
+ 'subproject': {'version', 'default_options', 'required'},
'test': {'args', 'depends', 'env', 'is_parallel', 'should_fail', 'timeout', 'workdir', 'suite'},
'vcs_tag': {'input', 'output', 'fallback', 'command', 'replace_string'},
}
@@ -2219,7 +2236,16 @@ external dependencies (including libraries) must go to "dependencies".''')
dirname = args[0]
return self.do_subproject(dirname, kwargs)
+ def disabled_subproject(self, dirname):
+ self.subprojects[dirname] = SubprojectHolder(None, self.subproject_dir, dirname)
+ return self.subprojects[dirname]
+
def do_subproject(self, dirname, kwargs):
+ disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
+ if disabled:
+ mlog.log('\nSubproject', mlog.bold(dirname), ':', 'skipped: feature', mlog.bold(feature), 'disabled')
+ return self.disabled_subproject(dirname)
+
default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
default_options = coredata.create_options_dict(default_options)
if dirname == '':
@@ -2237,7 +2263,13 @@ external dependencies (including libraries) must go to "dependencies".''')
incpath = ' => '.join(fullstack)
raise InvalidCode('Recursive include of subprojects: %s.' % incpath)
if dirname in self.subprojects:
- return self.subprojects[dirname]
+ subproject = self.subprojects[dirname]
+
+ if required and not subproject.found():
+ raise InterpreterException('Subproject "%s/%s" required but not found.' % (
+ self.subproject_dir, dirname))
+
+ return subproject
subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir)
r = wrap.Resolver(subproject_dir_abs, self.coredata.wrap_mode)
try:
@@ -2249,22 +2281,35 @@ external dependencies (including libraries) must go to "dependencies".''')
# promotion...
self.print_nested_info(dirname)
- msg = 'Subproject directory {!r} does not exist and cannot be downloaded:\n{}'
- raise InterpreterException(msg.format(os.path.join(self.subproject_dir, dirname), e))
+ if required:
+ msg = 'Subproject directory {!r} does not exist and cannot be downloaded:\n{}'
+ raise InterpreterException(msg.format(os.path.join(self.subproject_dir, dirname), e))
+
+ mlog.log('\nSubproject ', mlog.bold(dirname), 'is buildable:', mlog.red('NO'), '(disabling)\n')
+ return self.disabled_subproject(dirname)
+
subdir = os.path.join(self.subproject_dir, resolved)
os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True)
self.global_args_frozen = True
mlog.log()
with mlog.nested():
- mlog.log('\nExecuting subproject', mlog.bold(dirname), '\n')
- subi = Interpreter(self.build, self.backend, dirname, subdir, self.subproject_dir,
- self.modules, default_options)
- subi.subprojects = self.subprojects
-
- subi.subproject_stack = self.subproject_stack + [dirname]
- current_active = self.active_projectname
- subi.run()
- mlog.log('\nSubproject', mlog.bold(dirname), 'finished.')
+ try:
+ mlog.log('\nExecuting subproject', mlog.bold(dirname), '\n')
+ subi = Interpreter(self.build, self.backend, dirname, subdir, self.subproject_dir,
+ self.modules, default_options)
+ subi.subprojects = self.subprojects
+
+ subi.subproject_stack = self.subproject_stack + [dirname]
+ current_active = self.active_projectname
+ subi.run()
+ mlog.log('\nSubproject', mlog.bold(dirname), 'finished.')
+ except Exception as e:
+ if not required:
+ mlog.log(e)
+ mlog.log('\nSubproject', mlog.bold(dirname), 'is buildable:', mlog.red('NO'), '(disabling)')
+ return self.disabled_subproject(dirname)
+ else:
+ raise e
if 'version' in kwargs:
pv = subi.project_version
@@ -2274,7 +2319,7 @@ external dependencies (including libraries) must go to "dependencies".''')
self.active_projectname = current_active
self.build.subprojects[dirname] = subi.project_version
self.subprojects.update(subi.subprojects)
- self.subprojects[dirname] = SubprojectHolder(subi)
+ self.subprojects[dirname] = SubprojectHolder(subi, self.subproject_dir, dirname)
self.build_def_files += subi.build_def_files
return self.subprojects[dirname]
@@ -2799,6 +2844,13 @@ external dependencies (including libraries) must go to "dependencies".''')
def get_subproject_dep(self, name, dirname, varname, required):
try:
+ subproject = self.subprojects[dirname]
+ if not subproject.found():
+ if not required:
+ return DependencyHolder(NotFoundDependency(self.environment), self.subproject)
+
+ raise DependencyException('Subproject %s was not found.' % (name))
+
dep = self.subprojects[dirname].get_variable_method([varname], {})
except InvalidArguments as e:
if required:
@@ -2820,6 +2872,9 @@ external dependencies (including libraries) must go to "dependencies".''')
dep = self.get_subproject_dep(name, dirname, varname, required)
if not dep:
return False
+ if not dep.found():
+ return dep
+
found = dep.version_method([], {})
# Don't do a version check if the dependency is not found and not required
if not dep.found_method([], {}) and not required:
diff --git a/run_unittests.py b/run_unittests.py
index 5da2798..ebead66 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -2848,6 +2848,16 @@ class FailureTests(BasePlatformTests):
msg = '.*WARNING:.*feature.*build_always_stale.*custom_target.*'
self.assertMesonDoesNotOutput(vcs_tag, msg, meson_version='>=0.43')
+ def test_missing_subproject_not_required_and_required(self):
+ self.assertMesonRaises("sub1 = subproject('not-found-subproject', required: false)\n" +
+ "sub2 = subproject('not-found-subproject', required: true)",
+ """.*Subproject "subprojects/not-found-subproject" required but not found.*""")
+
+ def test_get_variable_on_not_found_project(self):
+ self.assertMesonRaises("sub1 = subproject('not-found-subproject', required: false)\n" +
+ "sub1.get_variable('naaa')",
+ """Subproject "subprojects/not-found-subproject" disabled can't get_variable on it.""")
+
class WindowsTests(BasePlatformTests):
'''
diff --git a/test cases/common/206 subproject with features/meson.build b/test cases/common/206 subproject with features/meson.build
new file mode 100644
index 0000000..5bdfefb
--- /dev/null
+++ b/test cases/common/206 subproject with features/meson.build
@@ -0,0 +1,17 @@
+project('proj', 'c')
+
+auto_subproj = subproject('sub', required: get_option('use-subproject'))
+assert(auto_subproj.found(), 'Subproject should always be buildable and thus found')
+
+auto_dep = dependency('', fallback: ['sub', 'libSub'], required: true)
+assert(auto_dep.found() == true, 'Subproject is required and foundable, dependency should be found.')
+
+disabled_subproj = subproject('disabled_sub', required: get_option('disabled-subproject'))
+assert(disabled_subproj.found() == false, 'Disabled subproject should be NOT found')
+
+disabled_dep = dependency('', fallback: ['disabled_sub', 'libSub'], required: false)
+assert(disabled_dep.found() == false, 'Subprojetc was disabled, it should never be built.')
+nothing = executable('nothing', 'nothing.c', dependencies: [disabled_dep])
+
+subproj_with_missing_dep = subproject('auto_sub_with_missing_dep', required: get_option('auto-sub-with-missing-dep'))
+assert(subproj_with_missing_dep.found() == false, 'Subproject with required=auto and missing dependency should be NOT found')
diff --git a/test cases/common/206 subproject with features/meson_options.txt b/test cases/common/206 subproject with features/meson_options.txt
new file mode 100644
index 0000000..a46e5fb
--- /dev/null
+++ b/test cases/common/206 subproject with features/meson_options.txt
@@ -0,0 +1,3 @@
+option('use-subproject', type : 'feature', value : 'auto')
+option('disabled-subproject', type : 'feature', value : 'disabled')
+option('auto-sub-with-missing-dep', type : 'feature', value : 'auto')
diff --git a/test cases/common/206 subproject with features/nothing.c b/test cases/common/206 subproject with features/nothing.c
new file mode 100644
index 0000000..77750c2
--- /dev/null
+++ b/test cases/common/206 subproject with features/nothing.c
@@ -0,0 +1,4 @@
+int main(int argc, char const *argv[])
+{
+ return 0;
+} \ No newline at end of file
diff --git a/test cases/common/206 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build b/test cases/common/206 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build
new file mode 100644
index 0000000..fa6b011
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/auto_sub_with_missing_dep/meson.build
@@ -0,0 +1,3 @@
+project('sub', 'c')
+
+dependency('no_way_this_exists', required: true) \ No newline at end of file
diff --git a/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/meson.build b/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/meson.build
new file mode 100644
index 0000000..933001a
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/meson.build
@@ -0,0 +1,3 @@
+lib = static_library('sub', 'sub.c')
+
+libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib) \ No newline at end of file
diff --git a/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/sub.c b/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/sub.c
new file mode 100644
index 0000000..068a5b8
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/sub.c
@@ -0,0 +1,5 @@
+#include "sub.h"
+
+int sub() {
+ return 0;
+}
diff --git a/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/sub.h b/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/sub.h
new file mode 100644
index 0000000..f1ab0e1
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/disabled_sub/lib/sub.h
@@ -0,0 +1,6 @@
+#ifndef SUB_H
+#define SUB_H
+
+int sub();
+
+#endif
diff --git a/test cases/common/206 subproject with features/subprojects/disabled_sub/meson.build b/test cases/common/206 subproject with features/subprojects/disabled_sub/meson.build
new file mode 100644
index 0000000..65fef03
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/disabled_sub/meson.build
@@ -0,0 +1,3 @@
+project('disabled_sub', 'c')
+
+subdir('lib') \ No newline at end of file
diff --git a/test cases/common/206 subproject with features/subprojects/sub/lib/meson.build b/test cases/common/206 subproject with features/subprojects/sub/lib/meson.build
new file mode 100644
index 0000000..731d22b
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/sub/lib/meson.build
@@ -0,0 +1,2 @@
+lib = static_library('sub', 'sub.c')
+libSub = declare_dependency(include_directories: include_directories('.'), link_with: lib)
diff --git a/test cases/common/206 subproject with features/subprojects/sub/lib/sub.c b/test cases/common/206 subproject with features/subprojects/sub/lib/sub.c
new file mode 100644
index 0000000..ed78306
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/sub/lib/sub.c
@@ -0,0 +1,5 @@
+#include "sub.h"
+
+int sub() {
+ return 0;
+}
diff --git a/test cases/common/206 subproject with features/subprojects/sub/lib/sub.h b/test cases/common/206 subproject with features/subprojects/sub/lib/sub.h
new file mode 100644
index 0000000..f1ab0e1
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/sub/lib/sub.h
@@ -0,0 +1,6 @@
+#ifndef SUB_H
+#define SUB_H
+
+int sub();
+
+#endif
diff --git a/test cases/common/206 subproject with features/subprojects/sub/meson.build b/test cases/common/206 subproject with features/subprojects/sub/meson.build
new file mode 100644
index 0000000..31882ac
--- /dev/null
+++ b/test cases/common/206 subproject with features/subprojects/sub/meson.build
@@ -0,0 +1,3 @@
+project('sub', 'c')
+
+subdir('lib') \ No newline at end of file