Rollback if an optional subproject fails
If a subproject is not required and fails during its configuration, the parent project continues, but should not include any target or state set by the failed subproject. This fix ninja still trying to build targets generated by subprojects before they fail in their configuration. The 'build' object is now per-interpreter instead of being global. Once a subproject interpreter succeed, values from its 'build' object are merged back into its parent 'build' object.
This commit is contained in:
parent
e4da09b8f9
commit
edccb11f01
|
@ -138,6 +138,19 @@ class Build:
|
|||
self.find_overrides = {}
|
||||
self.searched_programs = set() # The list of all programs that have been searched for.
|
||||
|
||||
def copy(self):
|
||||
other = Build(self.environment)
|
||||
for k, v in self.__dict__.items():
|
||||
if isinstance(v, (list, dict, set, OrderedDict)):
|
||||
other.__dict__[k] = v.copy()
|
||||
else:
|
||||
other.__dict__[k] = v
|
||||
return other
|
||||
|
||||
def merge(self, other):
|
||||
for k, v in other.__dict__.items():
|
||||
self.__dict__[k] = v
|
||||
|
||||
def add_compiler(self, compiler):
|
||||
if self.static_linker is None and compiler.needs_static_linker():
|
||||
self.static_linker = self.environment.detect_static_linker(compiler)
|
||||
|
|
|
@ -2286,7 +2286,8 @@ external dependencies (including libraries) must go to "dependencies".''')
|
|||
with mlog.nested():
|
||||
try:
|
||||
mlog.log('\nExecuting subproject', mlog.bold(dirname), '\n')
|
||||
subi = Interpreter(self.build, self.backend, dirname, subdir, self.subproject_dir,
|
||||
new_build = self.build.copy()
|
||||
subi = Interpreter(new_build, self.backend, dirname, subdir, self.subproject_dir,
|
||||
self.modules, default_options)
|
||||
subi.subprojects = self.subprojects
|
||||
|
||||
|
@ -2312,6 +2313,7 @@ external dependencies (including libraries) must go to "dependencies".''')
|
|||
self.subprojects.update(subi.subprojects)
|
||||
self.subprojects[dirname] = SubprojectHolder(subi, self.subproject_dir, dirname)
|
||||
self.build_def_files += subi.build_def_files
|
||||
self.build.merge(subi.build)
|
||||
return self.subprojects[dirname]
|
||||
|
||||
def get_option_internal(self, optname):
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
project('test broken subproject')
|
||||
subproject('broken', required : false)
|
|
@ -0,0 +1 @@
|
|||
#error This must not compile
|
|
@ -0,0 +1,4 @@
|
|||
project('broken', 'c')
|
||||
|
||||
executable('app', 'broken.c')
|
||||
assert(false, 'This subproject must fail')
|
Loading…
Reference in New Issue