Major rewrite of the build system/Makefile reorganized.
authorW. Trevor King <wking@drexel.edu>
Mon, 1 Sep 2008 03:25:36 +0000 (23:25 -0400)
committerW. Trevor King <wking@drexel.edu>
Mon, 1 Sep 2008 03:25:36 +0000 (23:25 -0400)
Almost everything got pushed out into subdirectories of the base
`sawsim/' dir.  All the versioned source got sent to `src'.
Processing `sawsim.nw' generates C code, which is placed in `build'
along with the odd bits of code not in the noweb file.  Finally, we
compile the code in `build' into executibles placed in `bin' and
documents placed in `doc'.  TODO: add appropriate commentary to
`sawsim.nw'.

Standardizing the Makefile also cut down on the module-specific code
needed in the makefile, which should encourage better modulization.

I hadn't been able to compile the checks in a while with the old
system, and now they compile, but they don't pass the checks.  Well,
that's what checks are for ;), although in this case I suspect it's
just that I've been ignoring the checks for a while and the code has
moved on, leaving incompatible checks.  Fixing the checks is the next
order of business, so we can implement fast, pre-commit sanity-checks.

README
src/interp.c [moved from interp.c with 100% similarity]
src/interp.h [moved from interp.h with 100% similarity]
src/sawsim.bib [moved from sawsim.bib with 100% similarity]
src/sawsim.nw [moved from sawsim.nw with 95% similarity]
src/tavl.c [moved from tavl.c with 100% similarity]
src/tavl.h [moved from tavl.h with 100% similarity]

diff --git a/README b/README
index 32e9fb15d009f839e967f797b852c3f6fa832df0..cc953111d6297f8951fa4cf6724af6266e4ed769 100644 (file)
--- a/README
+++ b/README
@@ -3,7 +3,7 @@ Warning: also my noweb-training program.
 (noweb, or the transitional nowebm, in Debian-based distributions)
 
 Extract Makefile and compile with:
- $ notangle -Rmakefile sawsim.nw | sed 's/        /\t/' > Makefile
+ $ notangle -Rmakefile src/sawsim.nw | sed 's/        /\t/' > Makefile
  $ make
 Run the unit tests with
  $ make check
similarity index 100%
rename from interp.c
rename to src/interp.c
similarity index 100%
rename from interp.h
rename to src/interp.h
similarity index 100%
rename from sawsim.bib
rename to src/sawsim.bib
similarity index 95%
rename from sawsim.nw
rename to src/sawsim.nw
index 2fce7f824497292dac2f89b7ccaf0ccfb2ee7d11..d4d5a9bc524e5a40b0eaded2fcb0c70f3976ba6a 100644 (file)
--- a/sawsim.nw
@@ -1,7 +1,7 @@
 %%%%%%%%%%%%%%%%%%%%%%%%% Start LaTeX boilerplate %%%%%%%%%%%%%%%%%%%%%%%%%%%
 % we have our own preamble, 
 % use `noweave -delay` to not print noweb's automatic one
-  % -*- mode: Noweb; noweb-code-mode: c-mode -*-
+% -*- mode: Noweb; noweb-code-mode: c-mode -*-
 \documentclass[letterpaper, 11pt]{article}
 \usepackage{noweb}
 \pagestyle{noweb}
@@ -1408,16 +1408,9 @@ We implement this parsing in [[parse.c]], define the interface in [[parse.h]], a
 @ 
 
 <<parse module makefile lines>>=
-parse.c : sawsim.nw
-       notangle -Rparse.c $^ > $@
-parse.h : sawsim.nw
-       notangle -Rparse.h $^ > $@
-check_parse.c : sawsim.nw
-       notangle -Rcheck-parse.c $^ > $@
-check_parse : check_parse.c parse.c parse.h
-       gcc -g -o $@ $< parse.c -lcheck
-clean_parse : 
-       rm -f parse.c parse.h check_parse.c check_parse
+NW_SAWSIM_MODS += parse
+CHECK_BINS += check_parse
+check_parse_MODS = 
 @ 
 
 <<parse definitions>>=
@@ -1832,16 +1825,9 @@ the implementation in [[tension_balance.c]], and the unit testing in
 @ 
 
 <<tension balance module makefile lines>>=
