X-Git-Url: http://git.tremily.us/?p=assignment-template.git;a=blobdiff_plain;f=Makefile;h=af2d15bbbc003d4a322be1236b70dfab14e2abb0;hp=74a07e0f1d18cf6dd89d9f024b23ed5bef306b88;hb=HEAD;hpb=0c57a2928b28425dab1acea82103e2aa4783aa1e diff --git a/Makefile b/Makefile index 74a07e0..af2d15b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2012 W. Trevor King +# Copyright (C) 2012-2013 W. Trevor King # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -24,18 +24,29 @@ COURSE = phys405 PACKAGE = hw0 VERSION = 1 RELEASE = $(COURSE)-$(PACKAGE)-$(VERSION) -PROGRAM = hello_world +RUN_PROGRAM = hello_world +SCRIPTS = +C_PROGRAMS = hello_world +CXX_PROGRAMS = goodbye_world +PROGRAMS = $(C_PROGRAMS) $(CXX_PROGRAMS) # Define the source files that will be distributed in the tarball -SOURCE = *.c COPYING Makefile README +SOURCE = *.c *.cpp *.h COPYING Makefile README $(SCRIPTS) -# Define a list of object files needed to link PROGRAM -OBJECTS = $(PROGRAM).o +# Define a list of object files needed to link PROGRAM. We're setting +# things up here so that a program % depends on the object file %.o. +# For details on `foreach` and `eval`, see +# http://www.gnu.org/software/make/manual/html_node/Foreach-Function.html +# http://www.gnu.org/software/make/manual/html_node/Eval-Function.html +$(foreach PROGRAM, $(PROGRAMS), $(eval $(PROGRAM)_OBJECTS = $(PROGRAM).o)) + +# You can override a paricular case here with something like: +#hello_world_OBJECTS = hello_world.o utility_code.o # You may want to link agains external libraries. For example, to # link against the system math library, use. -# LIBS = -lm -LIBS = +# hello_world_LIBS = -lm +$(foreach PROGRAM, $(PROGRAMS), $(eval $(PROGRAM)_LIBS =)) # Define useful programs (this makes it easy to swap in alternates) CP = cp @@ -46,10 +57,12 @@ TAR = tar # Declare targets that do not generate files of the same name. # http://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: all help clean dist run +.PHONY: all help clean dist run print- printvars # target: all - the default target -all: $(PROGRAM) +# The target of the first rule is the default goal. See: +# http://www.gnu.org/software/make/manual/html_node/Rules.html +all: $(PROGRAMS) # target: help - display callable targets # Use `grep` to search this file for target comments @@ -58,7 +71,7 @@ help: # target: clean - remove automatically generated files clean: - $(RM) -rf $(PROGRAM) *.o $(RELEASE)* + $(RM) -rf $(PROGRAMS) *.o $(RELEASE)* # target: dist - generate a tarball packaging the source # Here, we move the source into a temporary release directory, tar the @@ -71,23 +84,66 @@ dist: # target: hello_world - compile the hello_world program # Use GCC to link the program from object files. -$(PROGRAM): $(OBJECTS) - $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) +# For an explanation of the static pattern rule syntax: +# targets ...: target-pattern: prereq-patterns ... +# see +# http://www.gnu.org/software/make/manual/html_node/Static-Usage.html +# For an explanation of $@, $^, and other special variables, see +# http://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html +# For an explanation of .SECONDEXPANSION, see +# http://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html +# `$$` escapes make-variable expansion for the first pass through the +# recipe. See +# http://www.gnu.org/software/make/manual/html_node/Variables-in-Recipes.html +# +# What's going on here? During the read-in phase, Make expands the +# rule to +# hello_world goodbye_world: % : $($(@)_OBJECTS) +# Because we're using .SECONDEXPANSION, Make expands the prerequisites +# again during the target-update phase. If we're building +# hello_world, $(@) will expand to hello_world, and we'll have +# hello_world goodbye_world: hello_world : $(hello_world_OBJECTS) +# as the variable expansion continues, we end up with +# hello_world goodbye_world: hello_world : hello_world.o +# which is the final rule used to determine the prerequisites. +# +# The recipe expands to +# cc -o hello_world hello_world.o $(hello_world_LIBS) +# which expands to (if hello_world_LIBS was set to `-lm`) +# cc -o hello_world hello_world.o -lm +# +# Striking the right balance between "everything handled +# automatically" (i.e. "complicated") and "everything handled +# manually" (i.e. tedious) is difficult, and maybe this rule crosses +# the line. The simpler alternative would be to define your own +# prerequisites for each program you wish to compile, and you're +# certainly allowed to go that route if you wish. +.SECONDEXPANSION: +$(C_PROGRAMS): % : $$($$(@)_OBJECTS) + $(CC) $(LDFLAGS) -o "$@" $^ $($(@)_LIBS) + +.SECONDEXPANSION: +$(CXX_PROGRAMS): % : $$($$(*)_OBJECTS) + $(CXX) $(LDFLAGS) -o "$@" $^ $($(@)_LIBS) # target: run - use the program for its intended purpose -# Here we just execute PROGRAM, but you could also use something like -# run: $(PROGRAM) plot.gp -# ./$(PROGRAM) > data +# Here we just execute RUN_PROGRAM, but you could also use something +# like +# run: $(RUN_PROGRAM) plot.gp +# ./$(RUN_PROGRAM) > data # gnuplot plot.gp # where plot.gp was a gnuplot script for plotting data generated by -# PROGRAM. -run: $(PROGRAM) - ./$(PROGRAM) +# RUN_PROGRAM. +run: $(PROGRAMS) + ./$(RUN_PROGRAM) -# Matching rule for compiling object files from C++ source +# Pattern rule for compiling object files from C++ source # There is an implicit rule for this in GNU make # http://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html -# but I redefine it here for clarity. +# but I redefine it here for clarity. For an explanation of the +# %.o: %.cpp +# syntax, see +# http://www.gnu.org/software/make/manual/html_node/Pattern-Intro.html # # CXX and CXXFLAGS have defaults defined by make # http://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html @@ -96,9 +152,41 @@ run: $(PROGRAM) # for example, try # $ make CXX=/usr/local/bin/g++ CXXFLAGS=-Wall %.o: %.cpp - $(CXX) $(CXXFLAGS) -c $< + $(CXX) $(CXXFLAGS) -c "$<" -# Matching rule for compiling object files from C source +# Pattern rule for compiling object files from C source # The comments from the C++ rule above also apply here %.o: %.c - $(CC) $(CFLAGS) -c $< + $(CC) $(CFLAGS) -c "$<" + +# target: print-% - display a variable value (e.g. print-PROGRAMS) +# Take some of the mystery out of variable manipulation. For example, +# $ make print-hello_world_OBJECTS +# The `@` suppresses recipe echoing. See +# http://www.gnu.org/software/make/manual/html_node/Echoing.html +# The `info` function acts like the shell `echo` command. See +# http://www.gnu.org/software/make/manual/html_node/Make-Control-Functions.html +# For an explanation of $* and other special variables, see +# http://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html +print-%: + @$(info $* = $($*)) + +# target: printvars - display all non-default variables +# .VARIBALES holds a list of all global variables. See +# http://www.gnu.org/software/make/manual/html_node/Special-Variables.html +# The functions---`sort`, `if`, `filter-out`, `origin`, `warning`, and +# `value`--- are discussed, respectively, here: +# http://www.gnu.org/software/make/manual/html_node/Text-Functions.html#index-sort-580 +# http://www.gnu.org/software/make/manual/html_node/Conditional-Functions.html +# http://www.gnu.org/software/make/manual/html_node/Text-Functions.html#index-filter_002dout-577 +# http://www.gnu.org/software/make/manual/html_node/Origin-Function.html +# http://www.gnu.org/software/make/manual/html_node/Value-Function.html +printvars: + @$(foreach V, \ + $(sort $(.VARIABLES)), \ + $(if \ + $(filter-out environment default automatic, \ + $(origin $V)), \ + $(info $V=$($V) (origin: $(origin $V), value: $(value $V))) \ + ) \ + )