#!/usr/bin/env bash CBUILD_VERSION=2.3.1 PROJECT="tcp-chat" CMP_C="gcc" CMP_CPP="g++" STD_C="c99" STD_CPP="c++11" WARN_C="-Wall -Wextra -Wduplicated-branches -Wduplicated-cond -Wformat=2 -Wmissing-include-dirs -Wshadow -Werror=return-type -Werror=pointer-arith -Werror=init-self -Werror=incompatible-pointer-types" WARN_CPP="$WARN_C" SRC_C="$(find src -name '*.c')" SRC_CPP="$(find src -name '*.cpp')" # Directory with dependency configs. # See cbuild/example_dependency_configs DEPENDENCY_CONFIGS_DIR='dependencies' # List of dependency config files in DEPENDENCY_CONFIGS_DIR separated by space. ENABLED_DEPENDENCIES='tlibc bearssl' # OBJDIR structure: # ├── objects/ - Compiled object files. Cleans on each call of build task # ├── static_libs/ - Symbolic links to static libraries used by linker. Cleans on each call of build task. # ├── static_libs/ - Symbolic links to dynamic libraries used by linker. Cleans on each call of build task. # └── profile/ - gcc *.gcda profiling info files OBJDIR="obj" OUTDIR="bin" STATIC_LIB_FILE="$PROJECT.a" INCLUDE="-Isrc -I$DEPENDENCIES_DIR/BearSSL/inc -I$DEPENDENCIES_DIR/tlibc/include" # OS-specific options case "$OS" in WINDOWS) EXEC_FILE="$PROJECT.exe" SHARED_LIB_FILE="$PROJECT.dll" INCLUDE="$INCLUDE " LINKER_LIBS="-static -lpthread -lws2_32" ;; LINUX) EXEC_FILE="$PROJECT" SHARED_LIB_FILE="$PROJECT.so" INCLUDE="$INCLUDE " 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="@cbuild/default_tasks/strip_exec.sh" ;; # 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 $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE" 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 $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE" 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=$(pwd)/ --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" # arguments that emit some call counter code and disable optimizations to see function names # https://github.com/msys2/MINGW-packages/issues/8503#issuecomment-1365475205 C_ARGS="-O0 -g -pg -no-pie -fno-omit-frame-pointer -fno-inline-functions -fno-inline-functions-called-once -fno-optimize-sibling-calls -fopenmp" 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="@cbuild/default_tasks/build_exec.sh" TASK_SCRIPT="@cbuild/default_tasks/callgrind.sh" POST_TASK_SCRIPT="" ;; # 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="" ;; # rebuilds specified dependencies # EXAMPLE: `cbuild rebuild_dependencies=libexample1,fonts` # 'all' can be specified to rebuild all dependencies rebuild_dependencies) TASK_SCRIPT="@cbuild/default_tasks/rebuild_dependencies.sh" ;; # deletes generated files clean) TASK_SCRIPT="@cbuild/default_tasks/clean.sh" ;; # nothing to do "" | no_task) ;; # unknown task *) error "task <$PROJECT/$TASK> not found" ;; esac