]> Kevux Git Server - fll/commitdiff
Update: redesign to follow the Featureless Make design
authorKevin Day <thekevinday@gmail.com>
Sun, 7 Jun 2020 00:38:06 +0000 (19:38 -0500)
committerKevin Day <thekevinday@gmail.com>
Sun, 7 Jun 2020 00:38:06 +0000 (19:38 -0500)
Use the setting names specified by Featureless Make, which are a bit more generalized than the current generate.sh design.

This does not fully follow all of the Featureless Make functions.
Only what is necessary (or already implemented) to bootstrap the entire FLL project is done.

build/scripts/generate.sh

index ebafef8e3f383b113eb789c3c069c9b785824cef..5532297633e220a0ad47518d8242c7ce24f5b115 100644 (file)
@@ -3,7 +3,9 @@
 # programmer: Kevin Day
 #
 # The purpose of this script is to provide a simple bootstrap tool to compile any part of the FLL project.
-# The dependencies of this script are: bash, dirname, grep, and sed.
+# The dependencies of this script are: bash, basename, dirname, grep, and sed.
+#
+# This script is only designed specifically for bootstrap compiling the FLL project and does not necessarily fully follow the fake (featureless make) build process.
 
 generate_main(){
   local public_name="Simple FLL Project Make Script"
@@ -15,6 +17,7 @@ generate_main(){
   local do_color=normal
   local do_help=
   local i=0
+  local m=
   local p=
   local t=0
 
@@ -28,20 +31,23 @@ generate_main(){
   local c_subtle="\\033[1;30m"
   local c_prefix="\\"
 
-  local build_libraries_fll="build_libraries_fll"
   local variables=
+  local settings_name=settings
   local settings_file=
   local settings_defines=
+  local mode=
   local operation=
   local operation_failure=
   local path_build=build/
-  local path_build_settings=
+  local path_build_stage=build/stage/
+  local path_data=data/
+  local path_settings=data/build/settings/
+  local path_sources=sources/
   local path_c=sources/c/
-  local path_settings=data/settings/
-  local path_bash=
+  local path_work=
   local project_built=
-  local work_directory=
   local defines_override=
+  local process=
 
   local enable_shared=
   local enable_static=
@@ -63,26 +69,22 @@ generate_main(){
         elif [[ $p == "+v" || $p == "++version" ]] ; then
           echo $version
           return
-        elif [[ $p == "-b" || $p == "--build" ]] ; then
-          grab_next=path_build
-        elif [[ $p == "-s" || $p == "--settings" ]] ; then
-          grab_next=build_settings
-        elif [[ $p == "-B" || $p == "--path_bash" ]] ; then
-          grab_next=path_bash
-        elif [[ $p == "-c" || $p == "--path_c" ]] ; then
-          grab_next=path_c
-        elif [[ $p == "-S" || $p == "--path_settings" ]] ; then
-          grab_next=path_settings
-        elif [[ $p == "-p" || $p == "--project" ]] ; then
-          grab_next=project_built
-        elif [[ $p == "-w" || $p == "--work_directory" ]] ; then
-          grab_next=work_directory
         elif [[ $p == "-d" || $p == "--defines" ]] ; then
           grab_next=defines_override
-        elif [[ $p == "-l" || $p == "--level" ]] ; then
-          build_libraries_fll="build_libraries_fll-level"
-        elif [[ $p == "-m" || $p == "--monolithic" ]] ; then
-          build_libraries_fll="build_libraries_fll-monolithic"
+        elif [[ $p == "-m" || $p == "--mode" ]] ; then
+          grab_next="mode"
+        elif [[ $p == "-p" || $p == "--process" ]] ; then
+          grab_next="process"
+        elif [[ $p == "-s" || $p == "--settings" ]] ; then
+          grab_next=settings_name
+        elif [[ $p == "-b" || $p == "--build" ]] ; then
+          grab_next=path_build
+        elif [[ $p == "-d" || $p == "--data" ]] ; then
+          grab_next=path_data
+        elif [[ $p == "-S" || $p == "--sources" ]] ; then
+          grab_next=path_sources
+        elif [[ $p == "-w" || $p == "--work" ]] ; then
+          grab_next=path_work
         elif [[ $p == "--enable-shared" ]] ; then
           enable_shared="yes"
         elif [[ $p == "--disable-shared" ]] ; then
@@ -97,22 +99,23 @@ generate_main(){
           operation_failure=fail-multiple
         fi
       else
-        if [[ $grab_next == "path_build" ]] ; then
-          path_build=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
-        elif [[ $grab_next == "build_settings" ]] ; then
-          path_build_settings=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
-        elif [[ $grab_next == "path_bash" ]] ; then
-          path_bash=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
-        elif [[ $grab_next == "path_c" ]] ; then
-          path_c=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
-        elif [[ $grab_next == "path_settings" ]] ; then
-          path_settings=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
-        elif [[ $grab_next == "project_built" ]] ; then
-          project_built="-$(echo $p | sed -e 's|/*$||')"
-        elif [[ $grab_next == "work_directory" ]] ; then
-          work_directory=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
-        elif [[ $grab_next == "defines_override" ]] ; then
+        if [[ $grab_next == "defines_override" ]] ; then
           defines_override="$p"
+        elif [[ $grab_next == "mode" ]] ; then
+          mode="$p"
+        elif [[ $grab_next == "process" ]] ; then
+          process="$p"
+        elif [[ $grab_next == "settings_name" ]] ; then
+          settings_name="$p"
+        elif [[ $grab_next == "path_build" ]] ; then
+          path_build=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
+        elif [[ $grab_next == "path_data" ]] ; then
+          path_data=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
+        elif [[ $grab_next == "path_sources" ]] ; then
+          path_sources=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
+          path_c="${path_sources}c/"
+        elif [[ $grab_next == "path_work" ]] ; then
+          path_work=$(echo $p | sed -e 's|^//*|/|' -e 's|/*$|/|')
         fi
 
         grab_next=
@@ -122,12 +125,10 @@ generate_main(){
     p=
   fi
 
-  if [[ $path_build_settings == "" ]] ; then
-    path_build_settings=data/build/
-  fi
-
-  settings_file=${path_build_settings}settings
-  settings_defines=${path_build_settings}defines
+  settings_file="${path_data}build/$settings_name"
+  settings_defines="${path_data}build/defines"
+  path_settings="${path_data}build/settings/"
+  path_build_stage="${path_build}stage/"
 
   generate_handle_colors
 
@@ -137,30 +138,98 @@ generate_main(){
     return 0
   fi
 
+  # FSS and Featurless Make supports more flexible mode names, but for the purpose of this bootstrap script and avoiding potential problems, keep it simple.
+  if [[ $mode != "" && $(echo "$mode" | grep -s -o "[^_[:alnum:]+-]") != "" ]] ; then
+    echo -e "${c_error}ERROR: the mode $c_notice$mode$c_error includes invalid characters, only alphanumeric, underscore, minus, and plus are allowed.$c_reset"
+    generate_cleanup
+    return 1
+  fi
+
   generate_load_settings
 
-  if [[ $path_bash == "" ]] ; then
-    path_bash=sources/bash/
-  elif [[ ! -d $path_bash ]] ; then
-    echo -e "${c_error}ERROR: the bash path of $c_notice$path_bash$c_error is not a valid directory.$c_reset"
+  if [[ $mode == "" ]] ; then
+    mode=${variables[$(generate_id modes_default)]}
+
+    if [[ $mode != "" && $(echo "$mode" | grep -s -o "[^_[:alnum:]+-]") != "" ]] ; then
+      echo -e "${c_error}ERROR: the mode $c_notice$mode$c_error includes invalid characters, only alphanumeric, underscore, minus, and plus are allowed.$c_reset"
+      generate_cleanup
+      return 1
+    fi
+  fi
+
+  generate_load_settings_mode
+
+  project_built="${path_build_stage}${variables[$(generate_id project_name)]}"
+  if [[ $process != "" ]] ; then
+    project_built="${project_built}-$process"
+  fi
+
+  if [[ ${variables[$(generate_id modes)]} == "" ]] ; then
+    if [[ $mode != "" ]] ; then
+      echo -e "${c_error}ERROR: the mode $c_notice$mode$c_error is not a valid mode, there are no available modes.$c_error$c_reset"
+      generate_cleanup
+      return 1
+    fi
+  else
+    let i=0
+    for m in ${variables[$(generate_id modes)]} ; do
+      if [[ "$mode" == "$m" ]] ; then
+        let i=1
+        break
+      fi
+    done
+
+    if [[ $i -eq 0 ]] ; then
+      echo -e "${c_error}ERROR: the mode $c_notice$mode$c_error is not a valid mode, it must be one of: $c_notice${variables[$(generate_id modes)]}$c_error.$c_reset"
+      generate_cleanup
+      return 1
+    fi
+  fi
+
+  if [[ ${variables[$(generate_id project_name)]} == "" ]] ; then
+    echo -e "${c_error}ERROR: the required setting '${c_notice}project_name$c_error' is not specified in the build settings file '$c_notice$settings_file$c_error'.$c_reset"
     generate_cleanup
-    return 0
+    return 1
   fi
 
-  if [[ $work_directory != "" && ! -d $work_directory ]] ; then
-    echo -e "${c_error}ERROR: the work directory $c_notice$work_directory$c_error is not a valid directory.$c_reset"
+  if [[ ${variables[$(generate_id version_major)]} == "" ]] ; then
+    echo -e "${c_error}ERROR: the required setting '${c_notice}version_major$c_error' is not specified in the build settings file '$c_notice$settings_file$c_error'.$c_reset"
     generate_cleanup
     return 1
   fi
 
-  if [[ $defines_override != "" && $(echo "$defines_override" | grep -s -o "[^_[:alnum:][:space:]]") != "" ]] ; then
-    echo -e "${c_error}ERROR: the defines override $c_notice$defines_override$c_error includes invalid characters, only alphanumeric, whitespace, and underscore are allowed.$c_reset"
+  if [[ ${variables[$(generate_id version_minor)]} == "" ]] ; then
+    echo -e "${c_error}ERROR: the required setting '${c_notice}version_minor$c_error' is not specified in the build settings file '$c_notice$settings_file$c_error'.$c_reset"
+    generate_cleanup
+    return 1
+  fi
+
+  if [[ ${variables[$(generate_id version_micro)]} == "" ]] ; then
+    echo -e "${c_error}ERROR: the required setting '${c_notice}version_micro$c_error' is not specified in the build settings file '$c_notice$settings_file$c_error'.$c_reset"
+    generate_cleanup
+    return 1
+  fi
+
+  if [[ $path_data == "" || ! -d $path_data ]] ; then
+    echo -e "${c_error}ERROR: the data directory $c_notice$path_data$c_error is not a valid directory.$c_reset"
+    generate_cleanup
+    return 1
+  fi
+
+  if [[ $path_sources == "" || ! -d $path_sources ]] ; then
+    echo -e "${c_error}ERROR: the sources directory $c_notice$path_sources$c_error is not a valid directory.$c_reset"
+    generate_cleanup
+    return 1
+  fi
+
+  if [[ $path_work != "" && ! -d $path_work ]] ; then
+    echo -e "${c_error}ERROR: the work directory $c_notice$path_work$c_error is not a valid directory.$c_reset"
     generate_cleanup
     return 1
   fi
 
-  if [[ ! -d $path_c && ( ${variables[$(generate_id build_sources_library)]} != "" || ${variables[$(generate_id build_sources_program)]} != "" || ${variables[$(generate_id build_sources_headers)]} != "" ) ]] ; then
-    echo -e "${c_error}ERROR: the c path of '$c_notice$path_c$c_error' is invalid.$c_reset"
+  if [[ $defines_override != "" && $(echo "$defines_override" | grep -s -o "[^_[:alnum:][:space:]]") != "" ]] ; then
+    echo -e "${c_error}ERROR: the defines override $c_notice$defines_override$c_error includes invalid characters, only alphanumeric, whitespace, and underscore are allowed.$c_reset"
     generate_cleanup
     return 1
   fi
@@ -170,10 +239,10 @@ generate_main(){
     generate_cleanup
     return 1
   elif [[ $operation == "build" ]] ; then
-    if [[ -f ${path_build}.built$project_built ]] ; then
+    if [[ -f ${project_built}.built ]] ; then
       echo -e "${c_warning}WARNING: this project has already been built.$c_reset"
     else
-      if [[ ! -f ${path_build}.prepared$project_built ]] ; then
+      if [[ ! -f ${project_built}.prepared ]] ; then
         generate_prepare_build
       fi
 
@@ -222,7 +291,7 @@ generate_help(){
   echo -e " ${c_notice}Version $version$c_reset"
   echo
   echo -e "$c_highlight$system_name$c_reset $c_notice<${c_reset}operation$c_notice>$c_reset"
-  echo -e " ${c_important}build${c_reset}  Build or compile the code."
+  echo -e " ${c_important}build${c_reset}  Build or compile the code based on build settings file."
   echo -e " ${c_important}clean${c_reset}  Delete all build files."
   echo
   echo -e "${c_highlight}Options:$c_reset"
@@ -232,16 +301,15 @@ generate_help(){
   echo -e " +${c_important}v$c_reset, ++${c_important}version$c_reset   Print the version number of this program."
   echo
   echo -e "${c_highlight}Generate Options:$c_reset"
-  echo -e " -${c_important}b$c_reset, --${c_important}build${c_reset}           Custom build directory."
-  echo -e " -${c_important}s$c_reset, --${c_important}settings${c_reset}        Custom build settings directory."
-  echo -e " -${c_important}B$c_reset, --${c_important}path_bash${c_reset}       Custom path to the bash source files."
-  echo -e " -${c_important}c$c_reset, --${c_important}path_c${c_reset}          Custom path to the c source files."
-  echo -e " -${c_important}S$c_reset, --${c_important}path_settings${c_reset}   Custom path to the settings files."
-  echo -e " -${c_important}p$c_reset, --${c_important}project${c_reset}         Project name for storing build status."
-  echo -e " -${c_important}w$c_reset, --${c_important}work_directory${c_reset}  Use includes/libraries from this directory instead of system."
-  echo -e " -${c_important}d$c_reset, --${c_important}defines${c_reset}         Override custom defines with these defines."
-  echo -e " -${c_important}l$c_reset, --${c_important}level${c_reset}           Use FLL dependencies by level (-lfll_0, -lfll_1, -lfll_2)."
-  echo -e " -${c_important}m$c_reset, --${c_important}monolithic${c_reset}      Use FLL dependencies by monolithic (-lfll)."
+  echo -e " -${c_important}d$c_reset, --${c_important}defines${c_reset}    Override custom defines with these defines."
+  echo -e " -${c_important}m$c_reset, --${c_important}mode${c_reset}       Use this mode when processing the build settings."
+  echo -e " -${c_important}p$c_reset, --${c_important}process${c_reset}    Process name for storing build states."
+  echo -e " -${c_important}s$c_reset, --${c_important}settings${c_reset}   Use this settings file, from within the source settings directory."
+  echo
+  echo -e " -${c_important}b$c_reset, --${c_important}build${c_reset}      Specify a custom build directory."
+  echo -e " -${c_important}D$c_reset, --${c_important}data${c_reset}       Specify a custom path to the data files."
+  echo -e " -${c_important}S$c_reset, --${c_important}sources${c_reset}    Specify a custom path to the source files."
+  echo -e " -${c_important}w$c_reset, --${c_important}work${c_reset}       Use includes/libraries/programs from this directory instead of system."
   echo
   echo -e "${c_highlight}Special Options:$c_reset"
   echo -e " --${c_important}enable-shared${c_reset}   Forcibly do build shared files."
@@ -255,30 +323,62 @@ generate_id(){
   local name=$1
 
   case $name in
-    "project_name") echo -n 0;;
-    "project_level") echo -n 1;;
-    "version_major") echo -n 2;;
-    "version_minor") echo -n 3;;
-    "version_micro") echo -n 4;;
-    "build_compiler") echo -n 5;;
-    "build_linker") echo -n 6;;
-    "build_libraries") echo -n 7;;
-    "$build_libraries_fll") echo -n 8;;
-    "build_sources_library") echo -n 9;;
-    "build_sources_program") echo -n 10;;
-    "build_sources_headers") echo -n 11;;
-    "build_sources_bash") echo -n 12;;
-    "build_sources_settings") echo -n 13;;
-    "build_shared") echo -n 14;;
-    "build_static") echo -n 15;;
-    "defines_all") echo -n 16;;
-    "defines_shared") echo -n 17;;
-    "defines_static") echo -n 18;;
-    "flags_all") echo -n 19;;
-    "flags_shared") echo -n 20;;
-    "flags_static") echo -n 21;;
-    "flags_library") echo -n 22;;
-    "flags_program") echo -n 23;;
+    "build_compiler") echo -n 0;;
+    "build_language") echo -n 1;;
+    "build_libraries") echo -n 2;;
+    "build_linker") echo -n 3;;
+    "build_script") echo -n 4;;
+    "build_shared") echo -n 5;;
+    "build_sources_headers") echo -n 6;;
+    "build_sources_library") echo -n 7;;
+    "build_sources_program") echo -n 8;;
+    "build_sources_setting") echo -n 9;;
+    "build_sources_script") echo -n 10;;
+    "build_static") echo -n 11;;
+    "defines_all") echo -n 12;;
+    "defines_shared") echo -n 13;;
+    "defines_static") echo -n 14;;
+    "environment") echo -n 15;;
+    "flags_all") echo -n 16;;
+    "flags_library") echo -n 17;;
+    "flags_program") echo -n 18;;
+    "flags_shared") echo -n 19;;
+    "flags_static") echo -n 20;;
+    "modes") echo -n 21;;
+    "modes_default") echo -n 22;;
+    "path_language") echo -n 23;;
+    "path_headers") echo -n 24;;
+    "path_library_script") echo -n 25;;
+    "path_library_shared") echo -n 26;;
+    "path_library_static") echo -n 27;;
+    "path_program_script") echo -n 28;;
+    "path_program_shared") echo -n 29;;
+    "path_program_static") echo -n 30;;
+    "process_post") echo -n 31;;
+    "process_pre") echo -n 32;;
+    "project_name") echo -n 33;;
+    "search_exclusive") echo -n 34;;
+    "search_shared") echo -n 35;;
+    "search_static") echo -n 36;;
+    "version_major") echo -n 37;;
+    "version_micro") echo -n 38;;
+    "version_minor") echo -n 39;;
+
+    "build_libraries-$mode") echo -n 40;;
+    "build_sources_headers-$mode") echo -n 41;;
+    "build_sources_library-$mode") echo -n 42;;
+    "build_sources_program-$mode") echo -n 43;;
+    "build_sources_setting-$mode") echo -n 44;;
+    "build_sources_script-$mode") echo -n 45;;
+    "defines_all-$mode") echo -n 46;;
+    "defines_shared-$mode") echo -n 47;;
+    "defines_static-$mode") echo -n 48;;
+    "environment-$mode") echo -n 49;;
+    "flags_all-$mode") echo -n 50;;
+    "flags_library-$mode") echo -n 51;;
+    "flags_program-$mode") echo -n 52;;
+    "flags_shared-$mode") echo -n 53;;
+    "flags_static-$mode") echo -n 54;;
   esac
 }
 
