build_profile, make.log and other stuff

This commit is contained in:
Timerix22 2023-02-13 19:24:47 +06:00
parent 1b38b43c54
commit a0cdbf5522
15 changed files with 315 additions and 140 deletions

View File

@ -1,24 +1,23 @@
#!/bin/bash
function call_task {
TASK=$1
printf "${CYAN}===========[$TASK]===========\n"
source cbuild/init.sh
function exec_script {
myprint "${BLUE}executing $1"
source "$1"
}
clear_dir $OBJDIR
if [ -f "$PRE_TASK_SCRIPT" ]; then
printf "${BLUE}executing $PRE_TASK_SCRIPT\n"
source "$PRE_TASK_SCRIPT"
fi
source $TASK_SCRIPT
printf "${GRAY}"
if [ -f "$POST_TASK_SCRIPT" ]; then
printf "${BLUE}executing $POST_TASK_SCRIPT\n"
source "$POST_TASK_SCRIPT"
function try_exec_script {
if [ -f "$1" ]; then
exec_script "$1"
fi
}
time call_task $1
function call_task {
TASK="$1"
source cbuild/init.sh
myprint "${CYAN}===========[$TASK]==========="
try_exec_script "$PRE_TASK_SCRIPT"
exec_script "$TASK_SCRIPT"
try_exec_script "$POST_TASK_SCRIPT"
}
time call_task "$1"

View File

@ -2,6 +2,6 @@
SCRIPTS="$(find ./ -name '*.sh')"
for F in $SCRIPTS
do
echo $F
chmod +x $F
echo "$F"
chmod +x "$F"
done

View File

@ -1,24 +1,68 @@
all: build_exec
######################################
###### Build tasks #######
######################################
###### Build cbuild/default_tasks #######
build_exec:
@cbuild/call_task.sh build_exec
all: build_exec_dbg
# generates different profile info
build_profile:
@cbuild/call_task.sh build_profile 2>&1 | tee make_raw.log
# creates executable using profile info generated by build_profile
build_exec: build_profile
@cbuild/call_task.sh build_exec 2>&1 | tee -a make_raw.log
# creates executable with debug info and no optimizations
build_exec_dbg:
@cbuild/call_task.sh build_exec_dbg
@cbuild/call_task.sh build_exec_dbg 2>&1 | tee make_raw.log
# creates shared library
build_shared_lib:
@cbuild/call_task.sh build_shared_lib
@cbuild/call_task.sh build_shared_lib 2>&1 | tee make_raw.log
# creates shared library with debug symbols and no optimizations
build_shared_lib_dbg:
@cbuild/call_task.sh build_shared_lib_dbg
@cbuild/call_task.sh build_shared_lib_dbg 2>&1 | tee make_raw.log
# creates static library
build_static_lib:
@cbuild/call_task.sh build_static_lib
@cbuild/call_task.sh build_static_lib 2>&1 | tee make_raw.log
# creates static library with debug symbols and no optimizations
build_static_lib_dbg:
@cbuild/call_task.sh build_static_lib_dbg
@cbuild/call_task.sh build_static_lib_dbg 2>&1 | tee make_raw.log
###### Launch cbuild/default_tasks #######
######################################
###### Launch tasks #######
######################################
# executes $EXEC_FILE
exec: build_exec
@cbuild/call_task.sh exec
@cbuild/call_task.sh exec 2>&1 | tee -a make_raw.log
# executes $EXEC_FILE
exec_dbg: build_exec_dbg
@cbuild/call_task.sh exec_dbg 2>&1 | tee -a make_raw.log
# executes $EXEC_FILE with valgrind memory checker
valgrind: build_exec_dbg
@cbuild/call_task.sh valgrind
@cbuild/call_task.sh valgrind 2>&1 | tee -a make_raw.log
######################################
###### Other tasks #######
######################################
# deletes generated files
clean:
@cbuild/call_task.sh clean 2>&1 | tee make_raw.log
# removes all unreadable characters copied from stdio
fix_log:
sed 's/[^[:blank:][:print:]]//g' make_raw.log \
| sed 's/\[0;[0-9][0-9]m//g' \
| sed 's/\[0;[0-9]m//g' \
| sed 's/\[[0-9][0-9]m//g' \
| sed 's/\[[0-9]m//g' \
| sed 's/ H //g' \
| sed 's/\[3gH //g' \
> make_fixed.log

View File

@ -1,5 +1,5 @@
#!/bin/bash
CBUILD_VERSION=4
CBUILD_VERSION=5
CONFIG_VERSION=1
PROJECT="NULL"
@ -14,77 +14,117 @@ SRC_CPP="$( find src -name '*.cpp')"
#TESTS_C="$( find tests -name '*.c')"
#TESTS_CPP="$(find tests -name '*.cpp')"
OUTDIR=bin
OBJDIR=obj
STATIC_LIB_FILE=$PROJECT.a
# 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
OBJDIR="obj"
OUTDIR="bin"
STATIC_LIB_FILE="$PROJECT.a"
case $OS in
# OS-specific options
case "$OS" in
WINDOWS)
EXEC_FILE=$PROJECT.exe
SHARED_LIB_FILE=$PROJECT.dll
EXEC_FILE="$PROJECT.exe"
SHARED_LIB_FILE="$PROJECT.dll"
;;
LINUX)
EXEC_FILE=$PROJECT
SHARED_LIB_FILE=$PROJECT.so
EXEC_FILE="$PROJECT.P"
SHARED_LIB_FILE="$PROJECT.so"
;;
*)
printf "${RED}operating system $OS has no configuration variants\n"
exit 1
error "operating system $OS has no configuration variants"
;;
esac
case $TASK in
build_exec)
C_ARGS="-O2"
# TASKS
case "$TASK" in
# generates different profile info
build_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, it strips away all
# -pg adds code to executable, that generates file containing function call info (gmon.out)
# -fprofile-generate
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
CPP_ARGS="$C_ARGS"
LINKER_ARGS=""
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
PRE_TASK_SCRIPT=
LINKER_ARGS="$CPP_ARGS"
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
TASK_SCRIPT=cbuild/default_tasks/profile.sh
POST_TASK_SCRIPT=
;;
# creates executable using profile info generated by build_profile
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, it strips away all
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS"
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 -g"
CPP_ARGS="$C_ARGS"
LINKER_ARGS=""
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
LINKER_ARGS="$CPP_ARGS"
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="-Wl,-soname,$SHARED_LIB_FILE"
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
LINKER_ARGS="$CPP_ARGS -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 -g -fpic -shared"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="-Wl,-soname,$SHARED_LIB_FILE"
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
LINKER_ARGS="$CPP_ARGS -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"
CPP_ARGS="$C_ARGS"
TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh
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 -g"
CPP_ARGS="$C_ARGS"
TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh
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 --log-file=valgrind.log --read-var-info=yes --track-origins=yes --fullpath-after=$PROJECT/ --leak-check=full --show-leak-kinds=all"
TASK_SCRIPT=cbuild/default_tasks/valgrind.sh
;;
# deletes generated files
clean)
TASK_SCRIPT=cbuild/default_tasks/clean.sh
;;
# unknown task
*)
error "task <$TASK> not found"
;;
esac

