Newer
Older
Handbook / make-includes / build_section_rules.make
################################################################################
#
# File: $Id$
#
# Standard variables and rules for building a particular section of the
# handbook. Altering these definitions will affect ALL SECTION MAKEFILES
# FOR ALL PAPERS!! If you need to do something specific for a particular
# paper, include a custom rule in its makefile. DON'T add it here!
#
################################################################################


################################################################################
#
# Run one-time initialisation stuff, _unless_ NOINIT is defined. Any
# "parent" makefile that's already done the same one-time initialisation
# and calls this one should define NOINIT (the value doesn't matter) to
# switch off one-time initialisation in this makefile. Thus if the
# "parent" makefile calls this makefile several times, things like the
# content checking will only happen once for a single invocation of the
# "parent" makefile.
# 
# When running this makefile standalone, _don't_ define NOINIT, and
# everything will still work as expected.
#
ifndef NOINIT
include $(GLOBAL_HANDBOOK_INCLUDE)/remove_content_marker_files.make
endif

# Now that the one-time initialsation is out of the way, ensure that
# NOINIT (the value doesn't matter) is exported to all sub-makefiles to
# prevent them from repeating the one-time initialisation. This prevents
# the situation where we go "make" and content checking happens twice,
# once for the web version and once for the print version. (Although I'm
# not sure why it only happens twice --- I would have expected four times.
# Go figure.)
#
export NOINIT?=x


################################################################################
#
# Given that we print out our own messages, I see no point in splurging
# "Entering...leaving directory" messages all over the screen. It's hard
# enough to figure out what's going on already :)
#
MAKEFLAGS=--no-print-directory


################################################################################
#
# Include variables defining the current paper.
#
include $(LOCAL_HANDBOOK_INCLUDE)/paper_variables.make


################################################################################
#
# Defines which section we are currently building. This is actually the
# path to the main folder for the section. Normally this is exported from
# a higher-level makefile (i.e., "export SECTION=path/to/section").
#
export SECTION?=$(notdir $(CURDIR))


################################################################################
#
# Define patterns for required source files. We define the basic variables
# first (empty), then scan the make-includes directory for patterns files.
# Each patterns file should add its patterns (using +=) to the appropriate
# pattern variable from the following.
#
# QUESTIONS_PATTERNS defines the patterns for the "questions" version of
# the handbook (both web and print).
#
QUESTIONS_PATTERNS:=

#
# ANSWERS_PATTERNS defines the patterns for the "answers" version of
# the handbook (both web and print).
#
ANSWERS_PATTERNS:=

#
# *_INSTALL_PATTERNS defines the patterns for installing on the web server.
#
QUESTION_INSTALL_PATTERNS:=
ANSWER_INSTALL_PATTERNS:=

#
# Now go looking for patterns files in the local make-includes directory.
# files should be named "*.patterns"
#
include $(LOCAL_HANDBOOK_INCLUDE)/*.patterns


################################################################################
#
# Define lists of source directories that contain documents to be included
# in the handbook. These are generated according to the values of the
# patterns defined in the various pattern include files.
#
# Note that all the find commands are relative to the working directory of
# the makefile that includes this file. Thus, if we are in the Tutorials
# directory, all finds will be relative to this (and thus the lab patterns
# won't find anything). The main consequence of this is that the
# CLEAN_DIRS find will only generate a list of the directories that can be
# cleaned _for the current section_. In practice, however, this will still
# work as expected; if we're cleaning just that section, this is what we
# want anyway, and if we're cleaning the entire handbook, the master
# handbook makefile will call the makefile for each section separately.
#
################################################################################
#
# Directories for the complete collection of documents to be built for the
# "questions" and "answers" versions of the handbook, respectively. Since
# the tutorials variables will be empty when we're in the labs directory,
# and vice versa, everything just works!
#
QUESTION_SRC_DIRS:=$(foreach p,$(QUESTIONS_PATTERNS),$(notdir $(shell find . -regex '.*/'$(p))))

ANSWER_SRC_DIRS:=$(foreach p,$(ANSWERS_PATTERNS),$(notdir $(shell find . -regex '.*/'$(p))))

QUESTION_INSTALL_DIRS:=$(foreach p,$(QUESTION_INSTALL_PATTERNS),$(notdir $(shell find . -regex '.*/'$(p))))

ANSWER_INSTALL_DIRS:=$(foreach p,$(ANSWER_INSTALL_PATTERNS),$(notdir $(shell find . -regex '.*/'$(p))))

#
# List of directories that can be cleaned. "-mindepth 2" ensures
# that we only include sub-directories of the current directory.
#
CLEAN_DIRS:=$(dir $(shell find . -mindepth 2 -name Makefile))


