"Yann E. MORIN"  committed ea15433

Ah! I finally have a progress bar that doesn't stall the build!
- pipe size in Linux is only 8*512=4096 bytes
- pipe size is not setable
- when the feeding process spits out data faster than the eating
process can read it, then the feeding process stalls after 4KiB
of data sent to the pipe
- for us, the progress bar would spawn a sub-shell every line,
and the sub-shell would in turn spawn a 'date' command.
Which was sloooww as hell, and would cause some kind of a
starvation: the pipe was full most of the time, and the
feeding process was stalled all this time.

Now, we use internal variables and a little hack based onan offset
to determine the elapsed time. Much faster this way, but still

  • Participants
  • Parent commits 2e16b9f

Comments (0)

Files changed (3)

File config/

     default n
     depends on ! LOG_ALL
-      This option will print a "rotating bar" (/-\|) below the last log line
-      to show work is not stalled.
+      If you say 'y' here, you'll be able to see the elapsed time.
-      Available when not in DEBUG log level.
-      WARNING! Very CPU intensive! If you have spare CPU, then you can use it,
-      otherwise, refrain from using it.
+      As a bonus, you'll also get a rotating bar (/-\|) showing you
+      that the build is not stalled (the bar rotates 1/4 every 10 lines
+      of components build log).
+      Note that the elapsed time can stall for a little while if a
+      component has long commands, as the elapsed time is only updated
+      each line.
 config LOG_TO_FILE

File scripts/

 CT_STAR_DATE=`CT_DoDate +%s%N`
 CT_STAR_DATE_HUMAN=`CT_DoDate +%Y%m%d.%H%M%S`
-# Log to a temporary file until we have built our environment
+# Log policy:
+#  - what goes to the log file goes to fd #1 (stdout)
+#  - what goes to the screen goes to fd #6
+exec 6>&1
+exec >>"${tmp_log_file}"
 # Are we configured? We'll need that later...
 CT_TestOrAbort "Configuration file not found. Please create one." -f "${CT_TOP_DIR}/.config"
 # It's quite understandable that the log file will be installed in the install
 # directory, so we must first ensure it exists and is writeable (above) before
 # we can log there
+exec >/dev/null
 case "${CT_LOG_TO_FILE},${CT_LOG_FILE}" in
-    ,*)   rm -f "${CT_ACTUAL_LOG_FILE}"
-          CT_ACTUAL_LOG_FILE=/dev/null
+    ,*)   rm -f "${tmp_log_file}"
     y,/*) mkdir -p "`dirname \"${CT_LOG_FILE}\"`"
-          mv "${CT_ACTUAL_LOG_FILE}" "${CT_LOG_FILE}"
+          mv "${tmp_log_file}" "${CT_LOG_FILE}"
+          exec >>"${CT_LOG_FILE}"
     y,*)  mkdir -p "`pwd`/`dirname \"${CT_LOG_FILE}\"`"
-          mv "${CT_ACTUAL_LOG_FILE}" "`pwd`/${CT_LOG_FILE}"
-          CT_ACTUAL_LOG_FILE="`pwd`/${CT_LOG_FILE}"
+          mv "${tmp_log_file}" "`pwd`/${CT_LOG_FILE}"
+          exec >>"${CT_LOG_FILE}"
 # Determine build system if not set by the user
-CT_Test "You did not specify the build system. Guessing." -z "${CT_BUILD}"
+CT_Test "You did not specify the build system. That's OK, I can guess..." -z "${CT_BUILD}"
 CT_BUILD="`${CT_TOP_DIR}/tools/config.sub \"${CT_BUILD:-\`${CT_TOP_DIR}/tools/config.guess\`}\"`"
 # Arrange paths depending on wether we use sys-root or not.

File scripts/functions

     for((depth=2; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
         CT_DoLog ERROR "      called from \"${BASH_SOURCE[${depth}]}\" at line # ${BASH_LINENO[${depth}-1]} in function \"${FUNCNAME[${depth}]}\""
-    CT_DoLog ERROR "Look at \"${CT_ACTUAL_LOG_FILE}\" for more info on this error."
+    [ "${CT_LOG_TO_FILE}" = "y" ] && CT_DoLog ERROR "Look at \"${CT_LOG_FILE}\" for more info on this error."
     CT_DoEnd ERROR
     exit $ret
         cat -
         echo "${1}"
-    fi |( IFS="\n" # We want the full lines, even leading spaces
+    fi |( offset=$((`CT_DoDate +%s`+(CT_STAR_DATE/(1000*1000*1000))))
+          IFS="\n" # We want the full lines, even leading spaces
           while read line; do
               case "${CT_LOG_SEE_TOOLS_WARN},${line}" in
                 y,*"warning:"*)         cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
+                y,*"WARNING:"*)         cur_L=WARN; cur_l=${CT_LOG_LEVEL_WARN};;
                 *"error:"*)             cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
                 *"make["?*"]:"*"Stop.") cur_L=ERROR; cur_l=${CT_LOG_LEVEL_ERROR};;
                 *)                      cur_L="${LEVEL}"; cur_l="${level}";;
               l="`printf \"[%-5s]%*s%s%s\" \"${cur_L}\" \"${indent}\" \" \" \"${line}\"`"
               # There will always be a log file, be it /dev/null
-              echo -e "${l}" >>"${CT_ACTUAL_LOG_FILE}"
+              echo -e "${l}"
               if [ ${cur_l} -le ${max_level} ]; then
-                  echo -e "\r${l}"
+                  echo -e "\r${l}" >&6
               if [ "${CT_LOG_PROGRESS_BAR}" = "y" ]; then
-                  str=`CT_DoDate +%s`
-                  elapsed=$((str-(CT_STAR_DATE/(1000*1000*1000))))
+                  elapsed=$((SECONDS+OFFSET))
                   [ ${CT_PROG_BAR_CPT} -eq 0  ] && bar="/"
                   [ ${CT_PROG_BAR_CPT} -eq 10 ] && bar="-"
                   [ ${CT_PROG_BAR_CPT} -eq 20 ] && bar="\\"
                   [ ${CT_PROG_BAR_CPT} -eq 30 ] && bar="|"
-                  printf "\r[%02d:%02d] %s " $((elapsed/60)) $((elapsed%60)) "${bar}"
+                  printf "\r[%02d:%02d] %s " $((elapsed/60)) $((elapsed%60)) "${bar}" >&6