about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-10-06 15:40:56 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-10-06 15:40:56 -0700
commita232af2fafd9ad974ebc6cfcb2cd5a5883f0bd4a (patch)
tree8dd0390b7fb148fcdce2b724aa7f1d5abdd13dc6
parent6d6c37feeb72c7ab13276cec7df326f7d8cd1712 (diff)
downloadmu-a232af2fafd9ad974ebc6cfcb2cd5a5883f0bd4a.tar.gz
3447 - drop dependence on GNU make
A generic build system is overkill for such a small project, and it was
adding complexity on OpenBSD which doesn't come with GNU make by
default.

In the process we also eliminate our reliance on bash and perl, at least
for the core build script.
-rw-r--r--Readme.md8
-rwxr-xr-xbuild117
-rwxr-xr-xclean7
-rw-r--r--cleave/makefile7
-rw-r--r--makefile85
-rwxr-xr-xmu7
6 files changed, 129 insertions, 102 deletions
diff --git a/Readme.md b/Readme.md
index c6d6ed81..e9c170f3 100644
--- a/Readme.md
+++ b/Readme.md
@@ -84,10 +84,10 @@ operations (albeit at the cost of some runtime checks).
 *Taking Mu for a spin*
 
 Mu is currently implemented in C++ and requires a Unix-like environment. It's