################################################################################
#
# Define lists of LaTeX source files. These will be written out to the
# appropriate manifest file, so that the master handbook makefile can
# import them into the handbook LaTeX build. Only the files specified by
# the file patterns are included. The manifest file is also only updated
# when necessary, i.e., when the list of files changes.
#
QUESTION_TEX_SOURCE:=$(foreach d,$(QUESTION_SRC_DIRS),$d/$d-questions.tex)
ANSWER_TEX_SOURCE:=$(foreach d,$(ANSWER_SRC_DIRS),$d/$d-answers.tex)

QUESTION_TEX_INPUTS:=$(foreach f,$(QUESTION_TEX_SOURCE),\\input{Sections/$(SECTION)/$(basename $f)})
ANSWER_TEX_INPUTS:=$(foreach f,$(ANSWER_TEX_SOURCE),\\input{Sections/$(SECTION)/$(basename $f)})


################################################################################
#
# Directory to install files into on web server.
#
INSTALL_DIRECTORY:=$(HANDBOOK_INSTALL_ROOT)/$(SUBJECT_CODE)$(PAPER_NUMBER)/www/$(SECTION)


################################################################################
#
# Files to be installed on web server.
#
INSTALL_FILES:=


################################################################################
#
# Lists of files for cleaning up. Add to these (using +=) as necessary in
# derived makefiles.
#
WEB_CLEAN_FILES:=
PRINT_CLEAN_FILES:=*-manifest.tex
ALL_CLEAN_FILES:=$(WEB_CLEAN_FILES) $(PRINT_CLEAN_FILES)


################################################################################
#
# List of possible targets. If you need to add to this for a specific
# case, use TARGETS+=xxx in the actual makefile.
#
TARGETS:=all targets debug install \
	web web-questions web-answers \
	print print-questions print-answers \
	questions answers \
	print-question-docs print-answer-docs \
	clean web-clean print-clean

.PHONY: $(TARGETS)


################################################################################
#
# Build everything.
#
all: web print


################################################################################
#
# Build questions or answers only.
#
questions: web-questions print-questions

answers: web-answers print-answers


################################################################################
#
# Build web version only.
#
# Note the weird dance with the ifs in the recursive make calls. If we
# don't do this, the foreach just keeps going even if one of the sub-makes
# dies. We therefore have to do our own error detection and dying. Bummer.
#
web: web-questions web-answers

web-questions:
	@$(foreach d,$(QUESTION_SRC_DIRS),if $(MAKE) -C $d web-questions; then /usr/bin/true; else exit 1; fi;)

web-answers:
	@$(foreach d,$(ANSWER_SRC_DIRS),if $(MAKE) -C $d web-answers; then /usr/bin/true; else exit 1; fi;)


################################################################################
#
# Build print version only. We also need to build the manifest files that
# will be \input into the master handbook.tex document.
#
print: print-questions print-answers

print-questions: print-question-docs question-manifest.tex

print-question-docs:
	@$(foreach d,$(QUESTION_SRC_DIRS),if $(MAKE) -C $d print-questions; then /usr/bin/true; else exit 1; fi;)

question-manifest.tex: $(QUESTION_TEX_SOURCE) $(LOCAL_HANDBOOK_INCLUDE)/questions.patterns
	@announce "Generating questions version manifest file in $(SECTION)"
	@echo $(QUESTION_TEX_INPUTS) > $@

question-pdfs:
	@$(foreach d,$(QUESTION_SRC_DIRS),if $(MAKE) -C $d $d-questions.pdf $d-questions-2up.pdf; then /usr/bin/true; else exit 1; fi;)


print-answers: print-answer-docs answer-manifest.tex

print-answer-docs:
	@$(foreach d,$(ANSWER_SRC_DIRS),if $(MAKE) -C $d print-answers; then /usr/bin/true; else exit 1; fi;)

answer-manifest.tex: $(ANSWER_TEX_SOURCE) $(LOCAL_HANDBOOK_INCLUDE)/answers.patterns
	@announce "Generating answers version manifest file in $(SECTION)"
	@echo $(ANSWER_TEX_INPUTS) > $@

answer-pdfs:
	@$(foreach d,$(QUESTION_SRC_DIRS),if $(MAKE) -C $d $d-answers.pdf $d-answers-2up.pdf; then /usr/bin/true; else exit 1; fi;)


