This commit is contained in:
Timerix22 2023-05-24 22:19:33 +06:00
parent 5e23ef8156
commit ef6a3f82c4
8 changed files with 171 additions and 35 deletions

View File

@ -1,3 +1,12 @@
# v7
+ added function `resolve_dependencies` to `link`
+ added variables `DEPS_BASEDIR` and `DEPS` to config
+ added script `rebuild_dep.sh` which can be called through `Makefile`
+ added dependency cleaning in `default_tasks/clean.sh`
+ added task `callgrind`
+ added task `no_task` which is been set in `init.sh` when `TASK` is empty
+ now `STATIC_LIB_FILE` starts with "lib"
# v6
+ `build_profile` task was split to `profile` and `gprof`
+ added task `sanitize`

View File

@ -28,6 +28,12 @@ build_static_lib:
build_static_lib_dbg:
@cbuild/call_task.sh build_static_lib_dbg 2>&1 | tee make_raw.log
# recompile libsome_dep.a in the next build task
#rebuild_some_dep:
# @cbuild/rebuild_dep.sh libsome_dep.a 2>&1 | tee make_raw.log
#rebuild_all: rebuild_some_dep
######################################
###### Launch tasks #######
######################################
@ -49,10 +55,18 @@ profile:
@cbuild/call_task.sh profile 2>&1 | tee make_raw.log
# compiles program with -pg and runs it with gprof
# uses gprof2dot python script to generate function call tree
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
# requires graphviz (https://www.graphviz.org/download/source/)
gprof:
@cbuild/call_task.sh gprof 2>&1 | tee make_raw.log
# 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 rezults can be viewed in KCacheGrind
callgrind:
@cbuild/call_task.sh callgrind 2>&1 | tee make_raw.log
# compiles executable with sanitizers and executes it to find errors and warnings
sanitize:
@cbuild/call_task.sh sanitize 2>&1 | tee make_raw.log

View File

@ -1,5 +1,5 @@
#!/bin/bash
CBUILD_VERSION=6
CBUILD_VERSION=7
CONFIG_VERSION=1
PROJECT="NULL"
@ -14,13 +14,24 @@ 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="$PROJECT.a"
STATIC_LIB_FILE="lib$PROJECT.a"
# OS-specific options
case "$OS" in
@ -138,6 +149,20 @@ case "$TASK" in
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 rezults 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"
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"
@ -152,6 +177,9 @@ case "$TASK" in
clean)
TASK_SCRIPT=cbuild/default_tasks/clean.sh
;;
# nothing to do
no_task)
;;
# unknown task
*)
error "task <$TASK> not found"

View File

@ -0,0 +1,19 @@
#!/bin/bash
cd "$OUTDIR"
# deleting all files except excutable
echo "$(find . ! -name $EXEC_FILE -type f -delete)"
# executing file with callgrind
myprint "${BLUE}executing $OUTDIR/$EXEC_FILE"
valgrind --tool=callgrind --callgrind-out-file=callgrind.out ./$EXEC_FILE > exec.log
myprint "${GREEN}execution log saved to ${CYAN}$OUTDIR/exec.log"
# exit 0
# generating function call graph
myprint "${BLUE}generating function call graph..."
gprof2dot -f callgrind callgrind.out > gprof2dot.graph
dot gprof2dot.graph -Tpng -Gdpi=300 -o gprof2dot.png
myprint "${GREEN}function call graph saved to ${CYAN}$OUTDIR/gprof2dot.png"
cd ../..

View File

@ -4,3 +4,20 @@ try_delete_dir_or_file "$OBJDIR"
try_delete_dir_or_file "$OUTDIR"
myprint "${WHITE}deleting build logs"
rm -rf *.log
for tmpfile in $(ls -a | grep -e '\.rebuild.*\.tmp'); do
try_delete_dir_or_file "$tmpfile"
done
set +e
OLDIFS="$IFS"
IFS=$'\n'
for dep in $DEPS; do
dep_dir=$(echo ${dep/=*/} | tr -d '[:blank:]')
myprint "${CYAN}--------------[$dep_dir]--------------"
cd "$DEPS_BASEDIR/$dep_dir"
make clean
cd ..
done
IFS="$OLDIFS"
set -e

View File