-tension_balance.c : sawsim.nw
-       notangle -Rtension-balance.c $^ > $@
-tension_balance.h : sawsim.nw
-       notangle -Rtension-balance.h $^ > $@
-check_tension_balance.c : sawsim.nw
-       notangle -Rcheck-tension-balance.c $^ > $@
-check_tension_balance : check_tension_balance.c global.h tension_balance.c tension_balance.h
-       gcc -g -o $@ $< tension_balance.c -lcheck
-clean_tension : 
-       rm -f tension_balance.c tension_balance.h check_tension_balance.c check_tension_balance
+NW_SAWSIM_MODS += tension_balance
+CHECK_BINS += check_tension_balance
+check_tension_balance_MODS = 
 @ 
 
 The entire force balancing problem reduces to a solving two nested
@@ -2234,16 +2220,9 @@ The interface is defined in [[list.h]], the implementation in [[list.c]], and th
 @ 
 
 <<list module makefile lines>>=
-list.c : sawsim.nw
-       notangle -Rlist.c $^ > $@
-list.h : sawsim.nw
-       notangle -Rlist.h $^ > $@
-check_list.c : sawsim.nw
-       notangle -Rcheck-list.c $^ > $@
-check_list : check_list.c global.h list.c list.h
-       gcc -g -o $@ $< list.c -lcheck
-clean_list : 
-       rm -f list.c list.h check_list.c check_list
+NW_SAWSIM_MODS += list
+CHECK_BINS += check_list
+check_list_MODS = 
 @ 
 
 <<list definitions>>=
@@ -2581,7 +2560,9 @@ Here we check to make sure the various functions work as expected, using \citeta
 
 <<list check includes>>=
 #include <stdlib.h> /* EXIT_SUCCESS and EXIT_FAILURE */
+#include <stdio.h>  /* FILE                          */
 <<check includes>>
+#include "global.h"
 #include "list.h"
 @ 
 
