From 00904da6336ccf25ff3c2e4f4ae568002571de26 Mon Sep 17 00:00:00 2001 From: Joongi Kim Date: Wed, 20 Jan 2016 15:19:05 +0900 Subject: [PATCH] refs #27: Allow test sources to declare dependent object files. * Insert commented "#require " lines to declare dependent object files for each test case. * Those object files will be automatically rebuilt just like normal "all" compilation. --- Snakefile | 6 ++-- compilelib.py | 59 ++++++++++++++++++++--------------- include/nba/core/assert.hh | 5 ++- tests/test_core_bitmap.cc | 13 ++++++++ tests/test_core_shiftedint.cc | 9 ++++-- 5 files changed, 62 insertions(+), 30 deletions(-) create mode 100644 tests/test_core_bitmap.cc diff --git a/Snakefile b/Snakefile index 63ddc53..ce1cb3f 100644 --- a/Snakefile +++ b/Snakefile @@ -238,10 +238,12 @@ rule test: for case in _test_cases: includes = [f for f in compilelib.get_includes(fmt('tests/test_{case}.cc'), 'include')] + print(case, compilelib.get_requires(fmt('tests/test_{case}.cc'), 'src')) + requires = [joinpath(OBJ_DIR, f) for f in compilelib.get_requires(fmt('tests/test_{case}.cc'), 'src')] rule: - input: fmt('tests/test_{case}.cc'), includes + input: fmt('tests/test_{case}.cc'), includes, requires output: fmt('tests/test_{case}') - shell: '{CXX} {CXXFLAGS} -o {output} {input[0]} {LIBS}' + shell: '{CXX} {CXXFLAGS} -o {output} {input[0]} {input[2]} {LIBS}' for srcfile in SOURCE_FILES: # We generate build rules dynamically depending on the actual header diff --git a/compilelib.py b/compilelib.py index b452ac3..5e7516a 100644 --- a/compilelib.py +++ b/compilelib.py @@ -62,41 +62,50 @@ def find_all(dirlist, filepattern): results.append(joinpath(root, fname)) return results -_rx_included_local_header = re.compile(r'"(.+\.(h|hh))"') -_rx_included_nba_header = re.compile(r'<(nba/.+\.(h|hh))>') -def get_includes(srcfile, nba_include_dir, dynamic_inputs=None, visited=None): - ''' - Gets a list of included local header files from the given source file. - (e.g., #include ) - ''' +def _find_deps_with_regex(srcfile, base_dir, regexs, visited=None): results = set() visited = visited if visited else set() try: with open(srcfile, 'r', encoding='utf-8') as f: - for line in f: - if line.startswith('#include'): - m = _rx_included_local_header.search(line) - if m: - p = joinpath(os.path.split(srcfile)[0], m.group(1)) - if dynamic_inputs and any(di.endswith(p) for di in dynamic_inputs): - p = dynamic(p) - results.add(p) - m = _rx_included_nba_header.search(line) - if m: - p = joinpath(nba_include_dir, m.group(1)) - if dynamic_inputs and any(di.endswith(p) for di in dynamic_inputs): - p = dynamic(p) - results.add(p) + for line in filter(lambda l: l.startswith('#'), f): + for regex, is_relative in regexs: + m = regex.search(line) + if not m: continue + p = joinpath(os.path.split(srcfile)[0], m.group(1)) if is_relative \ + else joinpath(base_dir, m.group(1)) + results.add(p) for fname in results.copy(): - if (fname.endswith('.h') or fname.endswith('.hh')) \ - and not fname in visited: + if not fname in visited: visited.add(fname) - results.update(s for s in get_includes(fname, nba_include_dir, - dynamic_inputs, visited)) + results.update(s for s in _find_deps_with_regex(fname, base_dir, regexs, visited)) except FileNotFoundError: pass return results +_rx_included_local_header = re.compile(r'^#include "(.+\.(h|hh))"') +_rx_included_nba_header = re.compile(r'#include <(nba/.+\.(h|hh))>') +def get_includes(srcfile, nba_include_dir): + ''' + Gets a list of included local header files from the given source file. + (e.g., #include ) + ''' + regexs = ( + (_rx_included_local_header, True), + (_rx_included_nba_header, False), + ) + return _find_deps_with_regex(srcfile, nba_include_dir, regexs) + +_rx_required_obj_sig = re.compile(r'#require <(.+\.o)>') +def get_requires(srcfile, nba_src_dir, visited=None): + ''' + Gets a list of dependent object files from the given source file. + (e.g., #require ) + ''' + regexs = ( + (_rx_required_obj_sig, False), + ) + return _find_deps_with_regex(srcfile, nba_src_dir, regexs) + _rx_export_elem_decl = re.compile(r'^EXPORT_ELEMENT\(([a-zA-Z0-9_]+)\)') def detect_element_def(header_file): with open(header_file, 'r', encoding='utf-8') as fin: diff --git a/include/nba/core/assert.hh b/include/nba/core/assert.hh index f529387..bba44ae 100644 --- a/include/nba/core/assert.hh +++ b/include/nba/core/assert.hh @@ -4,9 +4,12 @@ #include #include +// Define an empty namespace for binaries with macro-only headers. +namespace nba { } + #define test_assert(cond, msg) {\ if (!(cond)) { \ - fprintf(stderr, "Assertion failure: %s, %s\n", #cond, msg); \ + fprintf(stderr, "Assertion failure (Line %d): %s, %s\n", __LINE__, #cond, msg); \ exit(1); \ } \ } diff --git a/tests/test_core_bitmap.cc b/tests/test_core_bitmap.cc new file mode 100644 index 0000000..bed8557 --- /dev/null +++ b/tests/test_core_bitmap.cc @@ -0,0 +1,13 @@ +#include +#include +#if 0 // for build scripts +#require +#endif + +using namespace nba; + +int main() { + return 0; +} + +// vim: ts=8 sts=4 sw=4 et diff --git a/tests/test_core_shiftedint.cc b/tests/test_core_shiftedint.cc index 6dff781..0bf749c 100644 --- a/tests/test_core_shiftedint.cc +++ b/tests/test_core_shiftedint.cc @@ -6,14 +6,19 @@ using namespace nba; int main() { printf("TEST: core.shiftedint\n"); + { + test_assert(sizeof(ShiftedInt) == sizeof(uint16_t), + "The size of ShfitedInt must be same to the given template."); + } { auto x = ShiftedInt(123); - test_assert((uint32_t) x == 120, "Assign-shift failed."); + test_assert((uint32_t) x == 120, "Expected precision loss due to shift."); } { auto x = ShiftedInt(120); - test_assert((uint32_t) x == 120, "Assign-shift failed."); + test_assert((uint32_t) x == 120, "Expected exactly same value."); } + return 0; } // vim: ts=8 sts=4 sw=4 et