758 lines
24 KiB
Bash
758 lines
24 KiB
Bash
#!/bin/bash
|
|
|
|
###### Usage ##################################################################
|
|
# To use the bld build system in a bash script, some setup is required:
|
|
# 1. Define paths:
|
|
# root_path, opts_path, bld_path, local_path, src_path,
|
|
# build_path, program_pather
|
|
# 2. Define local variables:
|
|
# compiler, compile_mode, arch, linker, ctx_opts
|
|
# 3. Then include this core file with "." prefix:
|
|
# . $bld_path/bld_core.sh
|
|
#
|
|
#
|
|
# The following bld functions form the core "commands":
|
|
# bld_compile, bld_link, bld_lib, bld_unit
|
|
#
|
|
# And there are several more helper functions:
|
|
# bld_print_implicit_opts, bld_load_local_opts
|
|
#
|
|
#
|
|
# Signatures:
|
|
# bld_compile <source-file> <zero-or-more-options>
|
|
# bld_link <out-name> <one-or-more-source-files-objs-or-libs> -- \
|
|
# <zero-or-more-options>
|
|
# bld_lib <out-name> <one-or-more-source-files-or-objs> -- \
|
|
# <zero-or-more-options>
|
|
# bld_unit <source-file> <zero-or-more-options>
|
|
#
|
|
# bld_print_implicit_opts (no arguments)
|
|
# bld_load_local_opts (no arguments)
|
|
#
|
|
#
|
|
# Shared notes for all:
|
|
# + Options are gathered from the arguments, from the local context, and
|
|
# in the case of the commands bld_compile and bld_unit, from the source file.
|
|
# + Options gathered from local context are prefixed with their context
|
|
# variable like so [var:val]. So for example, on windows the options list
|
|
# includes [os:windows].
|
|
# + Options in source files are specified between the strings //$ and //.
|
|
# + Object file extensions should be named based on whether they were
|
|
# generated by a compiler or assembler. Compiled objects should have the
|
|
# extension .cmp:o and assembled objects should have the extension
|
|
# .asm:o. The system automatically changes the name to match the correct
|
|
# extension given the context.
|
|
# + Static library files should have the extension .lib. The system
|
|
# automatically changes the name to match the correct extension given the
|
|
# context.
|
|
# + When the option "diagnostics" is included, extra details will be printed
|
|
# from the bld commands. Showing the full list of options, invokation lines,
|
|
# and the build path.
|
|
#
|
|
# bld_compile:
|
|
# + Creates an object file from a single source file via the selected compiler.
|
|
#
|
|
# bld_link:
|
|
# + Creates executables and shared binaries from source files, object files,
|
|
# and static libraries. First uses the bld_compile command on the source
|
|
# files.
|
|
# + Uses the selected linker.
|
|
# + If the short name for the linker does not work for any reason, the
|
|
# full path to the linker may be specified in a filter file pointed to by
|
|
# the setup variable `program_pather`
|
|
# + The output is a shared binary (.dll or .so) when the option "dll" is
|
|
# included.
|
|
#
|
|
# bld_lib:
|
|
# + Creates a static library from source files and object files. First uses
|
|
# the bld_compile command on the source files. Uses the OS to determine the
|
|
# correct archiver.
|
|
#
|
|
# bld_unit:
|
|
# + Creates an executable (or shared binary) from a single source file.
|
|
# This command essentially does a single bld_compile then bld_link. With
|
|
# two differences:
|
|
# 1. The options from the source file are visible to the bld_link.
|
|
# 2. The name of the executable is determined either from the first option
|
|
# in the list or from the source file name if there are no options.
|
|
#
|
|
# bld_print_implicit_opts:
|
|
# + Shows the implicit options loaded from the local parameters script.
|
|
#
|
|
# bld_load_local_opts:
|
|
# + It is possible and sometimes useful to modify the local parameters after
|
|
# they are loaded to create certain kinds of build scripts. This function
|
|
# resets the local parameters to their original states by rerunning the
|
|
# local parameters script.
|
|
|
|
|
|
###### Flags From Opts ########################################################
|
|
|
|
function bld_flags_from_opts {
|
|
###### parse arguments ####################################################
|
|
local in_file=$1
|
|
local opts=()
|
|
for ((i=2; i<=$#; i+=1)); do
|
|
opts+=(${!i})
|
|
done
|
|
|
|
###### load file ##########################################################
|
|
local flags_raw=()
|
|
IFS=$'\r\n' GLOBIGNORE='*' command eval 'flags_raw=($(cat $in_file))'
|
|
|
|
###### filter #############################################################
|
|
local flags=()
|
|
for ((i=0;i<${#flags_raw[@]};i+=1)); do
|
|
local flag=${flags_raw[i]}
|
|
|
|
###### skip blanks and comments #######################################
|
|
if [[ -z "${flag// }" ]]; then
|
|
continue
|
|
fi
|
|
if [[ "${flag:0:1}" == "#" ]]; then
|
|
continue
|
|
fi
|
|
|
|
###### parse line filters #############################################
|
|
local line_filters=()
|
|
while [[ $flag = *">"* ]]; do
|
|
line_filters+=("${flag%%>*}")
|
|
flag="${flag#*>}"
|
|
done
|
|
|
|
###### check filters ##################################################
|
|
local can_include=1
|
|
for ((j=0;j<${#line_filters[@]};j+=1)); do
|
|
can_include=0
|
|
for ((k=0;k<${#opts[@]};k+=1)); do
|
|
if [[ ${opts[k]} = ${line_filters[j]} ]]; then
|
|
can_include=1
|
|
break
|
|
fi
|
|
done
|
|
if [[ "$can_include" = "0" ]]; then
|
|
break
|
|
fi
|
|
done
|
|
if [[ "$can_include" = "1" ]]; then
|
|
flags+=("${flag}")
|
|
fi
|
|
done
|
|
|
|
echo "${flags[@]}"
|
|
}
|
|
|
|
###### Opts From Src ##########################################################
|
|
|
|
function bld_opts_from_src {
|
|
###### split file into tokens #############################################
|
|
local in_file=$1
|
|
local tokens=($(grep "//\\$" $in_file))
|
|
|
|
###### parse ##############################################################
|
|
local in_params_range="0"
|
|
local params=()
|
|
for ((i=0; i<${#tokens[@]}; i+=1)); do
|
|
local string="${tokens[i]}"
|
|
if [[ "$in_params_range" == "0" ]]; then
|
|
if [[ "$string" == "//$" ]]; then
|
|
in_params_range="1"
|
|
fi
|
|
elif [[ "$in_params_range" == "1" ]]; then
|
|
if [[ "${string:0:2}" == "//" ]]; then
|
|
break
|
|
fi
|
|
params+=($string)
|
|
fi
|
|
done
|
|
|
|
echo "${params[@]}"
|
|
}
|
|
|
|
###### Dedup ##################################################################
|
|
|
|
function bld_dedup {
|
|
###### parse arguments ####################################################
|
|
local in=()
|
|
for ((i=1; i<=$#; i+=1)); do
|
|
in+=(${!i})
|
|
done
|
|
|
|
###### dedup ##############################################################
|
|
local out=()
|
|
for ((i=0; i<${#in[@]}; i+=1)); do
|
|
local string=${in[i]}
|
|
local is_dup="0"
|
|
for ((j=0; j<${#out[@]}; j+=1)); do
|
|
if [[ "$string" == "${out[j]}" ]]; then
|
|
is_dup="1"
|
|
break
|
|
fi
|
|
done
|
|
if [[ "$is_dup" == "0" ]]; then
|
|
out+=($string)
|
|
fi
|
|
done
|
|
|
|
echo "${out[@]}"
|
|
}
|
|
|
|
###### Has Opt ################################################################
|
|
|
|
function bld_has_opt {
|
|
###### parse arguments ####################################################
|
|
local key_opt=$1
|
|
local opts=()
|
|
for ((i=2; i<=$#; i+=1)); do
|
|
opts+=(${!i})
|
|
done
|
|
|
|
###### scan ###############################################################
|
|
local has_key=0
|
|
for ((i=0;i<${#opts[@]};i+=1)); do
|
|
local opt=${opts[i]}
|
|
if [[ "$opt" == "$key_opt" ]]; then
|
|
has_key=1
|
|
break
|
|
fi
|
|
done
|
|
|
|
echo $has_key
|
|
}
|
|
|
|
###### Load Local Options #####################################################
|
|
|
|
function bld_load_local_opts {
|
|
###### os cracking ########################################################
|
|
os="undefined"
|
|
if [ "$OSTYPE" == "win32" ] ||
|
|
[ "$OSTYPE" == "msys" ]; then
|
|
os="windows"
|
|
elif [ "$OSTYPE" == "linux-gnu" ]; then
|
|
os="linux"
|
|
elif [ "$OSTYPE" == "darwin" ]; then
|
|
os="mac"
|
|
fi
|
|
###### load parameters from the local script ################################
|
|
if [ -f "$local_path/local_vars.sh" ]; then
|
|
source "$local_path/local_vars.sh"
|
|
fi
|
|
}
|
|
|
|
###### Implicit Opts ##########################################################
|
|
|
|
function bld_implicit_opts {
|
|
local linker_opt=""
|
|
if [[ "$linker" == "link" || "$linker" == "lld-link" ]]; then
|
|
linker_opt="link:msvc"
|
|
fi
|
|
echo $ctx_opts cmp:$compiler mode:$compile_mode asm:$assembler
|
|
echo link:$linker $linker_opt os:$os arch:$arch
|
|
}
|
|
|
|
###### Print Implicit Options #################################################
|
|
|
|
function bld_print_implicit_opts {
|
|
local opts=($(bld_implicit_opts))
|
|
local bracketed=()
|
|
for ((i=0; i<=${#opts[@]}; i+=1)); do
|
|
local opt="${opts[i]}"
|
|
if [ "$opt" != "" ]; then
|
|
bracketed+=("[${opts[i]}]")
|
|
fi
|
|
done
|
|
echo "${bracketed[@]}"
|
|
}
|
|
|
|
###### Print Help #############################################################
|
|
|
|
function bld_print_obj_note {
|
|
echo "NOTE: the interface does not use standard object file extensions"
|
|
echo "NOTE: use 'cmp:o' for object files produced by a compiler"
|
|
echo "NOTE: use 'asm:o' for object files produced by an assembler"
|
|
}
|
|
|
|
###### Compile ################################################################
|
|
|
|
function bld_compile {
|
|
local i=0
|
|
|
|
###### parse arguments ####################################################
|
|
local in_file=$1
|
|
local opts=()
|
|
for ((i=2; i<=$#; i+=1)); do
|
|
opts+=(${!i})
|
|
done
|
|
if [ "$in_file" == "" ]; then
|
|
echo "ERROR(compile): missing input file"
|
|
return 1
|
|
fi
|
|
|
|
###### finish in file #####################################################
|
|
local final_in_file=$in_file
|
|
|
|
###### determine build kind ###############################################
|
|
local ext="${final_in_file##*.}"
|
|
local build_kind="undetermined"
|
|
if [[ "$ext" == "c" || "$ext" == "cpp" ]]; then
|
|
build_kind="compile"
|
|
elif [[ "$ext" == "asm" ]]; then
|
|
build_kind="assemble"
|
|
else
|
|
echo "ERROR(compile): unrecgonized source type $final_in_file"
|
|
return 1
|
|
fi
|
|
|
|
###### finish options #####################################################
|
|
local src_opts=($(bld_opts_from_src $final_in_file))
|
|
local impl_opts=($(bld_implicit_opts))
|
|
local all_opts=($(bld_dedup ${impl_opts[@]} ${opts[@]} ${src_opts[@]}))
|
|
|
|
###### diagnostics ########################################################
|
|
local diagnostics=$(bld_has_opt diagnostics ${all_opts[@]})
|
|
|
|
###### out file name ######################################################
|
|
local dot_ext_o=""
|
|
if [[ "$build_kind" == "compile" ]]; then
|
|
dot_ext_o=$(bld_ext_cmpo)
|
|
elif [[ "$build_kind" == "assemble" ]]; then
|
|
dot_ext_o=$(bld_ext_asmo)
|
|
fi
|
|
local file_base=${final_in_file##*/}
|
|
local file_base_no_ext=${file_base%.*}
|
|
local out_file="$file_base_no_ext$dot_ext_o"
|
|
|
|
###### get real flags #####################################################
|
|
local flags=""
|
|
if [[ "$build_kind" == "compile" ]]; then
|
|
flags=$(bld_flags_from_opts $opts_path/compiler_flags.txt ${all_opts[@]})
|
|
else
|
|
flags=$(bld_flags_from_opts $opts_path/assembler_flags.txt ${all_opts[@]})
|
|
fi
|
|
|
|
###### move to output folder ##############################################
|
|
mkdir -p "$build_path"
|
|
cd $build_path
|
|
if [ "$diagnostics" == "1" ]; then
|
|
echo "build path: $build_path"
|
|
fi
|
|
|
|
###### delete existing object file ########################################
|
|
rm -f "$out_file_base.o"
|
|
rm -f "$out_file_base.obj"
|
|
|
|
###### final flags ########################################################
|
|
local final_flags=""
|
|
if [[ "$build_kind" == "compile" ]]; then
|
|
final_flags="-c -I$src_path ${flags}"
|
|
elif [[ "$build_kind" == "assemble" ]]; then
|
|
final_flags="-c ${flags}"
|
|
fi
|
|
|
|
###### compile ############################################################
|
|
if [[ "$build_kind" == "compile" ]]; then
|
|
if [ "$diagnostics" == "1" ]; then
|
|
echo "cmp $final_in_file -- ${all_opts[@]}"
|
|
echo $compiler "$final_in_file" $final_flags
|
|
fi
|
|
if [ "$compiler" == "clang" ]; then
|
|
echo "$file_base"
|
|
fi
|
|
$compiler "$final_in_file" $final_flags
|
|
elif [[ "$build_kind" == "assemble" ]]; then
|
|
if [ "$diagnostics" == "1" ]; then
|
|
echo "asm $final_in_file -- ${all_opts[@]}"
|
|
echo $assembler $final_flags "$final_in_file"
|
|
fi
|
|
$assembler $final_flags "$final_in_file"
|
|
fi
|
|
|
|
# return of status from compiler is automatic here.
|
|
}
|
|
|
|
###### Link ###################################################################
|
|
|
|
function bld_link {
|
|
local i=0
|
|
|
|
###### parse arguments ####################################################
|
|
local out_name=$1
|
|
local in_files=()
|
|
for ((i=2; i<=$#; i+=1)); do
|
|
if [ "${!i}" == "--" ]; then
|
|
break
|
|
fi
|
|
in_files+=(${!i})
|
|
done
|
|
local opts=()
|
|
for ((i+=1; i<=$#; i+=1)); do
|
|
opts+=(${!i})
|
|
done
|
|
if [ "$out_name" == "" ]; then
|
|
echo "link: missing output name"
|
|
return 1
|
|
fi
|
|
if [ "${#in_files}" == "0" ]; then
|
|
echo "link: missing input file(s)"
|
|
return 1
|
|
fi
|
|
|
|
###### finish options #####################################################
|
|
local impl_opts=($(bld_implicit_opts))
|
|
local all_opts=($(bld_dedup ${opts[@]} ${impl_opts[@]}))
|
|
|
|
###### diagnostics ########################################################
|
|
local diagnostics=$(bld_has_opt diagnostics ${all_opts[@]})
|
|
|
|
###### sort in files ######################################################
|
|
local in_src=()
|
|
local in_cmpo=()
|
|
local in_asmo=()
|
|
local in_lib=()
|
|
for ((i=0; i<${#in_files[@]}; i+=1)); do
|
|
local file="${in_files[i]}"
|
|
local ext="${file##*.}"
|
|
if [[ "$ext" == "c" || "$ext" == "cpp" || "$ext" == "asm" ]]; then
|
|
in_src+=($file)
|
|
elif [[ "$ext" == "cmp:o" ]]; then
|
|
in_cmpo+=($file)
|
|
elif [[ "$ext" == "asm:o" ]]; then
|
|
in_asmo+=($file)
|
|
elif [[ "$ext" == "lib" ]]; then
|
|
in_lib+=($file)
|
|
else
|
|
echo "WARNING: ignoring unrecgonized file type $file"
|
|
if [[ "$ext" == "obj" || "$ext" == "o" ]]; then
|
|
bld_print_obj_note
|
|
fi
|
|
fi
|
|
done
|
|
|
|
###### auto correct compiled object files #################################
|
|
local dot_ext_cmpo=$(bld_ext_cmpo)
|
|
for ((i=0; i<${#in_cmpo[@]}; i+=1)); do
|
|
local file_name="${in_cmpo[i]}"
|
|
local base_name="${file_name%.*}"
|
|
in_cmpo[$i]="$base_name$dot_ext_cmpo"
|
|
done
|
|
|
|
###### auto correct assembled object files ################################
|
|
local dot_ext_asmo=$(bld_ext_asmo)
|
|
for ((i=0; i<${#in_asmo[@]}; i+=1)); do
|
|
local file_name="${in_asmo[i]}"
|
|
local base_name="${file_name%.*}"
|
|
in_asmo[$i]="$base_name$dot_ext_asmo"
|
|
done
|
|
|
|
###### combine object files ###############################################
|
|
local in_obj=()
|
|
for ((i=0; i<${#in_cmpo[@]}; i+=1)); do
|
|
local file="${in_cmpo[i]}"
|
|
in_obj+=($file)
|
|
done
|
|
for ((i=0; i<${#in_asmo[@]}; i+=1)); do
|
|
local file="${in_asmo[i]}"
|
|
in_obj+=($file)
|
|
done
|
|
|
|
###### compile source files ###############################################
|
|
for ((i=0; i<${#in_src[@]}; i+=1)); do
|
|
local file="${in_src[i]}"
|
|
bld_compile "$file" ${all_opts[@]}
|
|
local status=$?
|
|
if [ $status -ne 0 ]; then
|
|
return $status
|
|
fi
|
|
done
|
|
|
|
###### intermediate object files ##########################################
|
|
local interm_obj=()
|
|
for ((i=0; i<${#in_src[@]}; i+=1)); do
|
|
local file_name="${in_src[i]}"
|
|
local base_name="${file_name##*/}"
|
|
local base_name_no_ext="${base_name%.*}"
|
|
local ext="${base_name##*.}"
|
|
if [[ "$ext" == "c" || "$ext" == "cpp" ]]; then
|
|
interm_obj+=($base_name_no_ext$dot_ext_cmpo)
|
|
elif [[ "$ext" == "asm" ]]; then
|
|
interm_obj+=($base_name_no_ext$dot_ext_asmo)
|
|
fi
|
|
done
|
|
|
|
###### get real flags #####################################################
|
|
local flags=$(bld_flags_from_opts $opts_path/linker_flags.txt ${all_opts[@]})
|
|
|
|
###### out file name ######################################################
|
|
local dot_ext_out=""
|
|
local is_dll=$(bld_has_opt dll ${all_opts[@]})
|
|
if [ "$is_dll" == "0" ]; then
|
|
dot_ext_out=$(bld_ext_exe)
|
|
else
|
|
dot_ext_out=$(bld_ext_dll)
|
|
fi
|
|
out_file="$out_name$dot_ext_out"
|
|
|
|
###### move to output folder ##############################################
|
|
mkdir -p "$build_path"
|
|
cd $build_path
|
|
if [ "$diagnostics" == "1" ]; then
|
|
echo "build path: $build_path"
|
|
fi
|
|
|
|
###### final files to linker ##############################################
|
|
local final_in_files="${interm_obj[@]} ${in_obj[@]} ${in_lib[@]}"
|
|
|
|
###### set first diagnostic string ########################################
|
|
local first_diagnostic_string="lnk $final_in_files -- ${all_opts[@]}"
|
|
|
|
###### linker executable name #############################################
|
|
local linker_exe=$linker
|
|
local linker_rename=$(bld_flags_from_opts $program_pather "link:$linker")
|
|
if [[ "$linker_rename" != "" ]]; then
|
|
if [ "$diagnostics" == "1" ]; then
|
|
echo "linker rename: $linker_rename"
|
|
fi
|
|
linker_exe=$linker_rename
|
|
fi
|
|
|
|
###### link ###############################################################
|
|
local status=0
|
|
local invokation=""
|
|
if [[ "$linker" == "link" || "$linker" == "lld-link" ]]; then
|
|
invokation="-OUT:$out_file $flags $final_in_files"
|
|
elif [ "$linker" == "clang" ]; then
|
|
invokation="-o $out_file $flags $final_in_files"
|
|
else
|
|
echo "ERROR(link): invokation not defined for this linker"
|
|
status=1
|
|
fi
|
|
if [ "$invokation" != "" ]; then
|
|
if [ "$diagnostics" == "1" ]; then
|
|
echo $first_diagnostic_string
|
|
echo $linker_exe $invokation
|
|
fi
|
|
echo "$out_file"
|
|
"$linker_exe" $invokation
|
|
status=$?
|
|
fi
|
|
|
|
return $status
|
|
}
|
|
|
|
###### Library ################################################################
|
|
|
|
function bld_lib {
|
|
local i=0
|
|
|
|
###### parse arguments ####################################################
|
|
local out_name=$1
|
|
local in_files=()
|
|
for ((i=2; i<=$#; i+=1)); do
|
|
if [ "${!i}" == "--" ]; then
|
|
break
|
|
fi
|
|
in_files+=(${!i})
|
|
done
|
|
local opts=()
|
|
for ((i+=1; i<=$#; i+=1)); do
|
|
opts+=(${!i})
|
|
done
|
|
if [ "$out_name" == "" ]; then
|
|
echo "lib: missing output name"
|
|
return 1
|
|
fi
|
|
if [ "${#in_files}" == "0" ]; then
|
|
echo "lib: missing input file(s)"
|
|
return 1
|
|
fi
|
|
|
|
###### finish options #####################################################
|
|
local impl_opts=($(bld_implicit_opts))
|
|
local all_opts=($(bld_dedup ${opts[@]} ${impl_opts[@]}))
|
|
|
|
###### diagnostics ########################################################
|
|
local diagnostics=$(bld_has_opt diagnostics ${all_opts[@]})
|
|
|
|
###### sort in files ######################################################
|
|
local in_src=()
|
|
local in_cmpo=()
|
|
local in_asmo=()
|
|
for ((i=0; i<${#in_files[@]}; i+=1)); do
|
|
local file="${in_files[i]}"
|
|
local ext="${file##*.}"
|
|
if [[ "$ext" == "c" || "$ext" == "cpp" ]]; then
|
|
in_src+=($file)
|
|
elif [[ "$ext" == "cmp:o" ]]; then
|
|
in_cmpo+=($file)
|
|
elif [[ "$ext" == "asm:o" ]]; then
|
|
in_asmo+=($file)
|
|
else
|
|
echo "WARNING: ignoring unrecgonized file type $file"
|
|
if [[ "$ext" == "obj" || "$ext" == "o" ]]; then
|
|
bld_print_obj_note
|
|
fi
|
|
fi
|
|
done
|
|
|
|
###### auto correct compiled object files #################################
|
|
local dot_ext_cmpo=$(bld_ext_cmpo)
|
|
for ((i=0; i<${#in_cmpo[@]}; i+=1)); do
|
|
local file_name="${in_cmpo[i]}"
|
|
local base_name="${file_name%.*}"
|
|
in_cmpo[$i]=$base_name$dot_ext_cmpo
|
|
done
|
|
|
|
###### auto correct assembled object files ################################
|
|
local dot_ext_asmo=$(bld_ext_asmo)
|
|
for ((i=0; i<${#in_asmo[@]}; i+=1)); do
|
|
local file_name="${in_asmo[i]}"
|
|
local base_name="${file_name%.*}"
|
|
in_asmo[$i]="$base_name$dot_ext_asmo"
|
|
done
|
|
|
|
###### combine object files ###############################################
|
|
local in_obj=()
|
|
for ((i=0; i<${#in_cmpo[@]}; i+=1)); do
|
|
local file="${in_cmpo[i]}"
|
|
in_obj+=($file)
|
|
done
|
|
for ((i=0; i<${#in_asmo[@]}; i+=1)); do
|
|
local file="${in_asmo[i]}"
|
|
in_obj+=($file)
|
|
done
|
|
|
|
###### compile source files ###############################################
|
|
for ((i=0; i<${#in_src[@]}; i+=1)); do
|
|
bld_compile "${in_src[i]}" ${all_opts[@]}
|
|
local status=$?
|
|
if [ $status -ne 0 ]; then
|
|
return $status
|
|
fi
|
|
done
|
|
|
|
###### intermediate object files ##########################################
|
|
local interm_obj=()
|
|
for ((i=0; i<${#in_src[@]}; i+=1)); do
|
|
local file_name="${in_src[i]}"
|
|
local base_name="${file_name##*/}"
|
|
local base_name_no_ext="${base_name%.*}"
|
|
local ext="${base_name##*.}"
|
|
if [[ "$ext" == "c" || "$ext" == "cpp" ]]; then
|
|
interm_obj+=($base_name_no_ext$dot_ext_cmpo)
|
|
elif [[ "$ext" == "asm" ]]; then
|
|
interm_obj+=($base_name_no_ext$dot_ext_asmo)
|
|
fi
|
|
done
|
|
|
|
###### out file name ######################################################
|
|
local out_file=""
|
|
if [ "$os" == "windows" ]; then
|
|
out_file="$out_name.lib"
|
|
elif [ "$os" == "linux" || "$os" == "mac" ]; then
|
|
out_file="lib$out_name.a"
|
|
else
|
|
echo "ERROR(lib): static library output not defined for OS: $os"
|
|
fi
|
|
|
|
###### final library build input files ####################################
|
|
local final_in_files="${interm_obj[@]} ${in_obj[@]}"
|
|
|
|
###### move to output folder ##############################################
|
|
mkdir -p "$build_path"
|
|
cd $build_path
|
|
if [ "$diagnostics" == "1" ]; then
|
|
echo "build path: $build_path"
|
|
fi
|
|
|
|
###### set first diagnostic string ########################################
|
|
local first_diagnostic_string="lib $final_in_files -- ${all_opts[@]}"
|
|
|
|
###### build library ######################################################
|
|
local status=0
|
|
if [ "$os" == "windows" ]; then
|
|
if [ "$diagnostics" == "1" ]; then
|
|
echo $first_diagnostic_string
|
|
echo lib -nologo -OUT:"$out_file" $final_in_files
|
|
fi
|
|
echo "$out_file"
|
|
lib -nologo -OUT:"$out_file" $final_in_files
|
|
status=$?
|
|
elif [ "$os" == "linux" || "$os" == "mac" ]; then
|
|
# TODO(allen): invoke ar here - make sure to delete the original .a first
|
|
# because ar does not (seem) to replace the output file, just append
|
|
echo "TODO: implement ar path in bld_core.sh:bld_lib"
|
|
status=1
|
|
else
|
|
echo "ERROR(lib): static library invokation not defined for OS: $os"
|
|
status=1
|
|
fi
|
|
|
|
return $status
|
|
}
|
|
|
|
###### Unit ###################################################################
|
|
|
|
function bld_unit {
|
|
local i=0
|
|
|
|
###### parse arguments ####################################################
|
|
local main_file=$1
|
|
local opts=()
|
|
for ((i=2; i<=$#; i+=1)); do
|
|
opts+=(${!i})
|
|
done
|
|
if [ "$main_file" == "" ]; then
|
|
echo "unit: missing main file"
|
|
return 1
|
|
fi
|
|
|
|
###### set out name #######################################################
|
|
local out_name=""
|
|
if [ "${#opts}" == "0" ]; then
|
|
local file_base=${main_file##*/}
|
|
local file_base_no_ext=${file_base%.*}
|
|
out_name=$file_base_no_ext
|
|
else
|
|
out_name="${opts[0]}"
|
|
fi
|
|
|
|
###### finish options #####################################################
|
|
local src_opts=$(bld_opts_from_src $main_file)
|
|
local impl_opts=($(bld_implicit_opts))
|
|
local all_opts=($(bld_dedup $out_name ${opts[@]} ${src_opts[@]} ${impl_opts[@]}))
|
|
|
|
###### link ###############################################################
|
|
bld_link $out_name $main_file ${in_files[@]} -- ${all_opts[@]}
|
|
}
|
|
|
|
###### Special Ifs ############################################################
|
|
|
|
function bld_ext_cmpo {
|
|
echo $(bld_flags_from_opts $opts_path/file_extensions.txt cmp:$compiler "cmp:o")
|
|
}
|
|
function bld_ext_asmo {
|
|
echo $(bld_flags_from_opts $opts_path/file_extensions.txt asm:$assembler "asm:o")
|
|
}
|
|
function bld_ext_exe {
|
|
echo $(bld_flags_from_opts $opts_path/file_extensions.txt os:$os exe)
|
|
}
|
|
function bld_ext_dll {
|
|
echo $(bld_flags_from_opts $opts_path/file_extensions.txt os:$os dll)
|
|
}
|
|
|
|
###### Load Locals ############################################################
|
|
bld_load_local_opts
|
|
|
|
###############################################################################
|
|
# TODO: Notes for future itations on this sytem
|
|
# - With the addition of the assembler, it is now becoming clear that the
|
|
# bld_compile path is feeling a bit overloaded and that the mapping of
|
|
# interface extensions to real extensions, and the mapping of interface
|
|
# extensions to inferred build steps, are major complicating factors.
|
|
# A new strategy for organizing multiple builders, and multiple conversion
|
|
# paths that may be inferred from a set of possible starting points would
|
|
# stand to simplify a lot of the system.
|
|
# - Switching out object file extensions
|
|
# - Subtlties of invoking different build kinds in bld_compile
|
|
# - Tracking subkinds through bld_link and bld_lib
|