changeset 897:850da666acc6

Redo command recording: no longer RECORD_COMMMANDS config entry, now sources/more/record-commands.sh run to set up the wrapper (either before or after host-tools.sh). General cleanup and simplification of code this interacted with, plus clean up bit rot in the reporting.
author Rob Landley <rob@landley.net>
date Sat, 21 Nov 2009 04:27:58 -0600
parents edc150001472
children db0f536aee7c
files config host-tools.sh sources/functions.sh sources/include.sh sources/more/record-commands.sh sources/more/report-recorded-commands.sh sources/more/report_recorded_commands.sh sources/toys/wrappy.c
diffstat 8 files changed, 119 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- a/config	Fri Nov 20 23:42:07 2009 -0600
+++ b/config	Sat Nov 21 04:27:58 2009 -0600
@@ -22,11 +22,6 @@
 
 # export ROOT_NODIRS=1
 
-# If this is set, the build records the command lines run by each build into
-# log files in the build directory, ala "build/cmdlines.$PACKAGENAME"
-
-# export RECORD_COMMANDS=1
-
 # By default, only busybox is built statically (doing so provides a 20%
 # performance boost to autoconf under qemu).
 
--- a/host-tools.sh	Fri Nov 20 23:42:07 2009 -0600
+++ b/host-tools.sh	Sat Nov 21 04:27:58 2009 -0600
@@ -29,8 +29,6 @@
 echo -e "$HOST_COLOR"
 echo "=== Building $STAGE_NAME"
 
-export LC_ALL=C
-
 STAGE_DIR="${HOSTTOOLS}"
 
 # Blank $WORK but accept $STAGE_DIR if it exists.  Re-running this script
@@ -44,13 +42,13 @@
 
 if [ ! -z "$RECORD_COMMANDS" ]
 then
-  if [ ! -f "$BUILD/wrapdir/wrappy" ]
+  if [ ! -f "$WRAPDIR/wrappy" ]
   then
     echo setup wrapdir
 
     # Build the wrapper and install it into build/wrapdir/wrappy
-    blank_tempdir "$BUILD/wrapdir"
-    $CC -Os "$SOURCES/toys/wrappy.c" -o "$BUILD/wrapdir/wrappy"  || dienow
+    blank_tempdir "$WRAPDIR"
+    $CC -Os "$SOURCES/toys/wrappy.c" -o "$WRAPDIR/wrappy"  || dienow
 
     # Loop through each $PATH element and create a symlink to the wrapper with
     # that name.
@@ -59,14 +57,14 @@
     do
       for j in $(ls $i)
       do
-        [ -f "$BUILD/wrapdir/$j" ] || ln -s wrappy "$BUILD/wrapdir/$j"
+        [ -f "$WRAPDIR/$j" ] || ln -s wrappy "$WRAPDIR/$j"
       done
     done
 
     # Adjust things to use wrapper directory
 
     export WRAPPY_REALPATH="$PATH"
-    PATH="$BUILD/wrapdir"
+    PATH="$WRAPDIR"
   fi
 
 # If we're not recording the host command lines, then populate a directory