View File

@ -1,5 +1,19 @@
#!/bin/bash
# delete old objects
clean_dir "$OBJDIR/objects"
# copy profiling info
prof_files=$(find "$OBJDIR/profile/" -name '*.gcda')
if [ -z "$prof_files" ]; then
myprint "${YELLOW}no profiling info found"
else
for prof_file in $prof_files; do
myprint "${GRAY}$(basename $prof_file)"
cp $prof_file "$OBJDIR/objects/"
done
fi
compile_c "$C_ARGS" "$SRC_C $TESTS_C"
compile_cpp "$CPP_ARGS" "$SRC_CPP $TESTS_CPP"
link "$CPP_ARGS" "$EXEC_FILE"
link "$LINKER_ARGS" "$EXEC_FILE"

View File

@ -1,5 +1,7 @@
#!/bin/bash
# delete old objects
clean_dir "$OBJDIR/objects"
compile_c "$C_ARGS" "$SRC_C"
compile_cpp "$CPP_ARGS" "$SRC_CPP"
link "$CPP_ARGS" "$SHARED_LIB_FILE"
link "$LINKER_ARGS" "$SHARED_LIB_FILE"

View File

@ -1,5 +1,7 @@
#!/bin/bash
# delete old objects
clean_dir "$OBJDIR/objects"
compile_c "$C_ARGS" "$SRC_C"
compile_cpp "$CPP_ARGS" "$SRC_CPP"
pack_static_lib "$STATIC_LIB_FILE"