################################################################################
#
# Install the appropriate files on the web server. This relies on the
# environment variable HANDBOOK_INSTALL_DIRECTORY being defined, and
# (assuming that this variable points to a directory on the network) the
# appropriate share has been mounted.
#
# Most of the work is carried out by recursive make calls to the
# subordinate document makefiles. Files that are generic to the entire
# section are dealt with here, though. Each file in the build directory is
# checked against the corresponding file in the install directory. The
# local file is only copied to the install directory if it is newer, or
# the remote file doesn't exist. See build_document_rules.make for an
# explanation of why it's implemented using a foreach.
#
install:
	@announce "Installing files in $(SECTION)"
	@test -d $(HANDBOOK_INSTALL_ROOT)
	@mkdir -p $(INSTALL_DIRECTORY)
	@$(foreach d,$(QUESTION_INSTALL_DIRS),if $(MAKE) -C $d install-questions; then /usr/bin/true; else exit 1; fi;)
	@$(foreach d,$(ANSWER_INSTALL_DIRS),if $(MAKE) -C $d install-answers; then /usr/bin/true; else exit 1; fi;)
	@$(foreach f,$(INSTALL_FILES),if test ! -f $(INSTALL_DIRECTORY)/$(f) -o $(f) -nt $(INSTALL_DIRECTORY)/$(f); then echo "Installing $(f)"; cp $(f) $(INSTALL_DIRECTORY); fi;)


################################################################################
#
# Clean up all generated files.
# "web-clean" and "print-clean" only clean up files for the web and print
# versions, respectively. Note that "clean" isn't dependent on either
# "web-clean" or "print-clean", to ensure that the correct target is
# used when calling the sub-makefile.
#
clean:
	@$(foreach d,$(CLEAN_DIRS),$(MAKE) -C $d $@;)
ifneq ($(strip $(ALL_CLEAN_FILES)),)
	-rm -f $(ALL_CLEAN_FILES)
endif

web-clean:
	@$(foreach d,$(CLEAN_DIRS),$(MAKE) -C $d $@;)
ifneq ($(strip $(WEB_CLEAN_FILES)),)
	-rm -f $(WEB_CLEAN_FILES)
endif

print-clean:
	@$(foreach d,$(CLEAN_DIRS),$(MAKE) -C $d $@;)
ifneq ($(strip $(PRINT_CLEAN_FILES)),)
	-rm -f $(PRINT_CLEAN_FILES)
endif

#
# "init-clean" is a dummy target that can be used to ensure that the
# content-checked marker files get deleted. Do a "make -C xxx" (i.e.,
# don't define NOINIT). The actual deletion is done by the one-time
# initialisation in remove_content_marker_files.make. Note that there's no
# point in this rule printing anything, because the output will probably
# end up buried in a one-time initialisation "variable".
#
init-clean:


################################################################################
#
# Debugging information, mostly lists of the generated variables.
#
debug:
	@announce Externally defined variables
	@echo "TEACHING_SHARED = [$(TEACHING_SHARED)]"
	@echo "HANDBOOK_INSTALL_ROOT = [$(HANDBOOK_INSTALL_ROOT)]"
	@echo "NOINIT = [$(NOINIT)]"
	@announce Internally defined variables
	@echo "GLOBAL_HANDBOOK_INCLUDE = [$(GLOBAL_HANDBOOK_INCLUDE)]"
	@echo "LOCAL_HANDBOOK_INCLUDE = [$(LOCAL_HANDBOOK_INCLUDE)]"
	@echo "QUESTIONS_PATTERNS = [$(QUESTIONS_PATTERNS)]"
	@echo "ANSWERS_PATTERNS = [$(ANSWERS_PATTERNS)]"
	@echo "QUESTION_INSTALL_PATTERNS = [$(QUESTION_INSTALL_PATTERNS)]"
	@echo "ANSWER_INSTALL_PATTERNS = [$(ANSWER_INSTALL_PATTERNS)]"
	@echo "SECTION = [$(SECTION)]"
	@echo "QUESTION_SRC_DIRS = [$(QUESTION_SRC_DIRS)]"
	@echo "ANSWER_SRC_DIRS = [$(ANSWER_SRC_DIRS)]"
	@echo "QUESTION_INSTALL_DIRS = [$(QUESTION_INSTALL_DIRS)]"
	@echo "ANSWER_INSTALL_DIRS = [$(ANSWER_INSTALL_DIRS)]"
	@echo "CLEAN_DIRS = [$(CLEAN_DIRS)]"
	@echo "QUESTION_TEX_SOURCE = [$(QUESTION_TEX_SOURCE)]"
	@echo "ANSWER_TEX_SOURCE = [$(ANSWER_TEX_SOURCE)]"
	@echo "QUESTION_TEX_INPUTS = [$(QUESTION_TEX_INPUTS)]"
	@echo "INSTALL_DIRECTORY = [$(INSTALL_DIRECTORY)]"
	@echo "INSTALL_FILES = [$(INSTALL_FILES)]"
	@echo "WEB_CLEAN_FILES = [$(WEB_CLEAN_FILES)]"
	@echo "PRINT_CLEAN_FILES = [$(PRINT_CLEAN_FILES)]"
	@echo "ALL_CLEAN_FILES = [$(ALL_CLEAN_FILES)]"


################################################################################
#
# Print out the list of targets. Handy for when you forget!
#
targets:
	@echo $(TARGETS)