# 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 # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Declare variables describing package information. # http://www.gnu.org/software/make/manual/html_node/Setting.html # The $(...) syntax references a variable's value. # http://www.gnu.org/software/make/manual/html_node/Reference.html # You can override variables from the command line. For example # $ make VERSION=2 dist # will generate phys405-hw0-2.tar.gz COURSE = phys405 PACKAGE = hw0 VERSION = 1 RELEASE = $(COURSE)-$(PACKAGE)-$(VERSION) 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 *.cpp *.h COPYING Makefile README $(SCRIPTS) # 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. # hello_world_LIBS = -lm $(foreach PROGRAM, $(PROGRAMS), $(eval $(PROGRAM)_LIBS =)) # Define useful programs (this makes it easy to swap in alternates) CP = cp GREP = grep MKDIR = mkdir RM = rm 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 print- printvars # target: all - the default target # 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 help: $(GREP) '^# target:' [Mm]akefile # target: clean - remove automatically generated files clean: $(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 # release directory, and remove the release directory. dist: $(MKDIR) $(RELEASE) $(CP) -r $(SOURCE) $(RELEASE) $(TAR) -czf $(RELEASE).tar.gz $(RELEASE) $(RM) -rf $(RELEASE) # target: hello_world - compile the hello_world program # Use GCC to link the program from object files. # 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 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 # RUN_PROGRAM. run: $(PROGRAMS) ./$(RUN_PROGRAM) # 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. 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 # but they can also be come from the environment # http://www.gnu.org/software/make/manual/html_node/Environment.html # for example, try # $ make CXX=/usr/local/bin/g++ CXXFLAGS=-Wall %.o: %.cpp $(CXX) $(CXXFLAGS) -c "$<" # Pattern rule for compiling object files from C source # The comments from the C++ rule above also apply here %.o: %.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))) \ ) \ )