Compare commits

..

10 Commits

Author SHA1 Message Date
60fa8c11c2 small bug fix 2023-07-10 17:03:20 +03:00
ef6a3f82c4 v7 2023-05-24 22:19:33 +06:00
5e23ef8156 force valgrind output on crash 2023-05-19 23:44:33 +06:00
9711d8fbb1 build_static_lib 2023-05-19 19:44:18 +06:00
991ee072b3 changelog 2023-05-19 19:31:22 +06:00
888b1e05e7 build_exec dead code removal 2023-05-19 19:30:44 +06:00
e8e42424d3 removed unnececary out file copy 2023-05-19 14:09:06 +06:00
dc5947f92d basic android compatibility 2023-05-19 13:36:35 +06:00
e83a7affef clean func 2023-04-01 15:55:17 +06:00
2bebe76c7e moved LNKER_ARGS to the end of command 2023-03-31 16:55:30 +06:00
10 changed files with 198 additions and 56 deletions

View File

@ -1,8 +1,20 @@
# 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`
+ default C++ standard set to `c++11`
+ added `INCLUDE` to `default.config`
+ moved `LINKER_ARGS` to the end of linkage command in `functions.sh` to properly link static libs
+ added function `try_delete_dir_or_file` for `clean` task
+ dead code removal in `build_exec` and `build_static_lib`
# v5
+ added task `clean`

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,14 +14,23 @@ 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
# └── out - output files are created here and then copied to OUTDIR
# ├── 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
@ -50,7 +59,8 @@ case "$TASK" in
# -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
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
# -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"
PRE_TASK_SCRIPT=
@ -86,7 +96,7 @@ case "$TASK" in
;;
# creates static library
build_static_lib)
C_ARGS="-O2 -fpic"
C_ARGS="-O2 -fpic -fdata-sections -ffunction-sections"
CPP_ARGS="$C_ARGS"
PRE_TASK_SCRIPT=
TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh
@ -106,7 +116,7 @@ case "$TASK" in
;;
# executes $EXEC_FILE with valgrind memory checker
valgrind)
VALGRIND_ARGS="-s --log-file=valgrind.log --read-var-info=yes --track-origins=yes --fullpath-after=$PROJECT/ --leak-check=full --show-leak-kinds=all"
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
@ -138,6 +148,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 +176,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

@ -1,6 +1,23 @@
#!/usr/bin/bash
delete_dir "$OBJDIR"
delete_dir "$OUTDIR"
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,10 @@
#!/bin/bash
cd "$OUTDIR"
valgrind $VALGRIND_ARGS ./$EXEC_FILE
cat "valgrind.log"
myprint "${GREEN}valgrind log saved to ${CYAN}$OUTDIR/exec.log"
rm -f "valgrind.log"
set +e
valgrind --log-file=valgrind.log $VALGRIND_ARGS ./$EXEC_FILE
set -e
[ -f "valgrind.log" ] && cat "valgrind.log" || error "valgrind exited with errors"
myprint "${GREEN}valgrind log saved to ${CYAN}$OUTDIR/valgrind.log"
cd ..

View File

@ -9,10 +9,7 @@ case "$uname_rezult" in
Msys | Cygwin | "MS/Windows")
OS=WINDOWS
;;
GNU/Linux)
OS=LINUX
;;
Linux)
Linux | GNU/Linux | Android)
OS=LINUX
;;
FreeBSD)

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 {
@ -22,6 +23,14 @@ function delete_dir {
rm -rf "$dir"
}
function try_delete_dir_or_file {
local path="$1"
if [ -f "$path" ] || [ -d "$path" ]; then
rm -rf "$path"
myprint "${WHITE}deleting $path"
fi
}
function compile {
local cmp="$1"
@ -36,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)
@ -69,28 +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"
clean_dir $OBJDIR/out
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 $args $(echo "$objects" | tr '\n' ' ') -o $OBJDIR/out/$outfile"
myprint "$command"
if $command
then
cp "$OBJDIR/out/$outfile" "$OUTDIR/$outfile"
myprint "${GREEN}file $CYAN$outfile ${GREEN}created"
else
error "some error happened"
fi
}
# (outfile)
function pack_static_lib {
myprint "${CYAN}----------[pack_static_lib]-----------"
@ -99,9 +77,76 @@ function pack_static_lib {
local objects="$(find $OBJDIR/objects -name *.o)
$(find $OBJDIR/libs -name '*.a')"
myprint "${BLUE}objects: ${GRAY}$objects"
if gcc-ar rcs -o "$OBJDIR/out/$outfile" $(echo "$objects" | tr '\n' ' ')
if ar rcs "$OUTDIR/$outfile" $(echo "$objects" | tr '\n' ' ')
then
myprint "${GREEN}file $CYAN$outfile ${GREEN}created"
else
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
cp "$OBJDIR/out/$outfile" "$OUTDIR/$outfile"
myprint "${GREEN}file $CYAN$outfile ${GREEN}created"
else
error "some error happened"

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
@ -69,7 +71,6 @@ mkdir -p "$OUTDIR"
mkdir -p "$OBJDIR/libs"
mkdir -p "$OBJDIR/objects"
mkdir -p "$OBJDIR/profile"
mkdir -p "$OBJDIR/out"
# dont thorw error on undefined variable
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"