@@ -2666,16 +2647,9 @@ The interface is defined in [[string_eval.h]], the implementation in [[string_ev
 @ 
 
 <<string eval module makefile lines>>=
-string_eval.c : sawsim.nw
-       notangle -Rstring-eval.c $^ > $@
-string_eval.h : sawsim.nw
-       notangle -Rstring-eval.h $^ > $@
-check_string_eval.c : sawsim.nw
-       notangle -Rcheck-string-eval.c $^ > $@
-check_string_eval : check_string_eval.c string_eval.c string_eval.h
-       gcc -g -o $@ $< string_eval.c -lcheck -lgsl -lgslcblas -lm
-clean_string_eval :
-       rm -f string_eval.c string_eval.h check_string_eval.c check_string_eval
+NW_SAWSIM_MODS += string_eval
+CHECK_BINS += check_string_eval
+check_string_eval_MODS = 
 @ 
 
 For an introduction to POSIX process control, see\\
@@ -2991,16 +2965,9 @@ void free_accels();
 @ 
 
 <<accel k module makefile lines>>=
-accel_k.c : sawsim.nw
-       notangle -Raccel-k.c $^ > $@
-accel_k.h : sawsim.nw
-       notangle -Raccel-k.h $^ > $@
-check_accel_k.c : sawsim.nw
-       notangle -Rcheck-accel_k.c $^ > $@
-check_accel_k : check_accel_k.c global.h
-       gcc -g -o $@ $< accel_k.c -lcheck -lgsl -lgslcblas -lm
-clean_accel_k : 
-       rm -f accel_k.c accel_k.h check_accel_k.c check_accel_k
+NW_SAWSIM_MODS += accel_k
+#CHECK_BINS += check_accel_k
+check_accel_k_MODS =  
 @ 
 
 <<accel-k.c>>=
@@ -3100,26 +3067,21 @@ The interface is defined in [[tension_model.h]], the implementation in [[tension
 @ 
 
 <<tension model module makefile lines>>=
-tension_model.c : sawsim.nw
-       notangle -Rtension-model.c $^ > $@
-tension_model.h : sawsim.nw
-       notangle -Rtension-model.h $^ > $@
-check_tension_model.c : sawsim.nw
-       notangle -Rcheck-tension-model.c $^ > $@
-check_tension_model : check_tension_model.c global.h tension_model.c tension_model.h
-       gcc -g -o $@ $< tension_model.c -lcheck -lgsl -lgslcblas -lm
-clean_tension_model : clean_tension_model_utils
-       rm -f tension_model.c tension_model.h check_tension_model.c check_tension_model
-tension_model_utils.c : sawsim.nw
-       notangle -Rtension-model-utils.c $^ > $@
-tension_model_utils : tension_model_utils.c global.h tension_model.c tension_model.h parse.c parse.h \
-               list.c list.h tension_balance.c tension_balance.h
-       gcc -g -o $@ $< tension_model.c parse.c list.c tension_balance.c -lgsl -lgslcblas -lm
-tension_model_utils_static : tension_model_utils.c global.h tension_model.c tension_model.h parse.c parse.h \
-               list.c list.h tension_balance.c tension_balance.h
-       gcc -g -static -o $@ $< tension_model.c parse.c list.c tension_balance.c -lgsl -lgslcblas -lm
+NW_SAWSIM_MODS += tension_model
+#CHECK_BINS += check_tension_model
+check_tension_model_MODS = 
+@ 
+<<tension model utils makefile lines>>=
+TENSION_MODEL_MODS = tension_model parse list tension_balance
+TENSION_MODEL_SRC = $(BUILD_DIR)/tension_model_utils.c $(BUILD_DIR)/global.h \
+       $(TENSION_MODEL_MODS:%=$(BUILD_DIR)/%.c) \
+       $(TENSION_MODEL_MODS:%=$(BUILD_DIR)/%.h)
+$(BUILD_DIR)/tension_model_utils.c : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+       notangle -Rtension-model-utils.c $< > $@
+$(BIN_DIR)/tension_model_utils : $(TENSION_MODEL_SRC) $(BIN_DIR)
+       gcc -g -o $@ $< $(TENSION_MODEL_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
 clean_tension_model_utils :
-       rm -f tension_model_utils.c tension_model_utils
+       rm -f $(BUILD_DIR)/tension_model_utils.c $(BIN_DIR)/tension_model_utils
 @ 
 
 \subsection{Null}
@@ -3842,24 +3804,22 @@ which I don't like as much.
 @ 
 
 <<k model module makefile lines>>=
-k_model.c : sawsim.nw
-       notangle -Rk-model.c $^ > $@
-k_model.h : sawsim.nw
-       notangle -Rk-model.h $^ > $@
-check_k_model.c : sawsim.nw
-       notangle -Rcheck-k-model.c $^ > $@
-check_k_model : check_k_model.c global.h k_model.c k_model.h
-       gcc -g -o $@ $< k_model.c -lcheck -lgsl -lgslcblas -lm
-clean_k_model : clean_k_model_utils
-       rm -f k_model.c k_model.h check_k_model.c check_k_model
-k_model_utils.c : sawsim.nw
-       notangle -Rk-model-utils.c $^ > $@
-k_model_utils : k_model_utils.c global.h k_model.c k_model.h parse.c parse.h string_eval.c string_eval.h
-       gcc -g -o $@ $< k_model.c parse.c string_eval.c -lgsl -lgslcblas -lm
-k_model_utils_static : k_model_utils.c global.h k_model.c k_model.h parse.c parse.h string_eval.c string_eval.h
-       gcc -g -static -o $@ $< k_model.c parse.c string_eval.c -lgsl -lgslcblas -lm
+NW_SAWSIM_MODS += k_model
+CHECK_BINS += check_k_model
+check_k_model_MODS = parse string_eval
+@ 
+[[check_k_model]] also depends on the parse module.
+
+<<k model utils makefile lines>>=
+K_MODEL_MODS = k_model parse string_eval
+K_MODEL_SRC = $(BUILD_DIR)/k_model_utils.c $(BUILD_DIR)/global.h \
+       $(K_MODEL_MODS:%=$(BUILD_DIR)/%.c) $(K_MODEL_MODS:%=$(BUILD_DIR)/%.h)
+$(BUILD_DIR)/k_model_utils.c : $(SRC_DIR)/sawsim.nw $(BUILD)
+       notangle -Rk-model-utils.c $< > $@
+$(BIN_DIR)/k_model_utils : $(K_MODEL_SRC) $(BIN_DIR)
+       gcc -g -o $@ $< $(K_MODEL_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
 clean_k_model_utils :
-       rm -f k_model_utils.c k_model_utils
+       rm -f $(BUILD_DIR)/k_model_utils.c $(BIN_DIR)/k_model_utils
 @ 
 
 \subsection{Null}
@@ -4682,8 +4642,8 @@ START_TEST(test_const_k_create_destroy)
   int i;
   for( i=0; i < sizeof(knot)/sizeof(char *); i++) {
     params[0] = knot[i];
-    p = string_create_const_param_t(params); 
-    destroy_const_param_t(p);
+    p = string_create_const_k_param_t(params); 
+    destroy_const_k_param_t(p);
   }
 }
 END_TEST
@@ -4700,13 +4660,13 @@ START_TEST(test_const_k_over_range)
   env.T = T;
   for( i=0; i < sizeof(knot)/sizeof(char *); i++) {
     params[0] = knot[i];
-    p = string_create_const_param_t(params); 
-    for ( F=Fm, F<FM, F+=dF ) {
+    p = string_create_const_k_param_t(params); 
+    for ( F=Fm; F<FM; F+=dF ) {
       fail_unless(const_k(F, &env, p)==atof(knot[i]),
-          "const_k(%g, %g, &{%s,%s}) = %g != %s",
-          F, T, knot[i], dx, const_k(F, &env, p), knot[i]);
+          "const_k(%g, %g, &{%s}) = %g != %s",
+          F, T, knot[i], const_k(F, &env, p), knot[i]);
     }
-    destroy_const_param_t(p);
+    destroy_const_k_param_t(p);
   }
 }
 END_TEST
@@ -5052,16 +5012,20 @@ void get_options(int argc, char **argv, environment_t *env,
 The comment blocks in this [[noweb]] file are in \LaTeX\ with \BibTeX\ citations.
 The comment blocks are extracted (with nicely formatted code blocks), using
 <<latex makefile lines>>=
-sawsim.tex : sawsim.nw
-       noweave -latex -index -delay $^ > $@
+$(BUILD_DIR)/sawsim.tex : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+       noweave -latex -index -delay $< > $@
+$(BUILD_DIR)/sawsim.bib : $(SRC_DIR)/sawsim.bib $(BUILD_DIR)
+       cp -f $< $@
 @ 
 and compiled using
 <<latex makefile lines>>=
-sawsim.pdf : sawsim.tex sawsim.bib
-       pdflatex $^
-       bibtex sawsim
-       pdflatex $^
-       pdflatex $^
+$(DOC_DIR)/sawsim.pdf : $(BUILD_DIR)/sawsim.tex $(BUILD_DIR)/sawsim.bib \
+               $(DOC_DIR)
+       $(SHELL) -e -c "cd $(BUILD_DIR) && pdflatex sawsim"
+       $(SHELL) -e -c "cd $(BUILD_DIR) && bibtex sawsim"
+       $(SHELL) -e -c "cd $(BUILD_DIR) && pdflatex sawsim"
+       $(SHELL) -e -c "cd $(BUILD_DIR) && pdflatex sawsim"
+       mv $(BUILD_DIR)/sawsim.pdf $@
 @
 The first [[pdflatex]] pass reads through the \TeX\ source and extracts citation information,
 the \BibTeX\ pass looks through the \BibTeX\ databases for the cited works, and
@@ -5070,9 +5034,12 @@ the remaining two [[pdflatex]] passes insert the citations and finalize the vari
 [[bibtex]] and [[pdflatex]] produce quite a few intermediate files, so provide a means to clean them up.
 <<latex makefile lines>>=
 semi-clean_latex : 
-       rm -f sawsim.aux sawsim.bbl sawsim.blg sawsim.log sawsim.out sawsim.tex
+       rm -f $(BUILD_DIR)/sawsim.aux $(BUILD_DIR)/sawsim.bbl \
+               $(BUILD_DIR)/sawsim.blg $(BUILD_DIR)/sawsim.log \
+               $(BUILD_DIR)/sawsim.out $(BUILD_DIR)/sawsim.tex \
+               $(BUILD_DIR)/sawsim.bib
 clean_latex : semi-clean_latex
-       rm -f sawsim.pdf
+       rm -f $(DOC_DIR)/sawsim.pdf
 @ 
 
 \section{Makefile}
@@ -5089,50 +5056,23 @@ Besides the generated files, there is the utility target
 % [[dist]] for generating a distributable tar file.
 
 Extract the makefile with
-`[[notangle -Rmakefile sawsim.nw | sed 's/        /\t/' > Makefile]]'.
+`[[notangle -Rmakefile src/sawsim.nw | sed 's/        /\t/' > Makefile]]'.
 The sed is needed because notangle replaces tabs with eight spaces,
 but [[make]] needs tabs.
 <<makefile>>=
-all : sawsim sawsim.pdf Makefile tension_model_utils k_model_utils
-
-view : sawsim.pdf
-       xpdf $^ &
-profile : sawsim_profile
-       sawsim_profile -v1e-6 -Mhooke -A.05 -U1 -kkramers_integ -mnull -Mwlc -A0.39e-9,28e-9 -F8        
-       gprof sawsim_profile gmon.out > $@
-
-clean : clean_check clean_list clean_tension clean_tension_model clean_tension_model_utils clean_k_model clean_parse clean_string_eval clean_latex
-       rm -f sawsim.c sawsim sawsim_static sawsim_profile gmon.out global.h
-
-sawsim.c : sawsim.nw
-       notangle $^ > $@
-global.h : sawsim.nw
-       notangle -Rglobal.h $^ > $@
-sawsim : sawsim.c global.h list.c list.h tension_balance.c tension_balance.h \
-               tension_model.c tension_model.h k_model.c k_model.h parse.c parse.h string_eval.c string_eval.h \
-               accel_k.c accel_k.h
-       gcc -g -o $@ $< list.c tension_balance.c tension_model.c k_model.c parse.c string_eval.c accel_k.c interp.c tavl.c -lgsl -lgslcblas -lm
-sawsim_static : sawsim
-       gcc -g -static -o $@ sawsim.c list.c tension_balance.c tension_model.c k_model.c parse.c string_eval.c accel_k.c interp.c tavl.c -lgsl -lgslcblas -lm
-sawsim_profile : sawsim
-       gcc -g -pg -o $@ sawsim.c list.c tension_balance.c tension_model.c k_model.c parse.c string_eval.c accel_k.c interp.c tavl.c -lgsl -lgslcblas -lm
-
-
-check_sawsim.c : sawsim.nw
-       notangle -Rchecks $^ > $@
-check_sawsim : check_sawsim.c global.h list.c list.h tension_balance.c tension_balance.h \
-               k_model.c k_model.h parse.c parse.h string_eval.c string_eval.h accel_k.c accel_k.h
-       gcc -g -o $@ $< list.c tension_balance.c k_model.c parse.c string_eval.c accel_k.c interp.c tavl.c -lgsl -lgslcblas -lm -lcheck
-clean_check :
-       rm -f check_sawsim check_sawsim.c
-check : check_list check_tension_balance check_k_model check_parse check_string_eval check_accel_k check_sawsim
-       check_list
-       check_tension_balance
-       check_k_model
-       check_parse
-       check_string_eval
-       check_accel_k
-       check_sawsim
+# Decide what directories to put things in
+SRC_DIR = src
+BUILD_DIR = build
+BIN_DIR = bin
+DOC_DIR = doc
+# Note: Cannot use, for example, `./build', because make eats the `./' 
+# and then $(BUILD_DIR) doesn't match in $$(subst $(BUILD_DIR), ...) 
+
+# Modules (X.c, X.h) defined in the noweb file
+NW_SAWSIM_MODS = 
+CHECK_BINS = 
+# Modules defined outside the noweb file
+FREE_SAWSIM_MODS = interp tavl
 
 <<list module makefile lines>>
 <<tension balance module makefile lines>>
@@ -5141,15 +5081,121 @@ check : check_list check_tension_balance check_k_model check_parse check_string_
 <<parse module makefile lines>>
 <<string eval module makefile lines>>
 <<accel k module makefile lines>>
+
+SAWSIM_MODS = $(NW_SAWSIM_MODS) $(FREE_SAWSIM_MODS)
+
+# Everything needed for sawsim under one roof.  sawsim.c must come first
+SAWSIM_SRC = $(BUILD_DIR)/sawsim.c $(BUILD_DIR)/global.h \
+       $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(SAWSIM_MODS:%=$(BUILD_DIR)/%.h)
+# Libraries needed to compile sawsim
+LIBS = gsl gslcblas m
+CHECK_LIBS = gsl gslcblas m check
+# The non-check binaries generated
+BINS = sawsim tension_model_utils k_model_utils sawsim_profile
+DOCS = sawsim.pdf
+
+# Define the major targets
+all : ./Makefile $(BINS:%=$(BIN_DIR)/%) $(DOCS:%=$(DOC_DIR)/%) ;
+
+view : $(DOC_DIR)/sawsim.pdf
+       xpdf $< &
+profile : $(BIN_DIR)/sawsim_profile $(BIN_DIR)
+       $(BIN_DIR)/sawsim_profile -v1e-6 -Mhooke -A.05 -U1 -kkramers_integ \
+               -mnull -Mwlc -A0.39e-9,28e-9 -F8
+       gprof $(BIN_DIR)/sawsim_profile gmon.out > $@
+check : $(CHECK_BINS:%=$(BIN_DIR)/%) $(BIN_DIR)/check_sawsim
+       $(SHELL) -e -c 'for B in $^; do ./$$B; done'
+clean : $(CHECK_BINS:%=clean_%) clean_tension_model_utils \
+               clean_k_model_utils clean_latex
+       rm -f $(BIN_DIR)/sawsim $(BIN_DIR)/sawsim_static \
+               $(BIN_DIR)/sawsim_profile $(BUILD_DIR)/sawsim.c \
+               $(BUILD_DIR)/interp.c $(BUILD_DIR)/interp.h \
+               $(BUILD_DIR)/tavl.c $(BUILD_DIR)/tavl.h \
+               $(BUILD_DIR)/global.h ./gmon.out
+       $(SHELL) -e -c "rmdir $(BUILD_DIR) $(BIN_DIR) $(DOC_DIR)"
+
+# Various builds of sawsim
+$(BIN_DIR)/sawsim : $(SAWSIM_SRC) $(BIN_DIR)
+       gcc -g -o $@ $< $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
+$(BIN_DIR)/sawsim_static : $(SAWSIM_SRC) $(BIN_DIR)
+       gcc -g -static -o $@ $< $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
+$(BIN_DIR)/sawsim_profile : $(SAWSIM_SRC) $(BIN_DIR)
+       gcc -g -pg -o $@ $< $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(LIBS:%=-l%)
+
+# Create the directories
+$(BUILD_DIR) $(BIN_DIR) $(DOC_DIR) :
+       mkdir $@
+
+# Copy over the source external to sawsim
+# Note: Cannot use, for example, `./build', because make eats the `./' 
+# and then $(BUILD_DIR) doesn't match in $$(subst $(BUILD_DIR), ...) 
+.SECONDEXPANSION:
+$(FREE_SAWSIM_MODS:%=$(BUILD_DIR)/%.h) : $$(subst $(BUILD_DIR),$(SRC_DIR),$$@)\
+               $(BUILD_DIR)
+       cp -f $< $@
+.SECONDEXPANSION:
+$(FREE_SAWSIM_MODS:%=$(BUILD_DIR)/%.c) : $$(subst $(BUILD_DIR),$(SRC_DIR),$$@)\
+               $(BUILD_DIR)
+       cp -f $< $@
+
+## Basic source generated with noweb
+# The central files sawsim.c and global.h...
+$(BUILD_DIR)/sawsim.c : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+       notangle $< > $@
+$(BUILD_DIR)/global.h : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+       notangle -Rglobal.h $< > $@
+# ... and the modules
+$(NW_SAWSIM_MODS:%=$(BUILD_DIR)/%.h) : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+       notangle -R$(subst _,-,$(@:$(BUILD_DIR)/%=%)) $< > $@
+$(NW_SAWSIM_MODS:%=$(BUILD_DIR)/%.c) : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+       notangle -R$(subst _,-,$(@:$(BUILD_DIR)/%=%)) $< > $@
+$(CHECK_BINS:%=$(BUILD_DIR)/%.c) : $(SRC_DIR)/sawsim.nw $(BUILD_DIR)
+       notangle -R$(subst _,-,$(@:$(BUILD_DIR)/%=%)) $< > $@
+# Note: I use `_' as a space in my file names, but noweb doesn't like
+# that so we use `-' to name the noweb roots and substitute here.
+
+## Building the unit-test programs
+# for sawsim.c...
+$(BUILD_DIR)/check_sawsim.c : $(SRC_DIR)/sawsim.nw
+       notangle -Rchecks $< > $@
+$(BIN_DIR)/check_sawsim : $(BUILD_DIR)/check_sawsim.c $(BUILD_DIR)/global.h \
+               $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) \
+               $(SAWSIM_MODS:%=$(BUILD_DIR)/%.h) $(BIN_DIR)
+       gcc -g -o $@ $< $(SAWSIM_MODS:%=$(BUILD_DIR)/%.c) $(CHECK_LIBS:%=-l%)
+clean_check_sawsim :
+       rm -f $(BIN_DIR)/check_sawsim $(BUILD_DIR)/check_sawsim.c
+# ... and the modules
+.SECONDEXPANSION:
+$(CHECK_BINS:%=$(BIN_DIR)/%) : $$(subst $(BIN_DIR),$(BUILD_DIR),$$@).c \
+               $$(subst $(BIN_DIR)/check_,$(BUILD_DIR)/,$$@).c \
+               $$(subst $(BIN_DIR)/check_,$(BUILD_DIR)/,$$@).h \
+               $$(patsubst %,$(BUILD_DIR)/%.c,$$($$(subst $(BIN_DIR)/,,$$@_MODS)))\
+               $$(patsubst %,$(BUILD_DIR)/%.h,$$($$(subst $(BIN_DIR)/,,$$@_MODS)))\
+               $$(BUILD_DIR)/global.h $(BIN_DIR)
+       gcc -g -o $@ $< $(@:$(BIN_DIR)/check_%=$(BUILD_DIR)/%.c) \
+               $(patsubst %,$(BUILD_DIR)/%.c,$($(subst $(BIN_DIR)/,,$@_MODS)))\
+               $(CHECK_LIBS:%=-l%)
+# todo: clean up the required modules to
+$(CHECK_BINS:%=clean_%) :
+       rm -f $(@:clean_%=$(BIN_DIR)/%) $(@:clean_%=$(BUILD_DIR)/%.c)
+
+# Cleaning up the modules
+.SECONDEXPANSION:
+$(SAWSIM_MODS:%=clean_%) :
+       rm -f $(@:clean_%=$(BUILD_DIR)/%.c) $(@:clean_%=$(BUILD_DIR)/%.h)
+
+<<tension model utils makefile lines>>
+<<k model utils makefile lines>>
 <<latex makefile lines>>
 
-Makefile : sawsim.nw
-       notangle -Rmakefile $^ | sed 's/        /\t/' > $@
+Makefile : $(SRC_DIR)/sawsim.nw
+       notangle -Rmakefile $< | sed 's/        /\t/' > $@
 @ 
-This is fairly self-explanatory.
-We compile a dynamically linked version ([[sawsim]]) and a statically linked version ([[sawsim_static]]).
-The static version is about 9 times as big, but it runs without needing dynamic GSL libraries to link to, so it's a better format for distributing to a cluster for parallel evaluation.
-
+This is fairly self-explanatory.  We compile a dynamically linked
+version ([[sawsim]]) and a statically linked version
+([[sawsim_static]]).  The static version is about 9 times as big, but
+it runs without needing dynamic GSL libraries to link to, so it's a
+better format for distributing to a cluster for parallel evaluation.
 
 \section{Math}
 
similarity index 100%
rename from tavl.c
rename to src/tavl.c
similarity index 100%
rename from tavl.h
rename to src/tavl.h