#!/bin/bash MODE_DIR="${ROOT_DIR}/remote" MODULES_DIR="${MODE_DIR}/modules" # Keep track of processed modules PROCESSED_MODULES="" initial_checks () { # check for required tools for BIN in git locate depmod do local TEST=$(which ${BIN}) [ -z "$TEST" ] && pinfo "Installing $BIN..." && apt-get install $BIN done } read_config () { # unset previous variables from other config files for VARNAME in "${!REQUIRED_*}"; do unset $VARNAME done local MODULE_CONFIG="${MODULE_DIR}/${MODULE}.conf" # otherwise, use the generic one [ ! -e "${MODULE_CONFIG}" ] && perror "Config for '$MODULE' not found." . "${MODULE_CONFIG}" || perror "Sourcing '${MODULE_CONFIG}' failed." if [ -e "${MODULE_CONFIG}.${PACKET_MANAGER}" ]; then # a specific tool.conf seems to exist, use it to override certain vars . "${MODULE_CONFIG}.${PACKET_MANAGER}" || perror "Sourcing '${MODULE_CONFIG}.${PACKET_MANAGER}' failed." fi } read_build () { local BUILD_SCRIPT="${MODULE_DIR}/${MODULE}.build" [ ! -e "${BUILD_SCRIPT}" ] && perror "Build script for specified tool not found." . "${BUILD_SCRIPT}" || perror "Sourcing '${BUILD_SCRIPT}' failed." } copy_files_with_deps () { [ ! -d $MODULE_BUILD_DIR ] && pinfo "No build directory found, skipping dependency copying" && return 0 cd $MODULE_BUILD_DIR COPYFILES_LIST="list_wanted_stage3.2" [ -e ${COPYFILES_LIST} ] && rm ${COPYFILES_LIST} [ ! -z "${REQUIRED_BINARIES}" ] && pinfo "Gathering required binaries from config file..." for FILENAME in ${REQUIRED_BINARIES} do local FILE_CANDIDATES=$( find . -name "${FILENAME}" -a \( -type f -o -type l \) ) # only do if more than one candidate found if [ $(echo $FILE_CANDIDATES | wc -w) -gt 1 ]; then pdebug "Candidates for $FILENAME are: $(echo $FILE_CANDIDATES)" local FINAL_LIST="" for FILE in $FILE_CANDIDATES; do local TESTFILE="$(readlink -f "$FILE")" pdebug " $FILE leads to $TESTFILE" [ -f "$TESTFILE" -a -x "$TESTFILE" ] && [ "x$(grep -l -E '^(.ELF|#!)' "$TESTFILE")" != "x" ] && FINAL_LIST="$FINAL_LIST $FILE" done FINAL_LIST=$(trim "$FINAL_LIST") if [ -z "$FINAL_LIST" ]; then pwarning "\tNo Binary found for ${FILENAME}. Skipping." continue fi if [[ "$FINAL_LIST" == *" "* ]]; then pwarning "Found more than one match for required file '$FILENAME': $FINAL_LIST" else pdebug "\tFound ${FILENAME} at ${FILE}" fi else # one candidate FINAL_LIST=${FILE_CANDIDATES} fi for FILE in $FINAL_LIST; do pdebug "* $FILE" strip $FILE || pwarning "Could not strip '${FILE}'" get_link_chain "${MODULE_BUILD_DIR}/${FILE}" "${MODULE_BUILD_DIR}" >> "${COPYFILES_LIST}" get_dynamic_dependencies -l "${MODULE_BUILD_DIR}" "${FILE}" >> "${COPYFILES_LIST}" done done [ ! -z "${REQUIRED_LIBRARIES}" ] && pinfo "Gathering required libraries from config file..." for LIB in ${REQUIRED_LIBRARIES} do for LOCATION in $(find . -name ${LIB}.so\*) do pdebug "* $LOCATION" strip $LOCATION || pwarning "Could not strip '${LOCATION}'" get_link_chain "${MODULE_BUILD_DIR}/${LOCATION}" "${MODULE_BUILD_DIR}" >> "${COPYFILES_LIST}" get_dynamic_dependencies -l "${MODULE_BUILD_DIR}" "${LOCATION}" >> "${COPYFILES_LIST}" done done [ ! -z "${REQUIRED_DIRECTORIES}" ] && pinfo "Gathering required directories from config file..." local CURRENT_PWD=$(pwd) # Prevent calling pwd 50000 times inside the loop below for ENTRY in ${REQUIRED_DIRECTORIES} do pdebug "* .$ENTRY" echo "./${ENTRY}" >> "${COPYFILES_LIST}" for BIN in $(find ".${ENTRY}" -type f -not -name '*.a' | xargs grep -l '^.ELF') do #pdebug "\tSearching libs for ${BIN}..." get_link_chain "${MODULE_BUILD_DIR}/${BIN}" "${MODULE_BUILD_DIR}" >> "${COPYFILES_LIST}" get_dynamic_dependencies -l "${MODULE_BUILD_DIR}" "${BIN}" >> "${COPYFILES_LIST}" done done [ ! -z "${REQUIRED_FILES}" ] && pinfo "Gathering required files from config file..." for ENTRY in ${REQUIRED_FILES} do get_link_chain "${MODULE_BUILD_DIR}/${ENTRY}" "${MODULE_BUILD_DIR}" >> "${COPYFILES_LIST}" get_dynamic_dependencies -l "${MODULE_BUILD_DIR}" "${MODULE_BUILD_DIR}/.${ENTRY}" >> "${COPYFILES_LIST}" done #copy to initramfsdir pdebug "File list generated at ${MODULE_BUILD_DIR}/${COPYFILES_LIST}." if [ -s "$COPYFILES_LIST" ]; then local CLISTCOUNT=$(cat "$COPYFILES_LIST" | wc -l) pinfo "Copying $CLISTCOUNT files to '${TARGET_BUILD_DIR}'." tarcopy "$(cat "$COPYFILES_LIST"|sort -u)" "${TARGET_BUILD_DIR}" fi } generate_target() { initial_checks #copy_kernel TARGET=$1 && shift TARGET_DIR="${MODE_DIR}/targets/${TARGET}" TARGET_BUILD_DIR="${MODE_DIR}/builds/${TARGET}" [ -e "${ROOT_DIR}/logs/${TARGET}.size" ] && . "${ROOT_DIR}/logs/${TARGET}.size" || echo "declare -A BUILD_SIZE" >> "${ROOT_DIR}/logs/${TARGET}.size" [ -d $TARGET_DIR ] || perror "Given target directory does not exist: $TARGET_DIR" [[ $TARGET == builds || $TARGET == modules ]] && \ perror "Target directory cannot be named 'builds' nor 'modules'." pinfo "Generating '$TARGET_BUILD_DIR' for '$TARGET'" # if no arguments assume all. if [ "x$1" = "x" -o "x$1" = "xall" ]; then MODULES=$(ls ${TARGET_DIR}) set -- $MODULES else # tools = arguments given MODULES=$@ fi pinfo "Activated modules in '${TARGET}':" pinfo "\t$(echo ${MODULES})" # copy basic libs pinfo "Copying libc and ld-linux used by ${SHELL}" tarcopy "$(list_basic_libs)" "${TARGET_BUILD_DIR}" [ -d "$TARGET_BUILD_DIR" ] && TARGET_BUILD_SIZE=$(du -bc "${TARGET_BUILD_DIR}" | awk 'END {print $1}') || TARGET_BUILD_SIZE=0 # now iterate over given tools and copy them while (( "$#" )); do process_module "$1" shift done post_process_target pinfo "Target completed. Total size: $(du -bsh "${TARGET_BUILD_DIR}" | awk 'END {print $1}')" TOOL_STR="" } process_module() { [ "$#" -ne "1" ] && perror "process_module: want 1 param." local MODULE="$1" [[ "$PROCESSED_MODULES" == *"!${MODULE}!"* ]] && return # Already processed this module PROCESSED_MODULES="${PROCESSED_MODULES}!${MODULE}!" local MODULE_DIR="${TARGET_DIR}/${MODULE}" local MODULE_BUILD_DIR="${MODULE_DIR}/build" local TOOL_STR="" pinfo ">>>>>>>>>>>>>>>>> Processing module [ $MODULE ]" TOOL_STR="[${MODULE}]" if [ -d "${MODULE_DIR}" ]; then #[ "x$DEBUG" != "x1" ] \ # && echo "Logging to ${TOOL_DIR}/${TOOL}/stage32.log" \ # && exec 6>&1 > ${TOOL_DIR}/${TOOL}/stage32.log # TODO: Make above work with the new logging system (add function to logging.inc to switch logfile) cd "${MODULE_DIR}" || perror "Module dir '${MODULE_DIR}' seems to exist, but cd to it failed." pinfo "## Reading config" read_config # Check if this module has a dependency that wasn't built yet: if [ ! -z "$REQUIRED_MODULES" ]; then pinfo "$MODULE depends on ${REQUIRED_MODULES}...." for DEP in $REQUIRED_MODULES; do process_module "$DEP" done # Read old config again, as it got overwritten by the deps cd "${MODULE_DIR}" || perror "Tool dir '${MODULE_DIR}' seems to exist, but cd to it failed (after building deps)." read_config pinfo "<<<<<<<<<<<<<<<<< Dependency modules processed, back to module [ $MODULE ]" fi pinfo "## Reading build" read_build pinfo "## Installing dependencies" install_dependencies pinfo "## Fetching source" [ -e "${MODULE_DIR}/.fetched_source" ] || { fetch_source && touch "${MODULE_DIR}/.fetched_source"; } pinfo "## Building" [ -e "${MODULE_DIR}/.built" ] || { build && touch "${MODULE_DIR}/.built"; } # remove *.la files as they might confuse libtool/linker of other tool packages [ -d "${MODULE_BUILD_DIR}" ] && find "${MODULE_BUILD_DIR}" -name '*.la' -exec rm -f {} \; [ -d "${TARGET_BUILD_DIR}" ] && TARGET_BUILD_SIZE=$(du -bc "${TARGET_BUILD_DIR}" | awk 'END {print $1}') || TARGET_BUILD_SIZE=0 pinfo "## Copying files with dependencies" copy_files_with_deps pinfo "## Copying required system files" copy_system_files pinfo "## Copying static module files" copy_static_data pinfo "## Post copy" post_copy # reset pipes #[ "x$DEBUG" != "x1" ] && exec 1>&6 6>&- # TODO calc_size #sets MODULE_BUILD_SIZE pinfo "Module completed. Total size: ${MODULE_BUILD_SIZE}" else pwarning "Module directory for '$MODULE' not found." fi } post_process_target() { local TOOL_STR="$TOOL_STR post_process_target:" #move systemd files from /lib to /etc/lib pinfo "move systemd files from /lib/systemd to /etc/systemd" if [ -d "${TARGET_BUILD_DIR}/lib/systemd" ]; then cd "${TARGET_BUILD_DIR}/lib" tarcopy "systemd" "${TARGET_BUILD_DIR}/etc" cd - &> /dev/null rm -r "${TARGET_BUILD_DIR}/lib/systemd" fi } clean_modules() { TARGET=$1 shift TARGET_DIR="${MODE_DIR}/targets/${TARGET}" TARGET_BUILD_DIR="${MODE_DIR}/builds/${TARGET}" [ -d $TARGET_DIR ] || perror "Given target directory does not exist: $TARGET_DIR" if [ "x$1" = "x" -o "x$1" = "xall" ]; then if [ -e ${ROOT_DIR}/logs/${TARGET}.size ]; then rm "${ROOT_DIR}/logs/${TARGET}.size" || perror "Could not delete logs/${TARGET}.size" fi if [ -d ${TARGET_BUILD_DIR} ]; then pinfo "Cleaning '${TARGET_BUILD_DIR}'" \ && rm -rf "${TARGET_BUILD_DIR}"/* \ || perror "Error deleting $TARGET_BUILD_DIR" fi set -- $(ls ${TARGET_DIR}) fi cd ${TARGET_DIR} while (( "$#" )); do clean_module $(readlink -f $1) shift done cd - &> /dev/null } clean_module() { pinfo "Cleaning '$1'..." local MODULE_DIR=$1 if [ -e ${MODULE_DIR}/.built ]; then rm "${MODULE_DIR}/.built" || perror "Could not clear built flag" fi if [ -e ${MODULE_DIR}/.fetched_source ]; then rm "${MODULE_DIR}/.fetched_source" || perror "Could not clear fetched_source flag" fi if [ -d ${MODULE_DIR}/build ]; then rm -rf "${MODULE_DIR}/build" || perror "Could not delete build path" fi if [ -d ${MODULE_DIR}/src ]; then rm -rf "${MODULE_DIR}/src" || perror "Could not delete src path" fi if [ -e ${MODULE_DIR}/list_dpkg_output ]; then rm "${MODULE_DIR}/list_dpkg_output" || perror "Could not delete list_dpkg_output" fi if [ -e ${MODULE_DIR}/list_binaries_and_files ]; then rm "${MODULE_DIR}/list_binaries_and_files" || perror "Could not delete list_binaries_and_files" fi }