Skip to content

Commit

Permalink
refs #27: Allow test sources to declare dependent object files.
Browse files Browse the repository at this point in the history
 * Insert commented "#require <path/to/module.o>" lines to declare
   dependent object files for each test case.

 * Those object files will be automatically rebuilt just like
   normal "all" compilation.
  • Loading branch information
achimnol committed Jan 20, 2016
1 parent 740fde9 commit 00904da
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 30 deletions.
6 changes: 4 additions & 2 deletions Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
59 changes: 34 additions & 25 deletions compilelib.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <nba/xxx/xxxx.hh>)
'''
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 <nba/xxx/xxxx.hh>)
'''
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 <lib/xxx.o>)
'''
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:
Expand Down
5 changes: 4 additions & 1 deletion include/nba/core/assert.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#include <cstdio>
#include <cstdlib>

// 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); \
} \
}
Expand Down
13 changes: 13 additions & 0 deletions tests/test_core_bitmap.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <nba/core/assert.hh>
#include <nba/core/bitmap.hh>
#if 0 // for build scripts
#require <core/bitmap.o>
#endif

using namespace nba;

int main() {
return 0;
}

// vim: ts=8 sts=4 sw=4 et
9 changes: 7 additions & 2 deletions tests/test_core_shiftedint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ using namespace nba;

int main() {
printf("TEST: core.shiftedint\n");
{
test_assert(sizeof(ShiftedInt<uint16_t, 0>) == sizeof(uint16_t),
"The size of ShfitedInt must be same to the given template.");
}
{
auto x = ShiftedInt<uint16_t, 2>(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<uint16_t, 2>(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

0 comments on commit 00904da

Please sign in to comment.