#!/bin/bash CBUILD_VERSION=7 CONFIG_VERSION=8 PROJECT="kerep" CMP_C="gcc" CMP_CPP="g++" STD_C="c11" STD_CPP="c++11" WARN_C="-Wall -Wno-discarded-qualifiers -Wextra -Wno-unused-parameter" WARN_CPP="-Wall -Wextra -Wno-unused-parameter" SRC_C="$( find src -name '*.c')" SRC_CPP="$( find src -name '*.cpp')" TESTS_C="$( find tests -name '*.c')" TESTS_CPP="$(find tests -name '*.cpp')" # dir with dependeicy dirs DEPS_BASEDIR="." # EXAMPLE: "dependency_dir='build_task out_dir lib_file' # other_depndency_dir=..." # Dependencies must be declared on separate lines # Values can be override by resetting one of dependencies: # DEPS="$DEPS # dependency_dir='...'" DEPS="" # OBJDIR structure: # ├── objects/ - dir where compiled *.o files are stored. cleans every call of build task # ├── profile/ - dir where gcc *.gcda profiling info files stored # └── libs/ - there you can put static libs and linker will find them OBJDIR="obj" OUTDIR="bin" STATIC_LIB_FILE="lib$PROJECT.a" # OS-specific options case "$OS" in WINDOWS) EXEC_FILE="$PROJECT.exe" SHARED_LIB_FILE="$PROJECT.dll" LINKER_LIBS="-lws2_32" ;; LINUX) EXEC_FILE="$PROJECT" SHARED_LIB_FILE="$PROJECT.so" LINKER_LIBS="" ;; *) error "operating system $OS has no configuration variants" ;; esac # TASKS case "$TASK" in # creates executable using profiling info if it exists build_exec) # -flto applies more optimizations across object files # -flto=auto is needed to multithreaded copilation # -fuse-linker-plugin is required to use static libs with lto # -fprofile-use enables compiler to use profiling info files to optimize executable # -fprofile-prefix-path sets path where profiling info about objects are be saved # -fdata-sections -ffunction-sections -Wl,--gc-sections removes unused code C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects -fdata-sections -ffunction-sections -Wl,--gc-sections" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_exec.sh POST_TASK_SCRIPT= ;; # creates executable with debug info and no optimizations build_exec_dbg) C_ARGS="-O0 -g3" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_exec.sh POST_TASK_SCRIPT= ;; # creates shared library build_shared_lib) C_ARGS="-O2 -fpic -flto -shared" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS -Wl,-soname,$SHARED_LIB_FILE $LINKER_LIBS" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh POST_TASK_SCRIPT= ;; # creates shared library with debug symbols and no optimizations build_shared_lib_dbg) C_ARGS="-O0 -g3 -fpic -shared" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS -Wl,-soname,$SHARED_LIB_FILE $LINKER_LIBS" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh POST_TASK_SCRIPT= ;; # creates static library build_static_lib) C_ARGS="-O2 -fpic -fdata-sections -ffunction-sections" CPP_ARGS="$C_ARGS" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh POST_TASK_SCRIPT= ;; # creates static library with debug symbols and no optimizations build_static_lib_dbg) C_ARGS="-O0 -g3" CPP_ARGS="$C_ARGS" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh POST_TASK_SCRIPT= ;; # executes $EXEC_FILE exec) TASK_SCRIPT=cbuild/default_tasks/exec.sh ;; # executes $EXEC_FILE with valgrind memory checker valgrind) VALGRIND_ARGS="-s --read-var-info=yes --track-origins=yes --fullpath-after=$PROJECT/ --leak-check=full --show-leak-kinds=all" TASK_SCRIPT=cbuild/default_tasks/valgrind.sh ;; # generates profiling info profile) OUTDIR="$OUTDIR/profile" # -flto applies more optimizations across object files # -flto=auto is needed to multithreaded copilation # -fuse-linker-plugin is required to use static libs with lto # -pg adds code to executable, that generates file containing function call info (gmon.out) # -fprofile-generate generates executable with profiling code # -fprofile-prefix-path sets path where profiling info about objects will be saved C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh TASK_SCRIPT=cbuild/default_tasks/profile.sh POST_TASK_SCRIPT= ;; # compiles program with -pg and runs it with gprof # uses gprof2dot python script to generate function call tree (pip install gprof2dot) # requires graphviz (https://www.graphviz.org/download/source/) gprof) OUTDIR="$OUTDIR/gprof" # -pg adds code to executable, that generates file containing function call info (gmon.out) C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh TASK_SCRIPT=cbuild/default_tasks/gprof.sh POST_TASK_SCRIPT= ;; # compiles program and runs it with callgrind (part of valgrind) # uses gprof2dot python script to generate function call tree (pip install gprof2dot) # requires graphviz (https://www.graphviz.org/download/source/) # P.S. detailed results can be viewed in KCacheGrind callgrind) OUTDIR="$OUTDIR/callgrind" # -pg adds code to executable, that generates file containing function call info (gmon.out) C_ARGS="-O2 -flto=auto -fuse-linker-plugin" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=tasks/pre_build.sh TASK_SCRIPT=cbuild/default_tasks/build_exec.sh POST_TASK_SCRIPT=cbuild/default_tasks/callgrind.sh ;; # compiles executable with sanitizers and executes it to find errors and warnings sanitize) OUTDIR="$OUTDIR/sanitize" C_ARGS="-O0 -g3 -fsanitize=undefined,address" CPP_ARGS="$C_ARGS" LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh TASK_SCRIPT=cbuild/default_tasks/exec.sh POST_TASK_SCRIPT= ;; # deletes generated files clean) TASK_SCRIPT=cbuild/default_tasks/clean.sh ;; # nothing to do no_task) ;; # unknown task *) error "task <$TASK> not found" ;; esac