-been tested on Ubuntu and Mac OS X, on x86, x86\_64 and ARMv7 with recent
-versions of GCC and Clang. Since it uses no recent language features and has
-no exotic dependencies, it should work with most reasonable versions,
-compilers or processors (though you do need GNU make or `gmake`).
+been tested on Ubuntu, Mac OS X and OpenBSD; on x86, x86\_64 and ARMv7; and on
+recent versions of GCC and Clang. Since it uses no bleeding-edge language
+features and has no exotic dependencies, it should work with most reasonable
+versions, compilers or processors.
 
 [![Build Status](https://api.travis-ci.org/akkartik/mu.svg)](https://travis-ci.org/akkartik/mu)
 
diff --git a/build b/build
new file mode 100755
index 00000000..86f9fa5f
--- /dev/null
+++ b/build
@@ -0,0 +1,117 @@
+#!/bin/sh
+set -e  # stop immediately on error
+
+# [0-9]*.cc -> mu.cc -> .build/*.cc -> .build/*.o -> .build/mu_bin
+# (layers)   |        |              |             |
+#          tangle  cleave          $CXX          $CXX
+
+test $CXX || export CXX=c++ 
+test $CC || export CC=cc
+test $CFLAGS || export CFLAGS="-g -O3"
+export CFLAGS="$CFLAGS -Wall -Wextra -ftrapv -fno-strict-aliasing"
+
+# return 1 if $1 is older than _any_ of the remaining args
+older_than() {
+  target=$1
+  shift
+  if [ ! -e $target ]
+  then 
+#?     echo "$target doesn't exist"
+    echo "updating $target" >&2
+    return 1
+  fi
+  for f in $*
+  do
+    if [ $f -nt $target ]
+    then
+      echo "updating $target" >&2
+      return 1
+    fi
+  done
+  return 0
+}
+
+noisy_cd() {
+  cd $1
+  echo "-- `pwd`" >&2
+}
+
+older_than enumerate/enumerate enumerate/enumerate.cc || {
+  $CXX $CFLAGS enumerate/enumerate.cc -o enumerate/enumerate
+}
+
+noisy_cd tangle
+  older_than type_list [0-9]*.cc || {
+    grep -h "^struct .* {" [0-9]*.cc |sed 's/\(struct *[^ ]*\).*/\1;/' > type_list
+    grep -h "^typedef " [0-9]*.cc >> type_list
+  }
+  older_than function_list [0-9]*.cc || {
+    grep -h "^[^ #].*) {" [0-9]*.cc |sed 's/ {.*/;/' > function_list
+  }
+  older_than file_list [0-9]*.cc || {
+    ls [0-9]*.cc |grep -v "\.test\.cc$" |sed 's/.*/#include "&"/' > file_list
+  }
+  older_than test_file_list [0-9]*.test.cc || {
+    ls [0-9]*.test.cc |sed 's/.*/#include "&"/' > test_file_list
+  }
+  older_than test_list [0-9]*.cc || {
+    grep -h "^[[:space:]]*void test_" [0-9]*.cc |sed 's/^\s*void \(.*\)() {$/\1,/' > test_list
+  }
+  older_than tangle boot.cc *_list || {
+    $CXX $CFLAGS boot.cc -o tangle
+  }
+noisy_cd ..
+
+LAYERS=$(./enumerate/enumerate --until zzz |grep -v '.mu$')
+older_than mu.cc $LAYERS enumerate/enumerate tangle/tangle || {
+  ./tangle/tangle $LAYERS > mu.cc
+}
+older_than function_list mu.cc || {
+  grep -h "^[^[:space:]#].*) {$" mu.cc |grep -v ":.*(" |sed 's/ {.*/;/' > function_list
+}
+older_than test_list mu.cc || {
+  grep -h "^\s*void test_" mu.cc |sed 's/^\s*void \(.*\)() {.*/\1,/' > test_list
+}
+
+older_than cleave/cleave cleave/cleave.cc || {
+  $CXX -O3 -Wall -Wextra -fno-strict-aliasing cleave/cleave.cc -o cleave/cleave
+  rm -rf .build
+}
+
+older_than mu_bin mu.cc *_list cleave/cleave || {
+  mkdir -p .build
+  cp function_list test_list .build
+  mkdir -p .build/termbox
+  cp termbox/termbox.h .build/termbox
+  ./cleave/cleave mu.cc .build
+  noisy_cd .build
+    older_than global_declarations_list global_definitions_list || {
+      grep ';' global_definitions_list |sed 's/[=(].*/;/' |sed 's/^[^\/# ]/extern &/' |sed 's/^extern extern /extern /' > global_declarations_list
+    }
+    for f in mu_*.cc
+    do
+      older_than `echo $f |sed 's/\.cc$/.o/'` $f || {
+        $CXX $CFLAGS -c $f
+      }
+    done
+  noisy_cd ../termbox
+    older_than utf8.o utf8.c || {
+      $CC $CFLAGS -c utf8.c
+    }
+    older_than termbox.o termbox.c termbox.h input.inl output.inl bytebuffer.inl || {
+      $CC $CFLAGS -c termbox.c
+    }
+    older_than libtermbox.a *.o || {
+      ar rcs libtermbox.a *.o
+    }
+  noisy_cd ..
+  $CXX .build/*.o termbox/libtermbox.a -o .build/mu_bin
+  cp .build/mu_bin .
+}
+
+## [0-9]*.mu -> core.mu
+
+MU_LAYERS=$(./enumerate/enumerate --until zzz |grep '.mu$')
+older_than core.mu $MU_LAYERS || {
+  cat $MU_LAYERS > core.mu
+}
diff --git a/clean b/clean
new file mode 100755
index 00000000..1cd632d0
--- /dev/null
+++ b/clean
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -v
+rm -rf mu.cc core.mu mu_bin* *_list .build
+rm -rf enumerate/enumerate tangle/tangle tangle/*_list cleave/cleave
+rm -rf termbox/*.o termbox/libtermbox.a
+rm -rf *.dSYM */*.dSYM
diff --git a/cleave/makefile b/cleave/makefile
deleted file mode 100644
index 33665b5c..00000000
--- a/cleave/makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-cleave: cleave.cc makefile
-	c++ -O3 -Wall -Wextra -fno-strict-aliasing cleave.cc -o cleave
-
-.PHONY: clean
-
-clean:
-	-rm cleave
diff --git a/makefile b/makefile
deleted file mode 100644
index 1f5599d7..00000000
--- a/makefile
+++ /dev/null
@@ -1,85 +0,0 @@
-# [0-9]*.cc -> mu.cc -> .build/*.cc -> .build/*.o -> .build/mu_bin
-# (layers)   |        |              |             |
-#          tangle  cleave          $CXX          $CXX
-#
-# [0-9]*.mu -> core.mu
-
-all: mu_bin core.mu
-
-# beware: if you introduce or delete functions the makefile isn't smart enough
-# to recompute dependencies. You have to manually run 'make redo' to recreate
-# the .build/ directory from scratch.
-redo: clean1 all
-
-CXX ?= c++
-CXXFLAGS ?= -g -O3
-CXXFLAGS := ${CXXFLAGS} -Wall -Wextra -ftrapv -fno-strict-aliasing
-
-core.mu: [0-9]*.mu mu.cc makefile
-	cat $$(./enumerate/enumerate --until zzz |grep '.mu$$') > core.mu
-
-mu_bin: mu.cc makefile function_list test_list cleave/cleave
-	@mkdir -p .build
-	@cp function_list test_list .build
-	@mkdir -p .build/termbox
-	@cp termbox/termbox.h .build/termbox
-	@# split mu.cc into separate compilation units under .build/ to speed up recompiles
-	./cleave/cleave mu.cc .build
-	@# recursive (potentially parallel) make to pick up BUILD_SRC after cleave
-	@${MAKE} .build/mu_bin
-	cp .build/mu_bin .
-
-BUILD_SRC=$(wildcard .build/*.cc)
-.build/mu_bin: $(BUILD_SRC:.cc=.o) termbox/libtermbox.a
-	${CXX} ${LDFLAGS} .build/*.o termbox/libtermbox.a -o .build/mu_bin
-
-.build/%.o: .build/%.cc .build/header .build/global_declarations_list
-	@# explicitly state default rule since we added dependencies
-	${CXX} ${CXXFLAGS} -c $< -o $@
-
-# To see what the program looks like after all layers have been applied, read
-# mu.cc
-mu.cc: [0-9]*.cc enumerate/enumerate tangle/tangle
-	./tangle/tangle $$(./enumerate/enumerate --until zzz |grep -v '.mu$$') > mu.cc
-
-enumerate/enumerate: enumerate/*.cc
-	cd enumerate && ${MAKE}
-
-tangle/tangle: tangle/*.cc
-	cd tangle && ${MAKE} && ./tangle test
-
-cleave/cleave: cleave/*.cc
-	cd cleave && ${MAKE}
-	rm -rf .build
-
-termbox/libtermbox.a: termbox/*.c termbox/*.h termbox/*.inl
-	cd termbox && ${MAKE}
-
-# auto-generated files; by convention they end in '_list'.
-
-# auto-generated list of function declarations, so I can define them in any order
-function_list: mu.cc
-	@# functions start out unindented, have all args on the same line, and end in ') {'
-	@#                                      ignore methods
-	@grep -h "^[^[:space:]#].*) {$$" mu.cc |grep -v ":.*(" |perl -pwe 's/ \{.*/;/' > function_list
-
-# auto-generated list of tests to run
-test_list: mu.cc
-	@grep -h "^\s*void test_" mu.cc |perl -pwe 's/^\s*void (.*)\(\) \{.*/$$1,/' > test_list
-
-# auto-generated list of extern declarations to global variables
-# for separate compilation
-.build/global_declarations_list: .build/global_definitions_list
-	@grep ';' .build/global_definitions_list |perl -pwe 's/[=(].*/;/' |perl -pwe 's/^[^\/# ]/extern $$&/' |perl -pwe 's/^extern extern /extern /' > .build/global_declarations_list
-
-.PHONY: all redo clean clena
-
-clena: clean
-clean: clean1
-	cd enumerate && ${MAKE} clean
-	cd tangle && ${MAKE} clean
-	cd cleave && ${MAKE} clean
-	cd termbox && ${MAKE} clean
-
-clean1:
-	rm -rf mu.cc core.mu mu_bin* *_list .build
diff --git a/mu b/mu
index ad3222d9..dabc77d6 100755
--- a/mu
+++ b/mu
@@ -2,12 +2,7 @@
 #
 # Compile mu if necessary before running it.
 
-# I try to keep this script working even on a minimal OpenBSD without bash.
-# In such situations you might sometimes need GNU make.
-which gmake >/dev/null 2>&1 && export MAKE=gmake || export MAKE=make
-
-# show make output only if something needs doing
-$MAKE -q || $MAKE >&2 || exit 1
+./build
 
 ./mu_bin $FLAGS "$@"