4
default_tasks/clean.sh Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/bash
delete_dir "$OBJDIR"
delete_dir "$OUTDIR"

View File

@ -1,5 +1,5 @@
#!/bin/bash
cd $OUTDIR
cd "$OUTDIR"
./$EXEC_FILE
cd ..

25
default_tasks/profile.sh Normal file
View File

@ -0,0 +1,25 @@
#!/bin/bash
cd "$OUTDIR"
# deleting all files except excutable
echo "$(find . ! -name $EXEC_FILE -type f -delete)"
# executing file compiled with -pg and -fprofile-gen
myprint "${BLUE}executing $OUTDIR/$EXEC_FILE"
./$EXEC_FILE > exec.log
myprint "${GREEN}execution log saved to ${CYAN}$OUTDIR/exec.log"
# moving *.gcda files from $OBJDIR/objects to $OBJDIR/profile
clean_dir ../../$OBJDIR/profile
mv ../../$OBJDIR/objects/*.gcda ../../$OBJDIR/profile/
myprint "${GREEN}$(ls ../../$OBJDIR/profile | wc -l) *.gcda profiling files have written to $OBJDIR/profile"
# generating function call graph
myprint "${BLUE}generating function call graph..."
gprof ./$EXEC_FILE > gprof.log
gprof2dot gprof.log > 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,7 @@
#!/bin/bash
cd $OUTDIR
cd "$OUTDIR"
valgrind $VALGRIND_ARGS ./$EXEC_FILE
cat "valgrind.log"
myprint "${GREEN}valgrind log saved to ${CYAN}$OUTDIR/exec.log"
cd ..

View File

@ -2,10 +2,10 @@
source cbuild/colors.sh
uname_rezult=$(uname -o);
printf "${GRAY}uname rezult: '$uname_rezult'\n"
uname_rezult="$(uname -o)"
myprint "${GRAY}uname rezult: '$uname_rezult'"
case $uname_rezult in
case "$uname_rezult" in
Msys | Cygwin | "MS/Windows")
OS=WINDOWS
;;
@ -19,9 +19,8 @@ case $uname_rezult in
OS=MACOS
;;
*)
printf "${RED}unknown operating system: $uname_rezult\n"
exit 1
error "unknown operating system: $uname_rezult"
;;
esac
printf "${GREEN}detected OS: $OS\n"
myprint "${GREEN}detected OS: $OS"

View File

@ -1,88 +1,107 @@
#!/bin/bash
function clear_dir {
printf "${BLUE}clearing $1\n${GRAY}"
rm -rf $1
mkdir $1
function myprint {
printf "$@${GRAY}\n"
}
function error {
myprint "${RED}$1"
exit 1
}
function clean_dir {
local dir="$1"
myprint "${WHITE}cleaning $dir"
rm -rf "$dir"
mkdir "$dir"
}
function delete_dir {
local dir="$1"
myprint "${WHITE}deleting $dir"
rm -rf "$dir"
}
function compile {
local cmp=$1
printf "${BLUE}compiler: ${GRAY}$cmp\n"
local std=$2
printf "${BLUE}standard: ${GRAY}$std\n"
local warn=$3
printf "${BLUE}warnings: ${GRAY}$warn\n"
local args=$4
printf "${BLUE}args: ${GRAY}$args\n"
local sources=$5
printf "${BLUE}sources: ${GRAY}$sources\n"
local cmp="$1"
myprint "${BLUE}compiler: ${GRAY}$cmp"
local std="$2"
myprint "${BLUE}standard: ${GRAY}$std"
local warn="$3"
myprint "${BLUE}warnings: ${GRAY}$warn"
local args="$4"
myprint "${BLUE}args: ${GRAY}$args"
local sources="$5"
myprint "${BLUE}sources: ${GRAY}$sources"
local compilation_error=0
for srcfile in $sources
do (
local object="$OBJDIR/$(basename $srcfile).o"
local object="$OBJDIR/objects/$(basename $srcfile).o"
if ! $($cmp -std=$std $warn $args -c -o $object $srcfile)
then
printf "${RED}some error happened\n"
error "some error happened"
#TODO parallel variable assignement doesnt work in bash
compilation_error=1
fi
) & done
wait
printf "${GRAY}"
#TODO doesnt work with multithreading
if [ $compilation_error != 0 ]
then
exit 1
exit -50
fi
}
# (args, sources)
function compile_c {
printf "${CYAN}-------------[compile_c]--------------\n"
compile $CMP_C $STD_C "$WARN_C" "$1" "$2"
myprint "${CYAN}-------------[compile_c]--------------"
compile "$CMP_C" "$STD_C" "$WARN_C" "$1" "$2"
}
# (args, sources)
function compile_cpp {
printf "${CYAN}------------[compile_cpp]-------------\n"
compile $CMP_CPP $STD_CPP "$WARN_CPP" "$1" "$2"
myprint "${CYAN}------------[compile_cpp]-------------"
compile "$CMP_CPP" "$STD_CPP" "$WARN_CPP" "$1" "$2"
}
# (args, outfile)
function link {
printf "${CYAN}----------------[link]----------------\n"
local args=$1
printf "${BLUE}args: ${GRAY}$args\n"
local outfile=$OUTDIR/$2
printf "${BLUE}outfile: ${GRAY}$outfile\n"
local objects="$(find $OBJDIR -name '*.o')
$(find $OBJDIR -name '*.a')"
printf "${BLUE}objects: ${GRAY}$objects\n"
local command="$CMP_CPP $args $(echo $objects | tr '\n' ' ') $LINKER_ARGS -o $outfile"
printf "$command\n"
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
printf "${GREEN}file $CYAN$outfile ${GREEN}created\n${GRAY}"
cp "$OBJDIR/out/$outfile" "$OUTDIR/$outfile"
myprint "${GREEN}file $CYAN$outfile ${GREEN}created"
else
printf "${RED}some error happened\n${GRAY}"
exit 1
error "some error happened"
fi
}
# (outfile)
function pack_static_lib {
printf "${CYAN}----------[pack_static_lib]-----------\n"
local outfile=$OUTDIR/$1
printf "${BLUE}outfile: ${GRAY}$outfile\n"
local objects="$(find $OBJDIR -name *.o)"
printf "${BLUE}objects: ${GRAY}$objects\n"
if ar rcs $outfile $(echo $objects | tr '\n' ' ')
myprint "${CYAN}----------[pack_static_lib]-----------"
local outfile="$OUTDIR/$1"
myprint "${BLUE}outfile: ${GRAY}$outfile"
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' ' ')
then
printf "${GREEN}file $CYAN$outfile ${GREEN}created\n${GRAY}"
cp "$OBJDIR/out/$outfile" "$OUTDIR/$outfile"
myprint "${GREEN}file $CYAN$outfile ${GREEN}created"
else
printf "${RED}some error happened\n${GRAY}"
exit 1
error "some error happened"
fi
}

59
init.sh
View File

@ -1,24 +1,39 @@
#!/bin/bash
# exit on errors
set -eo pipefail
tabs 4
source cbuild/colors.sh
source cbuild/functions.sh
source cbuild/detect_os.sh
# exit on errors
set -eo pipefail
# copying default config from cbuild if it not exists
if [ ! -f default.config ]; then
cp cbuild/default.config default.config
printf "${YELLOW}Default config didn't exist, copied from cbuild.\n"
myprint "${YELLOW}Default config didn't exist, copied from cbuild."
fi
source ./default.config
# getting some values from default config
DEFAULT_CONFIG_VERSION=$CONFIG_VERSION
source cbuild/default.config
DEFAULT_CBUILD_VERSION=$CBUILD_VERSION
function exec_script_line {
local script="$1"
local line_num="$2"
myprint "${BLUE}reading line $line_num from $script"
local line_str="$(sed $line_num'!d' $script)"
myprint "$line_str"
eval "$line_str"
}
# getting version of cbuild installation
exec_script_line cbuild/default.config 2
INSTALLED_CBUILD_VERSION="$CBUILD_VERSION"
unset CBUILD_VERSION
# getting version of default config
exec_script_line default.config 3
DEFAULT_CONFIG_VERSION="$CONFIG_VERSION"
unset CONFIG_VERSION
# error on undefined
@ -26,26 +41,34 @@ set -u
# reading current config or creating default
if [ ! -f current.config ]; then
printf "${YELLOW}./current.config doesn't exist\n"
myprint "${YELLOW}./current.config doesn't exist"
cp default.config current.config
printf "${YELLOW}New config created from the default.\nEdit it.\n${GRAY}"
myprint "${YELLOW}New config created from the default.\nEdit it."
exit
fi
printf "Reading ./current.config\n"
myprint "${BLUE}reading ./current.config"
source current.config
myprint "${WHITE}current.config cbuild version: ${CYAN}$CBUILD_VERSION"
myprint "${WHITE}installed cbuild version: ${CYAN}$INSTALLED_CBUILD_VERSION"
myprint "${WHITE}current.config version: ${CYAN}$CONFIG_VERSION"
myprint "${WHITE}default.config version: ${CYAN}$DEFAULT_CONFIG_VERSION"
# checking versions
if [ ! $CBUILD_VERSION -eq $DEFAULT_CBUILD_VERSION ]; then
printf "${RED}config was created for outdated cbuild version\n${GRAY}"
exit 1
if [ ! "$CBUILD_VERSION" -eq "$INSTALLED_CBUILD_VERSION" ]; then
error "config was created for outdated cbuild version"
fi
if [ ! $CONFIG_VERSION -eq $DEFAULT_CONFIG_VERSION ]; then
printf "${RED}config version isn't correct\n${GRAY}"
exit 1
if [ ! "$CONFIG_VERSION" -eq "$DEFAULT_CONFIG_VERSION" ]; then
error "config version isn't correct"
fi
mkdir -p "$OUTDIR"
mkdir -p "$OBJDIR"
mkdir -p "$OBJDIR/libs"
mkdir -p "$OBJDIR/objects"
mkdir -p "$OBJDIR/profile"
mkdir -p "$OBJDIR/out"
# dont thorw error on undefined variable
set +u
myprint "${GREEN}cbuild initialized!"

View File

@ -1,12 +1,16 @@
#!/bin/bash
# exit on errors
set -eo pipefail
# help
if [ $# -eq 0 ] || [ "$1" = "h" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ] || [ "$1" = "/?" ]; then
echo "usage: setup.sh [ submodule | standalone ]"
echo " submodule - add to existing git repo as submodule"
echo " standalone - keep independent git repo"
fi
case $1 in
case "$1" in
submodule)
echo "mode - $1"
git submodule add cbuild
@ -16,10 +20,9 @@ case $1 in
;;
*)
echo "invalid argument: $1"
exit 1
exit -1
;;
esac
cp cbuild/default.Makefile Makefile
cp cbuild/default.config ./
#bash cbuild/chmod_scripts.sh