Newer
Older
Handbook / make-includes / build_section_rules.make
################################################################################
#
# 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

#
# Ensure that the patterns files exist. If they don't, copy the originals
# across from the shared directory and abort the run so that the user can
# edit them appropriately.
#
CHECK_ANSWERS_PATTERNS:=$(shell ($(TEST) -f $(LOCAL_HANDBOOK_INCLUDE)/answers.patterns) || ($(CP) $(TEACHING_SHARED)/Authoring/Handbook/makefile-templates/answers.patterns $(LOCAL_HANDBOOK_INCLUDE); $(ECHO) "answers"))
CHECK_QUESTIONS_PATTERNS:=$(shell ($(TEST) -f $(LOCAL_HANDBOOK_INCLUDE)/questions.patterns) || ($(CP) $(TEACHING_SHARED)/Authoring/Handbook/makefile-templates/questions.patterns $(LOCAL_HANDBOOK_INCLUDE); $(ECHO) "questions"))
CHECK_INSTALL_PATTERNS:=$(shell ($(TEST) -f $(LOCAL_HANDBOOK_INCLUDE)/install.patterns) || ($(CP) $(TEACHING_SHARED)/Authoring/Handbook/makefile-templates/install.patterns $(LOCAL_HANDBOOK_INCLUDE); $(ECHO) "install"))
CHECK_ALL_PATTERNS:=$(CHECK_ANSWERS_PATTERNS) $(CHECK_QUESTIONS_PATTERNS) $(CHECK_INSTALL_PATTERNS)

ifneq "$(strip $(CHECK_ALL_PATTERNS))" ""
$(error Patterns files have been restored from defaults ($(CHECK_ALL_PATTERNS)), please check them before continuing)
endif

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) | sort)))

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

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

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

#
# 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)/$(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 $(TRUE); else exit 1; fi;)

web-answers:
	@$(foreach d,$(ANSWER_SRC_DIRS),if $(MAKE) -C $d web-answers; then $(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 $(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 $(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 $(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,$(ANSWER_SRC_DIRS),if $(MAKE) -C $d $d-answers.pdf $d-answers-2up.pdf; then $(TRUE); else exit 1; fi;)


################################################################################
#
# Deploy the appropriate files into a shared folder, which is then synchronised
# with Blackboard. This relies on the environment variable HANDBOOK_INSTALL_ROOT
# 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 deployment 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: questions answers
	@$(ANNOUNCE) "Deploying files from $(SECTION) into $(INSTALL_DIRECTORY)"
	@$(TEST) -d $(HANDBOOK_INSTALL_ROOT)
	@$(MKDIR_P) $(INSTALL_DIRECTORY)
	@$(foreach d,$(QUESTION_INSTALL_DIRS),if $(MAKE) -C $d install-questions; then $(TRUE); else exit 1; fi;)
	@$(foreach d,$(ANSWER_INSTALL_DIRS),if $(MAKE) -C $d install-answers; then $(TRUE); else exit 1; fi;)
	@$(foreach f,$(INSTALL_FILES),if $(TEST) ! -f $(INSTALL_DIRECTORY)/$(f) -o $(f) -nt $(INSTALL_DIRECTORY)/$(f); then $(ECHO) "Deploying $(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) "ANSWER_TEX_INPUTS = [$(ANSWER_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)