#!/usr/bin/env bash include "@cbuild/include/myprint.sh" function exec_script_line { local script="$1" local line_num="$2" #true or false local quiet=$3 myprint_quiet $quiet "${BLUE}reading line $line_num from $script" local line_str="$(sed $line_num'!d' $script)" if [ -z "$line_str" ]; then error "script line is empty" fi myprint_quiet $quiet "$line_str" eval "$line_str" } function replace_var_value_in_script(){ local script="$1" local var_name="$2" local new_value="$3" myprint "${BLUE}setting $var_name to ${CYAN}'$new_value' in '$script'" cp "$script" "$script.tmp" sed "s,$var_name=\".*\",$var_name=\"$new_value\",g" \ "$script.tmp" > "$script" rm "$script.tmp" } function clean_dir { local dir="$1" myprint "${BLUE}cleaning ${WHITE}'$dir'" rm -rf "$dir" mkdir "$dir" } function delete_dir { local dir="$1" myprint "${BLUE}deleting ${WHITE}'$dir'" rm -rf "$dir" } function try_delete_dir_or_file { local path="$1" if [ -f "$path" ] || [ -d "$path" ]; then rm -rf "$path" myprint "${BLUE}deleting ${WHITE}'$path'" fi } file_copy_default_if_not_present(){ local file="$1" local file_default="$2" if [ ! -f "$file" ]; then myprint "${YELLOW}creating default ${WHITE}'$file'" cp -r "$file_default" "$file" fi } function exec_command { local command="$@" if [ ! -z "$command" ]; then myprint "${GRAY}$command" $command || error "command returned eror" fi } function load_dependency_config { local dep_conf_file="$1" myprint "${BLUE}loading dependency config ${WHITE}'${dep_conf_file}'" include "$dep_conf_file" } # builds a dependency when $dep_out_files dont exist or rebuild task is executed function build_dependency { # path to *.config file local dep_conf_file="$1" # true or false local force_build="$2" load_dependency_config "$dep_conf_file" local proj_root_dir="$(pwd)" myprint "${BLUE}entering dependency directory '${DEP_WORKING_DIR}'" cd "$DEP_WORKING_DIR" local build_needed="$force_build" if [ "$build_needed" != true ]; then for file in $DEP_STATIC_OUT_FILES $DEP_DYNAMIC_OUT_FILES $DEP_OTHER_OUT_FILES; do if [ ! -f "$file" ]; then myprint "${GRAY}missing file '$file'" local build_needed=true fi done fi if [ "$build_needed" = true ]; then exec_command "$DEP_PRE_BUILD_COMMAND" exec_command "$DEP_BUILD_COMMAND" exec_command "$DEP_POST_BUILD_COMMAND" myprint "${GRAY}dependency build finished" else myprint "${GRAY}dependency was built already" fi if [ ! -z "$DEP_DYNAMIC_OUT_FILES" ]; then # copies each file to $OUTDIR and creates symbolic link in $OBJDIR/dynamic_libs for file in $DEP_DYNAMIC_OUT_FILES; do # doesnt return error if called not like this real_file=$(realpath $file) file_dir=$(dirname $file) if [ "$PRESERVE_OUT_DIRECTORY_STRUCTURE" = true ] && [ "$file_dir" != '.' ]; then mkdir -p "$proj_root_dir/$OUTDIR/$file_dir" mkdir -p "$proj_root_dir/$OBJDIR/dynamic_libs/$file_dir" cp -v -u --preserve=timestamps "$file" "$proj_root_dir/$OUTDIR/$file" ln -sfv "$real_file" "$proj_root_dir/$OBJDIR/dynamic_libs/$file" else cp -v -u --preserve=timestamps "$file" "$proj_root_dir/$OUTDIR/" ln -sfv "$real_file" "$proj_root_dir/$OBJDIR/dynamic_libs/" fi done fi if [ ! -z "$DEP_OTHER_OUT_FILES" ]; then # copies each file to $OUTDIR for file in $DEP_OTHER_OUT_FILES; do if [ "$PRESERVE_OUT_DIRECTORY_STRUCTURE" = true ]; then file_dir=$(dirname $file) mkdir -p "$proj_root_dir/$OUTDIR/$file_dir" cp -v -u --preserve=timestamps "$file" "$proj_root_dir/$OUTDIR/$file" else cp -v -u --preserve=timestamps "$file" "$proj_root_dir/$OUTDIR/" fi done fi if [ ! -z "$DEP_STATIC_OUT_FILES" ]; then # creates symbolic link to each file in $OBJDIR/static_libs for file in $DEP_STATIC_OUT_FILES; do # doesnt return error if called not like this f=$(realpath $file) ln -sfv $f "$proj_root_dir/$OBJDIR/static_libs" done fi cd "$proj_root_dir" # unsed all dependency config variables to not mess with next dependencies unset DEP_WORKING_DIR unset DEP_PRE_BUILD_COMMAND unset DEP_BUILD_COMMAND unset DEP_POST_BUILD_COMMAND unset DEP_CLEAN_COMMAND unset DEP_STATIC_OUT_FILES unset PRESERVE_OUT_DIRECTORY_STRUCTURE unset DEP_DYNAMIC_OUT_FILES unset DEP_OTHER_OUT_FILES } function build_dependencies { local dependencies="$1" # true or false local force_build="$2" myprint "${BLUE}resolving dependencies" clean_dir "$OBJDIR/static_libs" clean_dir "$OBJDIR/dynamic_libs" for dep in $dependencies; do build_dependency "$DEPENDENCY_CONFIGS_DIR/$dep.config" "$force_build" done } function compile { build_dependencies "$ENABLED_DEPENDENCIES" print_hline "${BLUE}" "─" local cmp="$1" local std="$2" local warn="$3" local args="$4" local include="$5" local sources="$6" myprint "${BLUE}compiler: ${GRAY}$cmp" myprint "${BLUE}standard: ${GRAY}$std" myprint "${BLUE}warnings: ${GRAY}$warn" myprint "${BLUE}args: ${GRAY}$args" myprint "${BLUE}include dirs: ${GRAY}$include" myprint "${BLUE}sources: ${GRAY}$sources" 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 stop all threads fi ) & done wait } # (args, sources) function compile_c { local cmp="$1" local std="$2" local warn="$3" local args="$4" local include="$5" local sources="$6" print_header "${CYAN}" "─" "$PROJECT/$TASK/compile_c" compile "$cmp" "$std" "$warn" "$args" "$include" "$sources" } # (args, sources) function compile_cpp { local cmp="$1" local std="$2" local warn="$3" local args="$4" local include="$5" local sources="$6" print_header "${CYAN}" "─" "$PROJECT/$TASK/compile_cpp" compile "$cmp" "$std" "$warn" "$args" "$include" "$sources" } # (outfile) function pack_static_lib { print_header "${CYAN}" "─" "$PROJECT/$TASK/pack_static_lib" local outfile="$1" myprint "${BLUE}outfile: ${GRAY}$outfile" local objects=$(find $OBJDIR/objects -type f,l | tr '\n' ' ') myprint "${BLUE}objects: ${GRAY}$objects" if [ -z "$objects" ]; then error "no compiled objects found" fi local command="ar rcs $OUTDIR/$outfile $objects" print_hline "${GRAY}" "─" myprint "${GRAY}$command" print_hline "${GRAY}" "─" if $command then myprint "${GREEN}file $CYAN$outfile ${GREEN}created" else error "some error happened" fi clean_dir "$OBJDIR/objects" } function link { print_header "${CYAN}" "─" "$PROJECT/$TASK/link" local args="$1" local outfile="$2" myprint "${BLUE}args: ${GRAY}$args" myprint "${BLUE}outfile: ${GRAY}$outfile" local objects=$(find $OBJDIR/objects -type f,l | tr '\n' ' ') myprint "${BLUE}objects: ${GRAY}$objects" if [ -z "$objects" ]; then error "no compiled objects found" fi local static_libs=$(find $OBJDIR/static_libs -type f,l | tr '\n' ' ') myprint "${BLUE}static libraries: ${GRAY}$static_libs" local dynamic_libs=$(find $OBJDIR/dynamic_libs -type f,l | tr '\n' ' '\ | sed "s,$OBJDIR/dynamic_libs/,,g") myprint "${BLUE}dynamic libraries: ${GRAY}$dynamic_libs" local dynamic_libs_args="-L./$OBJDIR/dynamic_libs -Wl,-Bdynamic" for lib in $dynamic_libs; do dynamic_libs_args="$dynamic_libs_args -Wl,-rpath=$(dirname $lib) -l:$lib" done local command="$CMP_CPP $objects $static_libs $args $dynamic_libs_args -o $OUTDIR/$outfile" print_hline "${GRAY}" "─" myprint "${GRAY}$command" print_hline "${GRAY}" "─" if $command then myprint "${GREEN}file $CYAN$outfile ${GREEN}created" else error "some error happened" fi clean_dir "$OBJDIR/objects" }