@ -1,7 +1,8 @@
#!/bin/bash
function myprint {
printf "$@${GRAY}\n"
# first gray is needed to print string trarting with -
printf "${GRAY}$@${GRAY}\n"
}
function error {
@ -44,25 +45,16 @@ function compile {
myprint "${BLUE}include dirs: ${GRAY}$include"
local sources="$6"
myprint "${BLUE}sources: ${GRAY}$sources"
local compilation_error=0
for srcfile in $sources
do (
local object="$OBJDIR/objects/$(basename $srcfile).o"
if ! $($cmp -std=$std $warn $args $include -c -o $object $srcfile)
then
error "some error happened"
#TODO parallel variable assignement doesnt work in bash
compilation_error=1
# TODO stop all threads
fi
) & done
wait
#TODO doesnt work with multithreading
if [ $compilation_error != 0 ]
then
exit -50
fi
}
# (args, sources)
@ -77,26 +69,6 @@ function compile_cpp {
compile "$CMP_CPP" "$STD_CPP" "$WARN_CPP" "$1" "$INCLUDE" "$2"
}
# (args, outfile)
function link {
myprint "${CYAN}----------------[link]----------------"
local args="$1"
myprint "${BLUE}args: ${GRAY}$args"
local outfile="$2"
myprint "${BLUE}outfile: ${GRAY}$outfile"
local objects="$(find $OBJDIR/objects -name '*.o')
$(find $OBJDIR/libs -name '*.a')"
myprint "${BLUE}objects: ${GRAY}$objects"
local command="$CMP_CPP $(echo "$objects" | tr '\n' ' ') $args -o $OUTDIR/$outfile"
myprint "$command"
if $command
then
myprint "${GREEN}file $CYAN$outfile ${GREEN}created"
else
error "some error happened"
fi
}
# (outfile)
function pack_static_lib {
myprint "${CYAN}----------[pack_static_lib]-----------"
@ -112,3 +84,71 @@ $(find $OBJDIR/libs -name '*.a')"
error "some error happened"
fi
}
# if $lib_file doesn't exist or rebuild_* task was executed, builds static lib
function handle_static_dependency {
local deps_basedir="$1"
local lib_project_dir="$2"
local lib_build_task="$3"
local lib_build_dir="$4"
local lib_file="$5"
if [ ! -f "$OBJDIR/libs/$lib_file" ] || [ -f .rebuild_$lib_file.tmp ]; then
[[ -z "$lib_build_task" ]] && error "lib_build_task is empty"
myprint "${BLUE}making $lib_file by task $lib_build_task"
cd "$deps_basedir/$lib_project_dir"
if ! make "$lib_build_task"; then
exit 1
fi
cd ..
cp "$deps_basedir/$lib_project_dir/$lib_build_dir/$lib_file" "$OBJDIR/libs/"
myprint "${GREEN}copied ${CYAN}$lib_file to $OBJDIR/libs/"
rm -f .rebuild_$lib_file.tmp
fi
}
function resolve_dependencies {
deps_basedir=$1
deps=$2
[[ -z "$deps_basedir" ]] && deps_basedir=.
OLDIFS="$IFS"
IFS=$'\n'
# Evalueting dependency expressions.
# Necessary for overriding dependency configurations.
for dep in $deps; do
eval $dep
done
# handling dependencies
for dep in $deps; do
IFS="$OLDIFS"
dep_dir=$(echo ${dep/=*/} | tr -d '[:blank:]')
eval 'dep_params=$'$dep_dir
f_args="$deps_basedir $dep_dir $dep_params"
myprint "${BLUE}resolving dependency ${WHITE}$dep_dir${BLUE}: ${GRAY}$f_args"
handle_static_dependency $f_args
IFS=$'\n'
done
IFS="$OLDIFS"
}
function link {
myprint "${CYAN}----------------[link]----------------"
local args="$1"
local outfile="$2"
resolve_dependencies "$DEPS_BASEDIR" "$DEPS"
myprint "${BLUE}args: ${GRAY}$args"
myprint "${BLUE}outfile: ${GRAY}$outfile"
local objects="$(find $OBJDIR/objects -name '*.o')
$(find $OBJDIR/libs -name '*.a')"
myprint "${BLUE}objects: ${GRAY}$objects"
local command="$CMP_CPP $(echo "$objects" | tr '\n' ' ') $args -o $OUTDIR/$outfile"
myprint "$command"
if $command
then
myprint "${GREEN}file $CYAN$outfile ${GREEN}created"
else
error "some error happened"
fi
}

View File

@ -35,6 +35,8 @@ exec_script_line default.config 3
DEFAULT_CONFIG_VERSION="$CONFIG_VERSION"
unset CONFIG_VERSION
# undefined task
[ -z "$TASK" ] && TASK="no_task"
# error on undefined
set -u

7
rebuild_dep.sh Normal file
View File

@ -0,0 +1,7 @@
#!/bin/bash
source "cbuild/init.sh"
target_file="$1"
touch ".rebuild_$target_file.tmp"
rm -fv "$OBJDIR/libs/$target_file.a"
myprint "${YELLOW}dependency ${WHITE}$target_file ${YELLOW}will be rebuilt with the next build task"