--- a/sources/functions.sh	Fri Nov 20 23:42:07 2009 -0600
+++ b/sources/functions.sh	Sat Nov 21 04:27:58 2009 -0600
@@ -419,7 +419,7 @@
 
 function setupfor()
 {
-  export WRAPPY_LOGPATH="$WRAPPY_LOGDIR/cmdlines.${STAGE_NAME}.setupfor"
+  export WRAPPY_LOGPATH="$BUILD/logs/cmdlines.${ARCH_NAME}.${STAGE_NAME}.setupfor"
 
   # Figure out whether we're using an unstable package.
 
@@ -466,7 +466,7 @@
   else
     mkdir -p "$2" && cd "$2" || dienow
   fi
-  export WRAPPY_LOGPATH="$WRAPPY_LOGDIR/cmdlines.${STAGE_NAME}.$1"
+  export WRAPPY_LOGPATH="$BUILD/logs/cmdlines.${ARCH_NAME}.${STAGE_NAME}.$1"
 
   # Change window title bar to package now
   set_titlebar "$ARCH_NAME $STAGE_NAME $PACKAGE"
--- a/sources/include.sh	Fri Nov 20 23:42:07 2009 -0600
+++ b/sources/include.sh	Sat Nov 21 04:27:58 2009 -0600
@@ -3,17 +3,26 @@
 # Set up all the environment variables and functions for a build stage.
 # This file is sourced, not run.
 
-umask 022
-
-# Tell bash not to cache the $PATH because we modify it.  Without this, bash
-# won't find new executables added after startup.
-set +h
-
-# Include two other files:
+# Include config and sources/functions.sh
 
 [ -e config ] && source config
+
 source sources/functions.sh
 
+# Where are our working directories?
+
+TOP=`pwd`
+export SOURCES="$TOP/sources"
+export SRCDIR="$TOP/packages"
+export BUILD="$TOP/build"
+export HOSTTOOLS="$BUILD/host"
+export WRAPDIR="$BUILD/wrapdir"
+
+# Set a default non-arch
+
+export WORK="${BUILD}/host-temp"
+export ARCH_NAME=host
+
 # What host compiler should we use?
 
 [ -z "$CC" ] && export CC=cc
@@ -26,52 +35,32 @@
   [ "$CPUS" -lt 1 ] && CPUS=1
 fi
 
-# Where are our working directories?
-
-TOP=`pwd`
-export SOURCES="${TOP}/sources"
-export SRCDIR="${TOP}/packages"
-export BUILD="${TOP}/build"
-export HOSTTOOLS="${BUILD}/host"
-
-# Set a default non-arch
-
-ARCH_NAME=host
-export WORK="${BUILD}/host-temp"
-
-# Retain old $PATH in case we re-run host-tools.sh with different options.
-
-export OLDPATH="$PATH"
+[ -z "$STAGE_NAME" ] && STAGE_NAME=`echo $0 | sed 's@.*/\(.*\)\.sh@\1@'`
+[ ! -z "$BUILD_VERBOSE" ] && VERBOSITY="V=1"
 
 # Adjust $PATH
 
-if [ "$PATH" != "$(hosttools_path)" ]
+export OLDPATH="$PATH"
+PATH="$(hosttools_path)"
+
+# If record-commands.sh set up a wrapper directory, adjust $PATH again.
+if [ -f "$WRAPDIR/wrappy" ]
 then
-  if [ -f "$HOSTTOOLS/busybox" ]
-  then
-    PATH="$(hosttools_path)"
-  else
-    PATH="$(hosttools_path):$PATH"
-  fi
+  export WRAPPY_LOGPATH="$BUILD/logs/cmdlines.$ARCH_NAME.early"
+  OLDPATH="$PATH:$OLDPATH"
+  PATH="$WRAPDIR"
+elif [ ! -f "$HOSTTOOLS/busybox" ]
+then
+  PATH="$PATH:$OLDPATH"
 fi
 
-# Setup for $RECORD_COMMANDS
-
-# WRAPPY_LOGPATH is set unconditionally in case host-tools.sh needs to
-# enable wrapping partway through its own build.  Extra environment variables
-# don't actually affect much, it's changing $PATH that changes behavior.
+# Create files with known permissions
+umask 022
 
-[ -z "$STAGE_NAME" ] && STAGE_NAME=`echo $0 | sed 's@.*/\(.*\)\.sh@\1@'`
-[ -z "$WRAPPY_LOGDIR" ] && WRAPPY_LOGDIR="$BUILD"
-export WRAPPY_LOGPATH="$WRAPPY_LOGDIR/cmdlines.${STAGE_NAME}.setupfor"
-if [ ! -z "$RECORD_COMMANDS" ] && [ -f "$BUILD/wrapdir/wrappy" ]
-then
-  export WRAPPY_REALPATH="$PATH"
-  PATH="$BUILD/wrapdir"
-fi
+# Tell bash not to cache the $PATH because we modify it.  (Without this, bash
+# won't find new executables added after startup.)
+set +h
 
-# This is an if instead of && so the exit code of include.sh is reliably 0
-if [ ! -z "$BUILD_VERBOSE" ]
-then
-  VERBOSITY="V=1"
-fi
+# Disable internationalization so sort and sed and such can cope with ASCII.
+
+export LC_ALL=C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/more/record-commands.sh	Sat Nov 21 04:27:58 2009 -0600
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+source sources/include.sh || exit 1
+
+# Build a wrapper that records each command line the build runs out of the
+# host's $PATH, so we know exactly what commands the build uses.
+
+# (Note: this misses things called via absolute paths, such as the #!/bin/bash
+# at the start of shell scripts.)
+
+echo "=== Setting up command recording wrapper"
+
+PATH="$OLDPATH"
+blank_tempdir "$WRAPDIR"
+blank_tempdir "$BUILD/logs"
+
+# Populate a directory of symlinks with every command in the $PATH.
+
+# For each each $PATH element, loop through each file in that directory,
+# and create a symlink to the wrapper with that name.  In the case of
+# duplicates, keep the first one.
+
+echo "$PATH" | sed 's/:/\n/g' | while read i
+do
+  ls -1 "$i" | while read j
+  do
+    ln -s wrappy "$WRAPDIR/$j" 2>/dev/null
+  done
+done
+
+# Build the wrapper
+$CC -Os "$SOURCES/toys/wrappy.c" -o "$WRAPDIR/wrappy"  || dienow
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sources/more/report-recorded-commands.sh	Sat Nov 21 04:27:58 2009 -0600
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+# List the commands used to build each architecture.
+
+# If given an argument it's the architecture to compare others against,
+# which shows just the extra commands used by those other architectures.
+
+# Mines the output created by build.sh after record-commands.sh.
+
+COMPARE="$1"
+
+# Output the list of commands used in a command log.
+
+function mine_commands()
+{
+  awk '{print $1}' build/logs/cmdlines.$1.* | sort -u
+}
+
+# Iterate through architectures
+
+for i in `ls -1 build/logs/cmdlines.* | sed 's@.*/cmdlines\.\([^.]*\).*@\1@' | sort -u`
+do
+  [ "$COMPARE" == "$i" ] && continue
+
+  # Start of new group, announce build stage we're looking at.
+  echo
+  echo -n Checking $i:
+
+  if [ -z "$COMPARE" ]
+  then
+    # Show all commands in first architecture.
+    echo $(mine_commands $i)
+  else
+    # Show commands that differ from first architecture (if any).
+    echo $(sort <(mine_commands $COMPARE) <(mine_commands $i) | uniq -u)
+  fi
+done
--- a/sources/more/report_recorded_commands.sh	Fri Nov 20 23:42:07 2009 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-#!/bin/bash
-
-# Quick script to mine the output of "RECORD_COMMANDS=1 ./forkbomb.sh --nofork"
-# for lists of commands used in each stage.
-
-# Output the list of commands used in a command log.
-
-function mine_commands()
-{
-  awk '{print $1}' $1 | sort -u
-}
-
-# Sort the log files into groups, then iterate through the result
-
-for i in `(for i in build/cmdlines-*/*; do echo $i; done) | sed 's@.*/cmdlines\.@@' | sort -u`
-do
-  # Start of new group, announce build stage we're looking at.
-  FIRST=""
-  echo
-  echo Checking $i
-
-  # Loop through this build stage in each architecture.
-  for j in build/cmdlines-*/cmdlines.$i
-  do
-    NAME="$(echo $j | sed 's@build/cmdlines-\([^/]*\)/.*@\1@')"
-
-    if [ -z "$FIRST" ]
-    then
-      # Show all commands in first architecture.
-      echo $NAME: $(mine_commands $j)
-      FIRST=$j
-    else
-      # Show commands that differ from first architecture (if any).
-      X=$(sort <(mine_commands $FIRST) <(mine_commands $j) | uniq -u)
-      [ ! -z "$X" ] && echo $NAME: $X
-    fi
-  done
-done
--- a/sources/toys/wrappy.c	Fri Nov 20 23:42:07 2009 -0600
+++ b/sources/toys/wrappy.c	Sat Nov 21 04:27:58 2009 -0600
@@ -4,7 +4,7 @@
 // environment variables.  Something like:
 //
 // export WRAPPY_LOGPATH=/path/to/wrappy.log
-// export WRAPPY_REALPATH="$PATH"
+// export OLDPATH="$PATH"
 //
 // WRAPPYDIR=/path/to/wrappy
 // cp wrappy $WRAPPYDIR
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <stdlib.h>
 
+// No, I'm not doing any bounds checking.  It's a debug wrapper.
 char blah[65536];
 
 int main(int argc, char *argv[], char *env[])
@@ -35,9 +36,9 @@
   // did $PATH make it there?  (Faily noisily if they are missing...)
 
   logpath = getenv("WRAPPY_LOGPATH");
-  realpath = getenv("WRAPPY_REALPATH");
+  realpath = getenv("OLDPATH");
   if (!logpath || !realpath) {
-    fprintf(stderr, "No WRAPPY_%s\n", logpath ? "REALPATH" : "LOGPATH");
+    fprintf(stderr, "No %s\n", logpath ? "OLDPATH" : "WRAPPY_LOGPATH");
     exit(1);
   }
 
@@ -48,7 +49,8 @@
   else p2++;
 
   // Write command line to a buffer.  (We need the whole command line in one
-  //buffer so we can do one write.)
+  // buffer so we can do a single atomic write, so commands don't get
+  // interleaved via make -j.)
 
   p=blah + sprintf(blah, "%s ",p2);
   for (i=1; i<argc && (p-blah)<sizeof(blah); i++) {
@@ -74,11 +76,6 @@
   write(fd, blah, p-blah);
   close(fd);
 
-  // Touch the file that got used.
-
-  // sprintf(blah, ROOTPATH "/used/%s", p2);
-  // close(open(blah, O_WRONLY|O_CREAT, 0777));
-
   // Hand off control to the real executable
 
   for (p = p3 = realpath; ; p3++) {