#! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # the following two variables are used by the target "waf dist" VERSION='0.0.1' APPNAME='cxx_test' # these variables are mandatory ('/' are converted automatically) top = '.' out = 'debug' import re from functools import partial from pathlib import Path class TestRecognizer: RE_FIND_WAF_INFO = re.compile(r"[^\w]waf_test_[A-Za-z0-9_]+\(") def __init__(self, bld, file): self.bld = bld self.file = Path(file) self.root = Path(str(bld.top_dir)) self.src_dir = self.root / "src" self.tests_dir = self.root / "tests" self.target = { "source" : [self.file.name], "target" : self.file.name.replace(".cpp", ""), "includes" : [".", "..", str(self.src_dir), str(self.tests_dir)], "lib" : ["SDL2", "SDL2_image", "fftw3", "sndfile"], "use" : ["io", "core", "common"] } def recognize(self, content, reco): start = reco.regs[0][0]+1 curr = start while content[curr] != "(": curr +=1 function = content[start : curr].strip(" \n\t") start = curr curr += 1 count = 1 while count>0: if content[curr] == ")": count-=1 if content[curr] == "(": count+=1 curr +=1 args = content[start:curr+1] args = eval(args) if not isinstance(args, (tuple, list)): args = [args] args = list(args) f_name = f"execute_{function[9:]}" if not hasattr(self, f_name): nb = len(content[:start].split("\n")) + 1 raise ValueError(f"Fichier {self.file} ligne {nb} waf_test_{f_name} est inconnu") getattr(self, f_name)(args) def _add_or_append(self, k, v): if k not in self.target: self.target[k] = [] if not isinstance(self.target[k], list): self.target[k] = [*(self.target[k].split(" "))] self.target[k].extend(v) def execute_use(self, data): self._add_or_append("use", data) def execute_lib(self, data): self._add_or_append("lib", data) def execute_uselib(self, data): self._add_or_append("uselib", data) def add_test(self): content = Path(self.file).read_text() find = False for x in self.RE_FIND_WAF_INFO.finditer(content): find = True self.recognize(content, x) if not find: return print(f"add program : {self.target}") self.bld.program(**self.target) def find_test(bld): dir = str(bld.path) for file in Path(dir).iterdir(): if file.is_file() and file.name.endswith(".cpp"): TestRecognizer(bld, file).add_test() elif file.is_dir() and (file / "wscript").is_file(): bld.recurse(file.name) def get_sub_files(obj, suffixes=(".c", ".cpp", ".cxx"), max_depth=None): root = Path(str(obj.path)) if root.is_file(): root = root.parent queue = [(0, root)] ret = [] while queue: depth, curr = queue.pop() if max_depth is not None and depth>max_depth: continue for file in curr.iterdir(): if file.is_file(): if not suffixes or file.name.endswith(suffixes): ret.append(str(file.relative_to(root))) elif file.is_dir(): queue.append((depth+1, file)) return ret def options(opt): opt.load('compiler_cxx') def configure(conf): conf.load('compiler_cxx') conf.env.append_value('CXXFLAGS', '-g') conf.check(header_name='stdio.h', features='cxx cxxprogram', mandatory=False) def build(bld): bld.find_test = partial(find_test, bld) bld.get_sub_files = partial(get_sub_files, bld) bld.recurse("src/common") bld.recurse("src/core") bld.recurse("src/fft") bld.recurse("src/io") bld.recurse("src/plugins") bld.recurse("tests") def test(bld): pass