Path: blob/master/Tools/ardupilotwaf/git_submodule.py
9661 views
# encoding: utf-812# flake8: noqa34"""5Waf tool for defining ardupilot's submodules, so that they are kept up to date.6Submodules can be considered dynamic sources, since they are updated during the7build. Furthermore, they can be used to generate other dynamic sources (mavlink8headers generation, for example). Thus, the correct use of this tool should9have three build groups: first one for updating the submodules, second for10generating any dynamic source from them, and the last one for the build. And11post_mode should be set to POST_LAZY. Example::1213def build(bld):14bld.post_mode = waflib.Build.POST_LAZY1516bld.add_group('git_submodules')17# gtest submodule18bld(19features='git_submodule'20git_submodule='gtest',21)22# mavlink submodule with syntactic sugar23bld.git_submodule('mavlink')24...2526# now, for the dynamic sources27bld.add_group('dynamic_sources')28...2930# now, below go the task generators for normal build process31bld.add_group('build')32...33"""3435from waflib import Context, Logs, Task, Utils, Errors36from waflib.Configure import conf37from waflib.TaskGen import before_method, feature, taskgen_method3839import os.path40import re4142class update_submodule(Task.Task):43color = 'BLUE'44run_str = '${GIT} submodule update --recursive --init -- ${SUBMODULE_PATH}'4546fast_forward_diff_re = dict(47removed=re.compile(r'-Subproject commit ([0-9a-f]+)'),48added=re.compile(r'\+Subproject commit ([0-9a-f]+)')49)5051def is_fast_forward(self, path):52bld = self.generator.bld53git = self.env.get_flat('GIT')5455cmd = git, 'diff', '--submodule=short', '--', os.path.basename(path)56cwd = self.cwd.make_node(os.path.dirname(path))57out = bld.cmd_and_log(cmd, quiet=Context.BOTH, cwd=cwd)5859m = self.fast_forward_diff_re['removed'].search(out)60n = self.fast_forward_diff_re['added'].search(out)61if not m or not n:62bld.fatal('git_submodule: failed to parse diff')6364head = n.group(1)65wanted = m.group(1)66cmd = git, 'merge-base', head, wanted67cwd = self.cwd.make_node(path)68out = bld.cmd_and_log(cmd, quiet=Context.BOTH, cwd=cwd)6970return out.strip() == head7172def runnable_status(self):73e = self.env.get_flat74cmd = e('GIT'), 'submodule', 'status', '--recursive', '--', e('SUBMODULE_PATH')75out = self.generator.bld.cmd_and_log(cmd, quiet=Context.BOTH, cwd=self.cwd)7677self.non_fast_forward = []7879# git submodule status uses a blank prefix for submodules that are up80# to date81r = Task.SKIP_ME82for line in out.splitlines():83prefix = line[0]84path = line[1:].split()[1]85if prefix == ' ':86continue87if prefix == '-':88r = Task.RUN_ME89if prefix == '+':90if not self.is_fast_forward(path):91self.non_fast_forward.append(path)92else:93r = Task.RUN_ME9495if getattr(self,'non_fast_forward',[]):96r = Task.SKIP_ME9798return r99100def uid(self):101if not hasattr(self, 'uid_'):102m = Utils.md5()103def u(s):104m.update(s.encode('utf-8'))105u(self.__class__.__name__)106u(self.env.get_flat('SUBMODULE_PATH'))107self.uid_ = m.digest()108109return self.uid_110111def __str__(self):112return 'Submodule update: %s' % self.submodule113114def configure(cfg):115cfg.find_program('git')116117_submodules_tasks = {}118119@taskgen_method120def git_submodule_update(self, name):121if name not in _submodules_tasks:122module_node = self.bld.srcnode.make_node(os.path.join('modules', name))123124tsk = self.create_task('update_submodule', submodule=name)125tsk.cwd = self.bld.srcnode126tsk.env.SUBMODULE_PATH = module_node.abspath()127128_submodules_tasks[name] = tsk129130return _submodules_tasks[name]131132133@feature('git_submodule')134@before_method('process_source')135def process_module_dependencies(self):136self.git_submodule = getattr(self, 'git_submodule', '')137if not self.git_submodule:138self.bld.fatal('git_submodule: empty or missing git_submodule argument')139self.git_submodule_update(self.git_submodule)140141@conf142def git_submodule(bld, git_submodule, **kw):143kw['git_submodule'] = git_submodule144kw['features'] = Utils.to_list(kw.get('features', ''))145kw['features'].append('git_submodule')146147return bld(**kw)148149def _post_fun(bld):150Logs.info('')151for name, t in _submodules_tasks.items():152if not getattr(t,'non_fast_forward',[]):153continue154Logs.warn("Submodule %s not updated: non-fastforward" % name)155156@conf157def git_submodule_post_fun(bld):158bld.add_post_fun(_post_fun)159160def _git_head_hash(ctx, path, short=False, hash_abbrev=8):161cmd = [ctx.env.get_flat('GIT'), 'rev-parse']162if short:163cmd.append(f'--short={hash_abbrev}')164cmd.append('HEAD')165try:166out = ctx.cmd_and_log(cmd, quiet=Context.BOTH, cwd=path)167except Errors.WafError as e:168print(e.stdout, e.stderr)169raise e170171return out.strip()172173@conf174def git_submodule_head_hash(self, name, short=False, hash_abbrev=8):175module_node = self.srcnode.make_node(os.path.join('modules', name))176return _git_head_hash(self, module_node.abspath(), short=short, hash_abbrev=hash_abbrev)177178@conf179def git_head_hash(self, short=False, hash_abbrev=8):180return _git_head_hash(self, self.srcnode.abspath(), short=short, hash_abbrev=hash_abbrev)181182183