Updating autogen script

This commit is contained in:
Leonardo Vencovsky committed 2020-06-20 12:12:47 -03:00
1 parent feaac16804
commit a1e0a4edbb
11 files changed
+161 -141

No files matched your search

+1 -1
View File
@@ -17,6 +17,6 @@ script:
- export CC=gcc-9
- gcc --version
- python --version
- make
- python autogen.py -e -b -cv -r
after_success:
- bash <(curl -s https://codecov.io/bash)
+112 -92
View File
@@ -3,6 +3,7 @@
import argparse
import os
import pathlib
import re
import shutil
import subprocess
@@ -39,7 +40,7 @@ INCLUDE_DIR = f"{OUTPUT_DIR}/{DIR_MAP['HEADER']}"
# const
SRC_DIR = f"{OUTPUT_DIR}/{DIR_MAP['SOURCE']}"
# Where object files .o go
OBJ_DIR = f'{BUILD_DIR}/obj'
OBJ_DIR = BUILD_DIR
# The name of the main test executable
TEST_EXE = f'{OUTPUT_DIR}/main.exe'
@@ -53,10 +54,10 @@ CFLAGS = ['-Wall', '-Werror']
CVFLAGS = ['--coverage', '-O0']
# Include to the main Library
# const
INCLUDE = '-I ./src'
INCLUDE = ['-I', './src']
# Include to the test file headers
# const
TINCLUDE = f'-I {INCLUDE_DIR}'
TINCLUDE = ['-I', f'{INCLUDE_DIR}']
# Macro expansion
@@ -115,25 +116,36 @@ COLLECTIONS = [
]
def full_path(path: Text) -> Text:
'''
Returns the full path of a 'path' with ralative paths, e.g. './' or '../'
'''
return str(pathlib.Path(path).resolve())
def execute_command(commands: List[Text]):
print(' '.join(commands))
subprocess.run(commands, shell=True)
cp = subprocess.run(commands, shell=True)
# if cp.returncode != 0:
# print('Error when executing the last command')
# exit(1)
def assert_executable(program: Text):
'''
Asserts that a given program is installed and available in PATH
Asserts that a given program is installed and available in PATH.
'''
if shutil.which(program) is None:
raise Exception(f'The required executable {program} was not found in your path')
def assert_dir(dir: Text):
def assert_dir(directory: Text):
'''
Given a string 'dir' that is a path to a directory, make sure that it exists.
Given a string 'directory' that is a path to a directory, make sure that it exists.
'''
if not os.path.exists(dir):
os.makedirs(dir)
if not os.path.exists(directory):
os.makedirs(directory)
def assert_structure():
@@ -143,13 +155,13 @@ def assert_structure():
assert_dir(OUTPUT_DIR)
# include and src
for dir in DIR_MAP.values():
assert_dir(f'{OUTPUT_DIR}/{dir}')
for directory in DIR_MAP.values():
assert_dir(f'{OUTPUT_DIR}/{directory}')
# For each library, create a directory for include and src
for lib in ALL_LIBS:
for dir in DIR_MAP.values():
assert_dir(f'{OUTPUT_DIR}/{dir}/{lib.lower()}')
for directory in DIR_MAP.values():
assert_dir(f'{OUTPUT_DIR}/{directory}/{lib.lower()}')
assert_dir(BUILD_DIR)
assert_dir(OBJ_DIR)
@@ -158,12 +170,21 @@ def assert_structure():
assert_dir(f'{OBJ_DIR}/{lib.lower()}')
def clean_build():
execute_command(['find', BUILD_DIR, '-type', 'f', '-delete'])
execute_command(['find', '.', '-iname', '*.gcov', '-type', 'f', '-delete'])
def clean_build(cleanfull: bool):
'''
Removes all files generated by compilation and code coverage along with folders.
'''
execute_command(['rm', '-r', '*.gcov'])
execute_command(['rm', TEST_EXE])
for directory in [BUILD_DIR, SRC_DIR, INCLUDE_DIR]:
execute_command(['rm', '-r', directory])
def expand_code():
'''
Expands code to be used in tests. This is necessary because code coverage doesn't work with macros.
'''
# Generate Header and Source separately
for ftype in ['HEADER', 'SOURCE']:
for data in COLLECTIONS:
@@ -183,7 +204,7 @@ def expand_code():
file.flush()
file.close()
result = subprocess.getoutput(f'{CC} {EXPAND_FLAGS} {INCLUDE} {TMP_FILE}')
result = subprocess.getoutput(f'{CC} {EXPAND_FLAGS} {" ".join(INCLUDE)} {TMP_FILE}')
# (?s) makes '.' match anything, even '\n'
match = re.search(fr'(?s){UNIQUE_FLAG}(?P<code>.+){UNIQUE_FLAG}', result)
@@ -223,6 +244,9 @@ def expand_code():
def format_expand():
'''
Format the files outputted by 'expand_code'.
'''
cmd = ['clang-format', '--style=file', '--verbose', '-i']
dirs_to_format = [f'{OUTPUT_DIR}/{DIR_MAP[ftype]}/{lib.lower()}/*.{EXT_MAP[ftype]}' for ftype in DIR_MAP.keys() for lib in ALL_LIBS]
cmd.extend(dirs_to_format)
@@ -230,79 +254,63 @@ def format_expand():
def format_code(source: bool, tests: bool):
'''
Format all source files from the main library or test files.
'''
if source:
execute_command(['find', './src/', '-iname', '*.h', '|', 'xargs', 'clang-format', '--style=file', '--verbose', '-i'])
execute_command(['find', './src/', '-name', '*.h', '|', 'xargs', 'clang-format', '--style=file', '--verbose', '-i'])
if tests:
execute_command(['find', './tests/', '-iname', '*.c', '-o', '-iname', '*.h', '|', 'xargs', 'clang-format', '--style=file', '--verbose', '-i'])
execute_command(['find', './tests/', '-name', '*.c', '-o', '-name', '*.h', '|', 'xargs', 'clang-format', '--style=file', '--verbose', '-i'])
def build_tests(with_coverage: bool):
'''
Build all object files and the main executable for tests
'''
cflags = CFLAGS.copy()
if with_coverage:
cflags += CVFLAGS
print("WIP")
def run_tests():
execute_command([TEST_EXE])
def unused():
# Makefile
# Contains many usefull things dealing with tests, code coverage and formatting
print('Updating Makefile...')
file = open(f'Makefile', 'w')
file.write(f'''# This file was generated by a Python script
CC = {CC}
CFLAGS = -std=c11 -Wall -Wextra
CFLAGS += -Wno-missing-braces -DCMC_TEST_COLOR
CVFLAGS = --coverage -O0 -g3
INCLUDE = {INCLUDE_DIR} -I src
# Runs the script to update tests, run all tests and code coverage
all: script coverage
tests: script build
\t{OUTPUT_DIR}/main.exe
# Like build but with coverage
coverage: {' '.join([f'{OBJ_DIR}/{data["LIB"].lower()}/{data["SNAME"]}.o' for data in COLLECTIONS])} {OBJ_DIR}/main.o
\t$(CC) $^ -o {OUTPUT_DIR}/main.exe $(CFLAGS) $(CVFLAGS)
\t{OUTPUT_DIR}/main.exe
\tgcov {OBJ_DIR}/main.o {' '.join([f'{OBJ_DIR}/{data["LIB"].lower()}/{data["SNAME"]}.o' for data in COLLECTIONS])}
# Run without coverage
run: build
\t{OUTPUT_DIR}/main.exe
script:
\tpython autogen.py
clean:
\tfind {BUILD_DIR} -type f -delete
\trm *.gcov
# No coverage build
build: {' '.join([f'{OBJ_DIR}/{data["LIB"].lower()}/{data["SNAME"]}.o' for data in COLLECTIONS])} {OBJ_DIR}/main.o
\t$(CC) $^ -o {OUTPUT_DIR}/main.exe $(CFLAGS)
{OBJ_DIR}/main.o: {OUTPUT_DIR}/main.c
\t$(CC) -c $^ -o $@ -I $(INCLUDE) $(CFLAGS)
''')
else:
cflags += ['-O3']
for data in COLLECTIONS:
file.write(f'''
{OBJ_DIR}/{data['LIB'].lower()}/{data['SNAME']}.o: {SRC_DIR}/{data['LIB'].lower()}/{data['SNAME']}.c {INCLUDE_DIR}/{data['LIB'].lower()}/{data['SNAME']}.h
\t$(CC) -c $< -o $@ -I $(INCLUDE) $(CFLAGS) $(CVFLAGS)
''')
cmd = [CC]
cmd += cflags
cmd += TINCLUDE # This one needs to go first
cmd += INCLUDE
cmd += ['-c', f"{SRC_DIR}/{data['LIB'].lower()}/{data['SNAME']}.c"]
cmd += ['-o', f"{OBJ_DIR}/{data['LIB'].lower()}/{data['SNAME']}.o"]
execute_command(cmd)
file.close()
print('\nDone')
# Build OUTPUT_DIR/main.c
cmd = [CC]
cmd += cflags
cmd += TINCLUDE # This one needs to go first
cmd += INCLUDE
cmd += ['-c', f'{OUTPUT_DIR}/main.c']
cmd += ['-o', f"{OBJ_DIR}/main.o"]
execute_command(cmd)
# Link everything producing OUTPUT_DIR/main.exe
cmd = [CC]
cmd += cflags
cmd += ['-o', TEST_EXE]
cmd += [f'{OBJ_DIR}/main.o']
cmd += [f'{OBJ_DIR}/{data["LIB"].lower()}/{data["SNAME"]}.o' for data in COLLECTIONS]
execute_command(cmd)
def run_tests(coverage: bool):
'''
Runs tests. If coverage, run gcov.
'''
execute_command([full_path(TEST_EXE)])
if coverage:
objects = [f'{OBJ_DIR}/main.o']
objects += [f'{OBJ_DIR}/{data["LIB"].lower()}/{data["SNAME"]}.o' for data in COLLECTIONS]
execute_command(['gcov'] + objects)
if __name__ == '__main__':
@@ -320,6 +328,11 @@ if __name__ == '__main__':
default=False,
action='store_true',
dest='clean')
tests.add_argument('-cf', '--clean-full',
help='Cleans all build objects, source and header files, and removes folders',
default=False,
action='store_true',
dest='cleanfull')
tests.add_argument('-e', '--expand',
help='Expands the header and source files',
default=False,
@@ -330,18 +343,23 @@ if __name__ == '__main__':
default=False,
action='store_true',
dest='noformat')
tests.add_argument('-b', '--build',
help='Compile the object files and the main executable',
default=False,
action='store_true',
dest='build')
tests.add_argument('-r', '--run',
help='Runs tests without code coverage',
help='Runs tests, assuming that it is already built',
default=False,
action='store_true',
dest='run')
tests.add_argument('-cv', '--coverage',
help='Compiles and runs tests with code coverage',
help='Adds the code coverage flags for compilation',
default=False,
action='store_true',
dest='coverage')
tests.add_argument('-rr', '--rerun',
help='Builds tests without code coverage and runs it',
help='Compile the object files again and then run the tests',
default=False,
action='store_true',
dest='rerun')
@@ -365,11 +383,12 @@ if __name__ == '__main__':
print(CONFIG)
exit(0)
if args.clean:
clean_build()
if args.clean or args.cleanfull:
clean_build(args.cleanfull)
assert_structure()
assert_executable(CC)
if not args.cleanfull:
assert_structure()
assert_executable(CC)
if args.expand:
expand_code()
@@ -382,11 +401,12 @@ if __name__ == '__main__':
assert_executable('xargs')
format_code(args.fmt_source, args.fmt_tests)
if args.rerun:
build_tests(False)
run_tests()
if args.build:
build_tests(args.coverage)
if args.run:
run_tests(args.coverage)
elif args.rerun:
build_tests(args.coverage)
run_tests(args.coverage)
elif args.run:
run_tests()
elif args.coverage:
build_tests(True)
run_tests()
run_tests(args.coverage)
+4 -4
View File
@@ -461,8 +461,8 @@
return false; \
} \
\
K max_key; \
V max_val; \
K max_key = (K) { 0 }; \
V max_val = (V) { 0 }; \
size_t first = 0; \
\
for (; first < _map_->capacity; first++) \
@@ -505,8 +505,8 @@
return false; \
} \
\
K min_key; \
V min_val; \
K min_key = (K) { 0 }; \
V min_val = (V) { 0 }; \
size_t first = 0; \
\
for (; first < _map_->capacity; first++) \
+4 -4
View File
@@ -684,8 +684,8 @@
return false; \
} \
\
K max_key; \
V max_val; \
K max_key = (K) { 0 }; \
V max_val = (V) { 0 }; \
\
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map_); \
\
@@ -728,8 +728,8 @@
return false; \
} \
\
K min_key; \
V min_val; \
K min_key = (K) { 0 }; \
V min_val = (V) { 0 }; \
\
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_map_); \
\
+2 -2
View File
@@ -477,7 +477,7 @@
return false; \
} \
\
V max_val; \
V max_val = (V) { 0 }; \
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_); \
\
/* TODO transform this into a normal loop */ \
@@ -510,7 +510,7 @@
return false; \
} \
\
V min_val; \
V min_val = (V) { 0 }; \
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_); \
\
/* TODO transform this into a normal loop */ \
+10 -10
View File
@@ -378,7 +378,7 @@
return false; \
} \
\
V max_value; \
V max_val = (V) { 0 }; \
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_); \
\
/* TODO turn this into a normal loop */ \
@@ -388,13 +388,13 @@
size_t index = CMC_(PFX, _iter_index)(&iter); \
\
if (index == 0) \
max_value = result; \
else if (_set_->f_val->cmp(result, max_value) > 0) \
max_value = result; \
max_val = result; \
else if (_set_->f_val->cmp(result, max_val) > 0) \
max_val = result; \
} \
\
if (value) \
*value = max_value; \
*value = max_val; \
\
_set_->flag = CMC_FLAG_OK; \
\
@@ -411,7 +411,7 @@
return false; \
} \
\
V min_value; \
V min_val = (V) { 0 }; \
struct CMC_DEF_ITER(SNAME) iter = CMC_(PFX, _iter_start)(_set_); \
\
/* TODO turn this into a normal loop */ \
@@ -421,13 +421,13 @@
size_t index = CMC_(PFX, _iter_index)(&iter); \
\
if (index == 0) \
min_value = result; \
else if (_set_->f_val->cmp(result, min_value) < 0) \
min_value = result; \
min_val = result; \
else if (_set_->f_val->cmp(result, min_val) < 0) \
min_val = result; \
} \
\
if (value) \
*value = min_value; \
*value = min_val; \
\
_set_->flag = CMC_FLAG_OK; \
\
+8 -8
View File
@@ -25,14 +25,6 @@ struct queue_fval
size_t (*hash)(size_t);
int (*pri)(size_t, size_t);
};
struct queue_iter
{
struct queue *target;
size_t cursor;
size_t index;
_Bool start;
_Bool end;
};
struct queue *q_new(size_t capacity, struct queue_fval *f_val);
struct queue *q_new_custom(size_t capacity, struct queue_fval *f_val, struct cmc_alloc_node *alloc,
struct cmc_callbacks *callbacks);
@@ -51,6 +43,14 @@ int q_flag(struct queue *_queue_);
_Bool q_resize(struct queue *_queue_, size_t capacity);
struct queue *q_copy_of(struct queue *_queue_);
_Bool q_equals(struct queue *_queue1_, struct queue *_queue2_);
struct queue_iter
{
struct queue *target;
size_t cursor;
size_t index;
_Bool start;
_Bool end;
};
struct queue_iter q_iter_start(struct queue *target);
struct queue_iter q_iter_end(struct queue *target);
_Bool q_iter_at_start(struct queue_iter *iter);
+4 -4
View File
@@ -201,8 +201,8 @@ _Bool hm_max(struct hashmap *_map_, size_t *key, size_t *value)
_map_->flag = CMC_FLAG_EMPTY;
return 0;
}
size_t max_key;
size_t max_val;
size_t max_key = (size_t){ 0 };
size_t max_val = (size_t){ 0 };
size_t first = 0;
for (; first < _map_->capacity; first++)
{
@@ -240,8 +240,8 @@ _Bool hm_min(struct hashmap *_map_, size_t *key, size_t *value)
_map_->flag = CMC_FLAG_EMPTY;
return 0;
}
size_t min_key;
size_t min_val;
size_t min_key = (size_t){ 0 };
size_t min_val = (size_t){ 0 };
size_t first = 0;
for (; first < _map_->capacity; first++)
{
+4 -4
View File
@@ -353,8 +353,8 @@ _Bool hmm_max(struct hashmultimap *_map_, size_t *key, size_t *value)
_map_->flag = CMC_FLAG_EMPTY;
return 0;
}
size_t max_key;
size_t max_val;
size_t max_key = (size_t){ 0 };
size_t max_val = (size_t){ 0 };
struct hashmultimap_iter iter = hmm_iter_start(_map_);
for (; !hmm_iter_at_end(&iter); hmm_iter_next(&iter))
{
@@ -389,8 +389,8 @@ _Bool hmm_min(struct hashmultimap *_map_, size_t *key, size_t *value)
_map_->flag = CMC_FLAG_EMPTY;
return 0;
}
size_t min_key;
size_t min_val;
size_t min_key = (size_t){ 0 };
size_t min_val = (size_t){ 0 };
struct hashmultimap_iter iter = hmm_iter_start(_map_);
for (; !hmm_iter_at_end(&iter); hmm_iter_next(&iter))
{
+2 -2
View File
@@ -218,7 +218,7 @@ _Bool hms_max(struct hashmultiset *_set_, size_t *value)
_set_->flag = CMC_FLAG_EMPTY;
return 0;
}
size_t max_val;
size_t max_val = (size_t){ 0 };
struct hashmultiset_iter iter = hms_iter_start(_set_);
for (; !hms_iter_at_end(&iter); hms_iter_next(&iter))
{
@@ -244,7 +244,7 @@ _Bool hms_min(struct hashmultiset *_set_, size_t *value)
_set_->flag = CMC_FLAG_EMPTY;
return 0;
}
size_t min_val;
size_t min_val = (size_t){ 0 };
struct hashmultiset_iter iter = hms_iter_start(_set_);
for (; !hms_iter_at_end(&iter); hms_iter_next(&iter))
{
+10 -10
View File
@@ -164,19 +164,19 @@ _Bool hs_max(struct hashset *_set_, size_t *value)
_set_->flag = CMC_FLAG_EMPTY;
return 0;
}
size_t max_value;
size_t max_val = (size_t){ 0 };
struct hashset_iter iter = hs_iter_start(_set_);
for (; !hs_iter_at_end(&iter); hs_iter_next(&iter))
{
size_t result = hs_iter_value(&iter);
size_t index = hs_iter_index(&iter);
if (index == 0)
max_value = result;
else if (_set_->f_val->cmp(result, max_value) > 0)
max_value = result;
max_val = result;
else if (_set_->f_val->cmp(result, max_val) > 0)
max_val = result;
}
if (value)
*value = max_value;
*value = max_val;
_set_->flag = CMC_FLAG_OK;
if ((_set_)->callbacks && (_set_)->callbacks->read)
(_set_)->callbacks->read();
@@ -190,19 +190,19 @@ _Bool hs_min(struct hashset *_set_, size_t *value)
_set_->flag = CMC_FLAG_EMPTY;
return 0;
}
size_t min_value;
size_t min_val = (size_t){ 0 };
struct hashset_iter iter = hs_iter_start(_set_);
for (; !hs_iter_at_end(&iter); hs_iter_next(&iter))
{
size_t result = hs_iter_value(&iter);
size_t index = hs_iter_index(&iter);
if (index == 0)
min_value = result;
else if (_set_->f_val->cmp(result, min_value) < 0)
min_value = result;
min_val = result;
else if (_set_->f_val->cmp(result, min_val) < 0)
min_val = result;
}
if (value)
*value = min_value;
*value = min_val;
_set_->flag = CMC_FLAG_OK;
if ((_set_)->callbacks && (_set_)->callbacks->read)
(_set_)->callbacks->read();