@@ -287,8 +387,8 @@ generate_load_settings(){
   local i=
   local key=
 
-  if [[ ! -d $path_build_settings ]] ; then
-    echo -e "${c_error}ERROR: no build settings directory $c_notice$path_build_settings$c_error could not be found or is not a valid directory.$c_reset"
+  if [[ ! -d ${path_data}build/ ]] ; then
+    echo -e "${c_error}ERROR: no build settings directory '$c_notice${path_data}build/$c_error' could not be found or is not a valid directory.$c_reset"
     failure=1
   elif [[ ! -f $settings_file ]] ; then
     echo -e "${c_error}ERROR: no settings file $c_notice$settings_file$c_error could not be found or is not a valid file.$c_reset"
@@ -300,37 +400,29 @@ generate_load_settings(){
     exit $failure
   fi
 
-  for i in project_name project_level version_major version_minor version_micro build_compiler build_linker build_libraries $build_libraries_fll build_sources_library build_sources_program build_sources_headers build_sources_settings build_shared build_static defines_all defines_shared defines_static flags_all flags_shared flags_static flags_library flags_program ; do
+  for i in build_compiler build_language build_libraries build_linker build_script build_shared build_sources_headers build_sources_library build_sources_program build_sources_setting build_sources_script build_static defines_all defines_shared defines_static environment flags_all flags_library flags_program flags_shared flags_static modes modes_default path_language path_headers path_library_script path_library_shared path_library_static path_program_script path_program_shared path_program_static process_post process_pre project_name search_exclusive search_shared search_static version_major version_micro version_minor ; do
     variables[$(generate_id $i)]=$(grep -s -o "^[[:space:]]*$i[[:space:]].*\$" $settings_file | sed -e "s|^[[:space:]]*$i\>||" -e 's|^[[:space:]]*||')
   done
+}
 
-  if [[ $project_name == "" ]] ; then
-    key="project_name"
-    if [[ ${variables[$key]} != "" ]] ; then
-      project_built="-${variables[$key]}"
-    fi
-  fi
+generate_load_settings_mode(){
+  local i=
+
+  for i in build_libraries-$mode build_sources_headers-$mode build_sources_library-$mode build_sources_program-$mode build_sources_setting-$mode build_sources_script-$mode defines_all-$mode defines_shared-$mode defines_static-$mode environment-$mode flags_all-$mode flags_library-$mode flags_program-$mode flags_shared-$mode flags_static-$mode ; do
+    variables[$(generate_id $i)]=$(grep -s -o "^[[:space:]]*$i[[:space:]].*\$" $settings_file | sed -e "s|^[[:space:]]*$i\>||" -e 's|^[[:space:]]*||')
+  done
 }
 
 generate_prepare_build(){
   local failure=
-  local level=${variables[$(generate_id project_level)]}
   local alt=$1
+  local i=
 
-  mkdir -vp ${path_build}{includes,programs/{shared,static},libraries/{shared,static},objects,bash,settings} || failure=1
-
-  if [[ $failure == "" && $level != "" ]] ; then
-    mkdir -vp ${path_build}includes/level_$level || failure=1
-  fi
+  mkdir -vp ${path_build}{documents,includes,libraries/{script,shared,static},objects,programs/{script,shared,static},settings,stage} || failure=1
 
   if [[ $failure == "" ]] ; then
-    for i in $headers ; do
-      ln -vsf ../../$i ${path_build}includes/level_$level/
-
-      if [[ $? != 0 ]] ; then
-        failure=1
-        break
-      fi
+    for i in ${variables[$(generate_id path_headers)]} ; do
+      mkdir -vp ${path_build}includes/$i || failure=1
     done
   fi
 
@@ -339,30 +431,32 @@ generate_prepare_build(){
     exit $failure
   fi
 
-  touch ${path_build}.prepared$project_built
+  touch ${project_built}.prepared
 }
 
 generate_operation_build(){
   local failure=
   local name=${variables[$(generate_id project_name)]}
-  local level=${variables[$(generate_id project_level)]}
   local major=${variables[$(generate_id version_major)]}
   local minor=${variables[$(generate_id version_minor)]}
   local micro=${variables[$(generate_id version_micro)]}
   local compiler=${variables[$(generate_id build_compiler)]}
   local linker=${variables[$(generate_id build_linker)]}
-  local arguments="${variables[$(generate_id "$build_libraries_fll")]} ${variables[$(generate_id build_libraries)]}"
   local arguments_include="-I${path_build}includes"
   local arguments_shared="-L${path_build}libraries/shared"
   local arguments_static="-L${path_build}libraries/static"
+  local search_exclusive=${variables[$(generate_id search_exlusive)]}
+  local search_shared=${variables[$(generate_id search_shared)]}
+  local search_static=${variables[$(generate_id search_static)]}
   local shared=${variables[$(generate_id build_shared)]}
   local static=${variables[$(generate_id build_static)]}
   local sources_library=${variables[$(generate_id build_sources_library)]}
   local sources_program=${variables[$(generate_id build_sources_program)]}
   local sources_headers=${variables[$(generate_id build_sources_headers)]}
   local sources_bash=${variables[$(generate_id build_sources_bash)]}
-  local sources_settings=${variables[$(generate_id build_sources_settings)]}
+  local sources_setting=${variables[$(generate_id build_sources_setting)]}
   local sources=
+  local libraries=${variables[$(generate_id build_libraries)]}
   local links=
   local defines=${variables[$(generate_id defines_all)]}
   local defines_shared=${variables[$(generate_id defines_shared)]}
@@ -373,13 +467,93 @@ generate_operation_build(){
   local flags_library=${variables[$(generate_id flags_library)]}
   local flags_program=${variables[$(generate_id flags_program)]}
   local i=
+  local n=
   local alt=$1
   local directory=
+  local path_headers=${variables[$(generate_id path_headers)]}
+
+  if [[ $sources_library == "" ]] ; then
+    sources_library=${variables[$(generate_id build_sources_library-$mode)]}
+  else
+    sources_library="$sources_library ${variables[$(generate_id build_sources_library-$mode)]}"
+  fi
+
+  if [[ $sources_program == "" ]] ; then
+    sources_program=${variables[$(generate_id build_sources_program-$mode)]}
+  else
+    sources_program="$sources_program ${variables[$(generate_id build_sources_program-$mode)]}"
+  fi
+
+  if [[ $sources_headers == "" ]] ; then
+    sources_headers=${variables[$(generate_id build_sources_headers-$mode)]}
+  else
+    sources_headers="$sources_headers ${variables[$(generate_id build_sources_headers-$mode)]}"
+  fi
+
+  if [[ $sources_setting == "" ]] ; then
+    sources_setting=${variables[$(generate_id build_sources_setting-$mode)]}
+  else
+    sources_setting="$sources_setting ${variables[$(generate_id build_sources_setting-$mode)]}"
+  fi
 
-  if [[ $work_directory != "" ]] ; then
-    flags_all="-I${work_directory}includes/ $flags_all"
-    flags_shared="-L${work_directory}libraries/shared/ $flags_shared"
-    flags_static="-L${work_directory}libraries/static/ $flags_static"
+  if [[ $libraries == "" ]] ; then
+    libraries=${variables[$(generate_id build_libraries-$mode)]}
+  else
+    libraries="$libraries ${variables[$(generate_id build_libraries-$mode)]}"
+  fi
+
+  if [[ $defines == "" ]] ; then
+    defines=${variables[$(generate_id defines_all-$mode)]}
+  else
+    defines="$defines ${variables[$(generate_id defines_all-$mode)]}"
+  fi
+
+  if [[ $defines_shared == "" ]] ; then
+    defines_shared=${variables[$(generate_id defines_shared-$mode)]}
+  else
+    defines_shared="$defines_shared ${variables[$(generate_id defines_shared-$mode)]}"
+  fi
+
+  if [[ $defines_static == "" ]] ; then
+    defines_static=${variables[$(generate_id defines_static-$mode)]}
+  else
+    defines_static="$defines_static ${variables[$(generate_id defines_static-$mode)]}"
+  fi
+
+  if [[ $flags_all == "" ]] ; then
+    flags_all=${variables[$(generate_id flags_all-$mode)]}
+  else
+    flags_all="$flags_all ${variables[$(generate_id flags_all-$mode)]}"
+  fi
+
+  if [[ $flags_shared == "" ]] ; then
+    flags_shared=${variables[$(generate_id flags_shared-$mode)]}
+  else
+    flags_shared="$flags_shared ${variables[$(generate_id flags_shared-$mode)]}"
+  fi
+
+  if [[ $flags_static == "" ]] ; then
+    flags_static=${variables[$(generate_id flags_static-$mode)]}
+  else
+    flags_static="$flags_static ${variables[$(generate_id flags_static-$mode)]}"
+  fi
+
+  if [[ $flags_library == "" ]] ; then
+    flags_library=${variables[$(generate_id flags_library-$mode)]}
+  else
+    flags_library="$flags_library ${variables[$(generate_id flags_library-$mode)]}"
+  fi
+
+  if [[ $flags_program == "" ]] ; then
+    flags_program=${variables[$(generate_id flags_program-$mode)]}
+  else
+    flags_program="$flags_program ${variables[$(generate_id flags_program-$mode)]}"
+  fi
+
+  if [[ $path_work != "" ]] ; then
+    arguments_include="$arguments_include -I${path_work}includes/"
+    arguments_shared="$arguments_shared -L${path_work}libraries/shared/"
+    arguments_static="$arguments_static -L${path_work}libraries/static/"
   fi
 
   if [[ $defines_override != "" ]] ; then
@@ -411,14 +585,18 @@ generate_operation_build(){
 
   if [[ $enable_shared == "yes" ]] ; then
     shared="yes"
+    search_shared="yes"
   elif [[ $enable_shared == "no" ]] ; then
     shared="no"
+    search_shared="no"
   fi
 
   if [[ $enable_static == "yes" ]] ; then
     static="yes"
+    search_static="yes"
   elif [[ $enable_static == "no" ]] ; then
     static="no"
+    search_static="no"
   fi
 
   if [[ $shared != "yes" && $static != "yes" ]] ; then
@@ -427,6 +605,12 @@ generate_operation_build(){
     exit -1
   fi
 
+  if [[ $search_shared != "yes" && $search_static != "yes" ]] ; then
+    echo -e "${c_error}ERROR: Cannot Build, either search_shared or search_static must be set to 'yes'.$c_reset"
+    generate_cleanup
+    exit -1
+  fi
+
   for i in $sources_library ; do
     if [[ $i != "$(echo $i | sed -e 's|^//*||' -e 's|^\.\.//*||' -e 's|/*$||')" ]] ; then
       echo -e "${c_error}ERROR: Cannot Build, invalid source_library path provided: '$i'.$c_reset"
@@ -459,16 +643,29 @@ generate_operation_build(){
     fi
   done
 
-  for i in $sources_settings ; do
+  for i in $sources_setting ; do
     if [[ $i != "$(echo $i | sed -e 's|^//*||' -e 's|^\.\.//*||' -e 's|/*$||')" ]] ; then
-      echo -e "${c_error}ERROR: Cannot Build, invalid sources_settings path provided: '$i'.$c_reset"
+      echo -e "${c_error}ERROR: Cannot Build, invalid sources_setting path provided: '$i'.$c_reset"
       generate_cleanup
       exit -1
     fi
   done
 
-  if [[ $sources_settings != "" ]] ; then
-    for i in $sources_settings ; do
+  if [[ $search_shared == "no" ]] ; then
+    arguments_shared=
+  fi
+
+  if [[ $search_static == "no" ]] ; then
+    arguments_static=
+  fi
+
+  # when not in search exclusive mode, allow static libraries to be linked into shared libraries if the shared library is not found first.
+  if [[ $search_exclusive == "no" ]] ; then
+    arguments_shared="$arguments_shared $arguments_static"
+  fi
+
+  if [[ $sources_setting != "" ]] ; then
+    for i in $sources_setting ; do
       directory=$(dirname $i)
 
       if [[ $directory == "." ]] ; then
@@ -484,7 +681,7 @@ generate_operation_build(){
   fi
 
   if [[ $failure == "" && $sources_headers != "" ]] ; then
-    if [[ $level == "" ]] ; then
+    if [[ $path_headers == "" ]] ; then
       for i in $sources_headers ; do
         directory=$(dirname $i)
 
@@ -500,7 +697,7 @@ generate_operation_build(){
       done
     else
       for i in $sources_headers ; do
-        cp -vf $path_c$i ${path_build}includes/level_$level/ || failure=1
+        cp -vf $path_c$i ${path_build}includes/$path_headers/ || failure=1
       done
     fi
   fi
@@ -512,8 +709,8 @@ generate_operation_build(){
         sources="$sources$path_c$i "
       done
 
-      echo $compiler $sources -shared -Wl,-soname,lib$name.so.$major -o ${path_build}libraries/shared/lib$name.so.$major.$minor.$micro $arguments_shared $arguments_include $arguments $flags_all $flags_shared $flags_library
-      $compiler $sources -shared -Wl,-soname,lib$name.so.$major -o ${path_build}libraries/shared/lib$name.so.$major.$minor.$micro $arguments_shared $arguments_include $arguments $flags_all $flags_shared $flags_library || failure=1
+      echo $compiler $sources -shared -Wl,-soname,lib$name.so.$major -o ${path_build}libraries/shared/lib$name.so.$major.$minor.$micro $arguments_shared $arguments_include $libraries $flags_all $flags_shared $flags_library
+      $compiler $sources -shared -Wl,-soname,lib$name.so.$major -o ${path_build}libraries/shared/lib$name.so.$major.$minor.$micro $arguments_shared $arguments_include $libraries $flags_all $flags_shared $flags_library || failure=1
 
       if [[ $failure == "" ]] ; then
         ln -vsf lib$name.so.$major.$minor.$micro ${path_build}libraries/shared/lib$name.so.$major || failure=1
@@ -533,8 +730,8 @@ generate_operation_build(){
         sources="$sources$path_c$i "
       done
 
-      echo $compiler $sources -o ${path_build}programs/shared/$name $arguments_shared $arguments_include $links $arguments $flags_all $flags_shared $flags_program
-      $compiler $sources -o ${path_build}programs/shared/$name $arguments_shared $arguments_include $links $arguments $flags_all $flags_shared $flags_program || failure=1
+      echo $compiler $sources -o ${path_build}programs/shared/$name $arguments_shared $arguments_include $links $libraries $flags_all $flags_shared $flags_program
+      $compiler $sources -o ${path_build}programs/shared/$name $arguments_shared $arguments_include $links $libraries $flags_all $flags_shared $flags_program || failure=1
     fi
   fi
 
@@ -543,6 +740,7 @@ generate_operation_build(){
     if [[ $sources_library != "" ]] ; then
       for i in $sources_library ; do
         directory=$(dirname $i)
+        n=$(basename $i | sed -e 's|\.c$||')
 
         if [[ $directory != "." && ! -d ${path_build}objects/$directory ]] ; then
           mkdir -vp ${path_build}objects/$directory
@@ -553,10 +751,10 @@ generate_operation_build(){
           fi
         fi
 
-        sources="$sources${path_build}objects/$i.o "
+        sources="$sources${path_build}objects/$directory/$n.o "
 
-        echo $compiler $path_c$i -c -static -o ${path_build}objects/$i.o $arguments_static $arguments_include $arguments $flags_all $flags_static $flags_library
-        $compiler $path_c$i -c -static -o ${path_build}objects/$i.o $arguments_static $arguments_include $arguments $flags_all $flags_static $flags_library || failure=1
+        echo $compiler $path_c$i -c -static -o ${path_build}objects/$directory/$n.o $arguments_static $arguments_include $libraries $flags_all $flags_static $flags_library
+        $compiler $path_c$i -c -static -o ${path_build}objects/$directory/$n.o $arguments_static $arguments_include $libraries $flags_all $flags_static $flags_library || failure=1
 
         if [[ $failure == "1" ]] ; then
           break;
@@ -581,51 +779,35 @@ generate_operation_build(){
         sources="$sources$path_c$i "
       done
 
-      echo $compiler -static -o ${path_build}programs/static/$name $sources $arguments_static $arguments_include $links $arguments $flags_all $flags_static $flags_program
-      $compiler -static -o ${path_build}programs/static/$name $sources $arguments_static $arguments_include $links $arguments $flags_all $flags_static $flags_program || failure=1
+      echo $compiler $sources -static -o ${path_build}programs/static/$name $arguments_static $arguments_include $links $libraries $flags_all $flags_static $flags_program
+      $compiler $sources -static -o ${path_build}programs/static/$name $arguments_static $arguments_include $links $libraries $flags_all $flags_static $flags_program || failure=1
     fi
   fi
 
-  if [[ $failure == "" && $sources_bash != "" ]] ; then
-    for i in $sources_bash ; do
-      directory=$(dirname $i)
-
-      if [[ $directory == "." ]] ; then
-        cp -vf $path_bash$i ${path_build}bash/ || failure=1
-      else
-        mkdir -vp ${path_build}bash/$directory || failure=1
-
-        if [[ $failure == "" ]] ; then
-          cp -vf $path_bash$i ${path_build}bash/${directory}/ || failure=1
-        fi
-      fi
-    done
-  fi
-
   if [[ $failure != "" ]] ; then
     echo -e "${c_error}ERROR: failed to build.$c_reset"
     generate_cleanup
     exit $failure
   fi
 
-  touch ${path_build}.built$project_built
+  touch ${project_built}.built
 }
 
 generate_operation_clean(){
   local i=
 
-  for i in ${path_build}{includes,programs,libraries,objects,bash,settings} ; do
+  for i in ${path_build}{documents,includes,libraries,objects,programs,settings,stage} ; do
     if [[ -e $i ]] ; then
       rm -vRf $i
     fi
   done
 
-  if [[ -f ${path_build}.prepared$project_built ]] ; then
-    rm -vf ${path_build}.prepared$project_built
+  if [[ -f ${project_built}.prepared ]] ; then
+    rm -vf ${project_built}.prepared
   fi
 
-  if [[ -f ${path_build}.built$project_built ]] ; then
-    rm -vf ${path_build}.built$project_built
+  if [[ -f ${project_built}.built ]] ; then
+    rm -vf ${project_built}.built
   fi
 }
 
@@ -635,6 +817,7 @@ generate_cleanup(){
   unset generate_help
   unset generate_id
   unset generate_load_settings
+  unset generate_load_settings_mode
   unset generate_prepare_build
   unset generate_operation_build
   unset generate_operation_clean