GitBucket
4.21.2
Toggle navigation
Snippets
Sign in
Files
Branches
1
Releases
Issues
1
Pull requests
Labels
Priorities
Milestones
Wiki
Forks
nigel.stanger
/
Handbook
Browse code
- Fixed typo.
master
1 parent
6ad308b
commit
6b7f646a573697c9d29696d40959e34bf82cc6b0
nstanger
authored
on 13 Aug 2012
Patch
Showing
3 changed files
make-includes/build_document_rules.make
make-includes/build_misc_rules.make
make-includes/build_section_rules.make
Ignore Space
Show notes
View
make-includes/build_document_rules.make
################################################################################ # # File: $Id$ # # Standard variables and rules for building a particular document within a # section of the handbook (e.g., a single tutorial). Altering these # definitions will affect ALL DOCUMENT 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 ################################################################################ # # 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 ################################################################################ # # We make quite a lot of reference to files in the handbook directory, # so set a variable to point to it. PAPER_ROOT is defined in the include # file paper_variables.make. # HANDBOOK_ROOT:=$(PAPER_ROOT)/Handbook ################################################################################ # # Include XSLT functions. # include $(GLOBAL_HANDBOOK_INCLUDE)/xslt_functions.make ################################################################################ # # Defines which section we are currently building. This is actually the # path to the main folder for the section. Normally this is passed in as # an argument to make from a higher-level makefile (i.e., "make # SECTION=path/to/section"). # # Hmm, sh seems to convert uppercase letters in my paths to lowercase. # I'm not sure whether this will break anything or not... # # I _can_ confirm that having spaces anywhere in the parent path causes # serious breakage, because notdir returns bogus results in such cases. # All of the make functions assume whitespace delimitation, and there # doesn't seem to be any obvious way to work around this other than # eliminating spaces from the parent path (quoting the result of the # shell function below makes no difference). Fortunately, this is pretty # easy to do :) # # SECTION?=$(notdir $(shell cd ..; pwd)) ################################################################################ # # Set up the context for the current document. # # We use the same base name for both the directory and the document, which # makes life very easy :) # BASE_NAME:=$(notdir $(CURDIR)) # # SOURCE_XML is the original source XML, from which DERIVED_XML is # generated (the derived source has the includes for questions, etc., # inserted). # SOURCE_XML:=$(BASE_NAME).xml DERIVED_XML:=$(SOURCE_XML:.xml=-derived.xml) # # Define the names of the output files. # WEB_QUESTIONS_HTML:=$(BASE_NAME)-questions.html WEB_ANSWERS_HTML:=$(BASE_NAME)-answers.html PRINT_QUESTIONS_TEX:=$(WEB_QUESTIONS_HTML:.html=.tex) PRINT_ANSWERS_TEX:=$(WEB_ANSWERS_HTML:.html=.tex) PRINT_QUESTIONS_PDF_1UP:=$(PRINT_QUESTIONS_TEX:.tex=.pdf) PRINT_ANSWERS_PDF_1UP:=$(PRINT_ANSWERS_TEX:.tex=.pdf) PRINT_QUESTIONS_PDF_2UP:=$(PRINT_QUESTIONS_TEX:.tex=-2up.pdf) PRINT_ANSWERS_PDF_2UP:=$(PRINT_ANSWERS_TEX:.tex=-2up.pdf) # # Groupings of various web- and print-related files, for easy reference. # Feel free to add to these as necessary :) # DERIVED_WEB_FILES:=$(WEB_QUESTIONS_HTML) $(WEB_ANSWERS_HTML) DERIVED_PRINT_FILES:=$(PRINT_QUESTIONS_TEX) $(PRINT_ANSWERS_TEX) \ $(PRINT_QUESTIONS_PDF_1UP) $(PRINT_ANSWERS_PDF_1UP) \ $(PRINT_QUESTIONS_PDF_2UP) $(PRINT_ANSWERS_PDF_2UP) # # List of XSL stylesheets. If any of these change, we need to rebuild # everything. # # We can't use the resolver approach under Windows because of the DOS # pathnames. The style sheets come out of the resolver with paths like # C:\bar\foo\..., and make interprets the colon as an extra dependency # delimiter (tested and behaviour verified). Of course, this works fine on # any platform with sensible path standards. Quoting the value doesn't # help, unfortunately. Bugger :( # #XSLT_STYLESHEETS:=$(shell $(JAVA) org.apache.xml.resolver.apps.resolver -u file:///xml2html.xsl uri | ( $(GREP) 'Result: file:' || $(ECHO) '::xml2html.xsl' ) | $(CUT) -d':' -f3-) $(shell $(JAVA) org.apache.xml.resolver.apps.resolver -u file:///xml2latex.xsl uri | ( $(GREP) 'Result: file:' || $(ECHO) '::xml2latex.xsl' ) | $(CUT) -d':' -f3-) XSLT_STYLESHEETS:=$(TEACHING_SHARED)/Authoring/XML/xml2html.xsl $(TEACHING_SHARED)/Authoring/XML/xml2xhtml.xsl $(TEACHING_SHARED)/Authoring/XML/xml2latex.xsl $(TEACHING_SHARED)/Authoring/XML/xml2xelatex.xsl ################################################################################ # # Extract the list of included filenames from the source template. Hooray # for the shell function and Perl! Include file paths are found within the # href attributes of XML Include elements (<xi:include href="..." />). # All paths are relative to $(PAPER_ROOT). We don't use # $(PAPER_ROOT)/$(SECTION), because some of the include directories may be # in relatively arbitrary locations. # CONTENT_SRC:=$(shell $(PERL) -ne 'print "$(PAPER_ROOT)/$$2\n" if m{<xi:include .*href="(\.\./)*([^"]+)"};' $(SOURCE_XML)) ################################################################################ # # Directory to install files into on web server. # INSTALL_DIRECTORY:=$(HANDBOOK_INSTALL_ROOT)/$(SUBJECT_CODE)$(PAPER_NUMBER)/$(SECTION)/$(BASE_NAME) ################################################################################ # # Files to be installed on web server. # QUESTION_INSTALL_FILES:=$(WEB_QUESTIONS_HTML) $(PRINT_QUESTIONS_PDF_1UP) \ $(PRINT_QUESTIONS_PDF_2UP) $(wildcard *.png) ANSWER_INSTALL_FILES:=$(WEB_ANSWERS_HTML) $(PRINT_ANSWERS_PDF_1UP) \ $(PRINT_ANSWERS_PDF_2UP) $(wildcard *.png) ################################################################################ # # Lists of files for cleaning up. Add to these (using +=) as necessary in # derived makefiles. Note that ALL_CLEAN_FILES comprises files that need # to be deleted _in addition_ to those listed in WEB_CLEAN_FILES and # PRINT_CLEAN_FILES (that is, it's the list of additional files for the # "clean" target, which depends on "web-clean" and "print-clean" anyway). # WEB_CLEAN_FILES:=$(DERIVED_WEB_FILES) *-web*.png PRINT_CLEAN_FILES:=$(DERIVED_PRINT_FILES) *-print*.png *.pdf ALL_CLEAN_FILES:=$(DERIVED_XML) ################################################################################ # # List of possible targets. If you need to add to this for a specific # case, use TARGETS+=xxx in the actual makefile. # TARGETS:=all content targets debug install-questions install-answers \ web web-questions web-answers \ print print-questions print-answers \ questions answers \ 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. # web: web-questions web-answers web-questions: content $(WEB_QUESTIONS_HTML) $(WEB_QUESTIONS_HTML): $(DERIVED_XML) @$(ANNOUNCE) "Building $@ from $<" $(call xslt,$<,xml2html.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,period-code,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'no'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ web-answers: content $(WEB_ANSWERS_HTML) $(WEB_ANSWERS_HTML): $(DERIVED_XML) @$(ANNOUNCE) "Building $@ from $<" $(call xslt,$<,xml2html.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,period-code,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'no'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ ################################################################################ # # Build print version only. We add code to the LaTeX source to mark the # first and last pages of the document, so that an individual PDF for this # document can be generated later. \markfirstpage and \marklastpage are # macros defined in handbook_template.tex that write the current physical # page number to the .aux file. # print: print-questions print-answers print-questions: content $(PRINT_QUESTIONS_TEX) $(PRINT_QUESTIONS_TEX): $(DERIVED_XML) @$(ANNOUNCE) "Building $@ from $<" @$(ECHO) "\\markfirstpage{$(SECTION)/$(BASE_NAME)/$(@:.tex=.pdf)}" > $@ $(call xslt,$<,xml2latex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,period-code,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'no'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'sections/$(SECTION)/$(BASE_NAME)'),$(call xslt_parameter,image-format,'pdf')) >> $@ @$(ECHO) "\\marklastpage{$(SECTION)/$(BASE_NAME)/$(@:.tex=.pdf)}" >> $@ %-questions.pdf: %-questions.tex @$(ANNOUNCE) "Generating $@" @$(if $(wildcard $(HANDBOOK_ROOT)/handbook.pdf),,$(error $(HANDBOOK_ROOT)/handbook.pdf is missing)) @gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@ \ -dFirstPage=$(shell $(GREP) '$@.1up.first' $(HANDBOOK_ROOT)/handbook.aux | $(CUT) -d= -f2) \ -dLastPage=$(shell $(GREP) '$@.1up.last' $(HANDBOOK_ROOT)/handbook.aux | $(CUT) -d= -f2) $(HANDBOOK_ROOT)/handbook.pdf %-questions-2up.pdf: %-questions.tex @$(ANNOUNCE) "Generating $@" @$(if $(wildcard $(HANDBOOK_ROOT)/handbook-2up.pdf),,$(error $(HANDBOOK_ROOT)/handbook-2up.pdf is missing)) @gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@ \ -dFirstPage=$(shell $(GREP) '$(@:-2up.pdf=.pdf).2up.first' $(HANDBOOK_ROOT)/handbook.aux | $(CUT) -d= -f2) \ -dLastPage=$(shell $(GREP) '$(@:-2up.pdf=.pdf).2up.last' $(HANDBOOK_ROOT)/handbook.aux | $(CUT) -d= -f2) $(HANDBOOK_ROOT)/handbook-2up.pdf print-answers: content $(PRINT_ANSWERS_TEX) $(PRINT_ANSWERS_TEX): $(DERIVED_XML) @$(ANNOUNCE) "Building $@ from $<" @$(ECHO) "\\markfirstpage{$(SECTION)/$(BASE_NAME)/$(@:.tex=.pdf)}" > $@ $(call xslt,$<,xml2latex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,period-code,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'no'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'sections/$(SECTION)/$(BASE_NAME)'),$(call xslt_parameter,image-format,'pdf')) >> $@ @$(ECHO) "\\marklastpage{$(SECTION)/$(BASE_NAME)/$(@:.tex=.pdf)}" >> $@ %-answers.pdf: %-answers.tex @$(ANNOUNCE) "Generating $@" @$(if $(wildcard $(HANDBOOK_ROOT)/handbook-answers.pdf),,$(error $(HANDBOOK_ROOT)/handbook-answers.pdf is missing)) @gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@ \ -dFirstPage=$(shell $(GREP) '$@.1up.first' $(HANDBOOK_ROOT)/handbook-answers.aux | $(CUT) -d= -f2) \ -dLastPage=$(shell $(GREP) '$@.1up.last' $(HANDBOOK_ROOT)/handbook-answers.aux | $(CUT) -d= -f2) $(HANDBOOK_ROOT)/handbook-answers.pdf %-answers-2up.pdf: %-answers.tex @$(ANNOUNCE) "Generating $@" @$(if $(wildcard $(HANDBOOK_ROOT)/handbook-answers-2up.pdf),,$(error $(HANDBOOK_ROOT)/handbook-answers-2up.pdf is missing)) @gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@ \ -dFirstPage=$(shell $(GREP) '$(@:-2up.pdf=.pdf).2up.first' $(HANDBOOK_ROOT)/handbook-answers.aux | $(CUT) -d= -f2) \ -dLastPage=$(shell $(GREP) '$(@:-2up.pdf=.pdf).2up.last' $(HANDBOOK_ROOT)/handbook-answers.aux | $(CUT) -d= -f2) $(HANDBOOK_ROOT)/handbook-answers-2up.pdf ################################################################################ # # Generate the derived XML source from the original XML template. # This is done by simply running the original source through xmllint # with the --xinclude option to process all the xi:include elements. # The result of this could have just been piped into the XSLT processor, # except that (a) not all of the processors support input from stdin, # and (b) combining both xmllint and XSLT processing into one command # means that make won't stop if there's any errors from xmllint. # # Sed is used to add a comment to the derived XML file, warning that this # is generated and shouldn't be edited. Sed was used because the <?xml?> # processing instruction MUST be on the first line. The implication here # is that all input source files have an <?xml?> processing instruction # (which they should anyway). # $(DERIVED_XML): $(SOURCE_XML) $(XSLT_STYLESHEETS) @$(ANNOUNCE) "Generating $@" @$(XMLLINT) --xinclude $< >$@ @$(SED) -i -e '1a <!-- THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! -->' $@ ################################################################################ # # If any of the content files change, touch the XML template to # ensure that the document gets fully rebuilt. # $(SOURCE_XML): $(CONTENT_SRC) @$(TOUCH) $@ ################################################################################ # # Build the individual content files, etc., as necessary. Note above that # all the primary targets depend on the "content" target, _before_ # anything else. This ensures that the content gets rebuilt (if necessary) # before anything else happens. # # This may seem redundant, given that SOURCE_XML depends on CONTENT_SRC in # the rule above. However, this rule only works if we change one of the # actual content files. What if instead, we change a graphic associated # with one of the content files, without changing the content file itself? # In this case, make assumes that nothing needs to be done, because the # content file is older than the target, and this makefile knows nothing # about any dependencies that the content file might have (that's dealt # with by the makefile in the appropriate content directory). This is the # main downside of having independent makefiles. # # So, the slightly convoluted workaround using the empty "content" target # ensures that the content files will always be checked, regardless of # whether they've changed. If any of their prerequisites for a particular # content file change, then the content file itself will be touched, thus # activating the SOURCE_XML rule above. This process is particularly # important to ensure that associated graphics get rebuilt when they # change. # # All that aside, however, the _real_ trick is to ensure that this rule is # only executed once. If we do a "make", this rule would nominally get # executed four times (once for each of the targets that depend on # "content"). The first time through the rule, therefore, we create a # marker file called "content-checked". If this file exists, the rule # isn't executed. These marker files are cleaned up by a one-off find # command when the makefile is first run (see the include file # one-time-init.make). # # Note: using the wildcard function to test for the existence of the # marker file doesn't work when the makefile is run standalone, because # the function result is expanded at the time the makefile is _loaded_, # _before_ the one-time initialisation has a change to kick in and delete # the file. This has the rather bizarre side-effect of the makefile only # re-checking the content on every second run, and means that we can't use # make conditionals to control rule execution. The solution is to prefix # every command in the rule with "test ! -f" to check whether the marker # file exists. # # Ack! The tribulations of not using a monolithic makefile... # content: # Of course, there's little point in doing anything if there's no content! ifneq ($(strip $(CONTENT_SRC)),) @if $(TEST) ! -f content-checked; then \ $(ANNOUNCE) "Checking content for $(BASE_NAME)"; \ fi # Sanity check: do the content files referenced from the original source # actually exist? The "$(TRUE)" is included because there needs to # be something in the body of the if --- you can't just leave it empty. We # can use the wildcard function here because these files should already # exist --- if they don't, then by definition the filename is wrong! @if $(TEST) ! -f content-checked; then \ $(foreach f,$(CONTENT_SRC),$(if $(wildcard $f),,$(error Content file $f referenced from $(SOURCE_XML) does not exist)) $(TRUE);) \ fi # Remake each individual content file. @if $(TEST) ! -f content-checked; then \ $(foreach f,$(CONTENT_SRC),if $(MAKE) -C $(dir $f) $(notdir $f) BUILD_DIR=$(CURDIR); then $(TRUE); else exit 1; fi;) \ fi # Create the marker file so that this rule doesn't get executed again. @if $(TEST) ! -f content-checked; then \ $(TOUCH) content-checked; \ fi endif ################################################################################ # # 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. # # This checks each file in the build directory 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. # # I was going to do the testing using a target rule that dealt with # each file individually, but for some weird reason it would ignore any # additional files appended to the *_INSTALL_FILES variables. So I've done # it with a foreach instead, which _does_ work. (Ick, although ironically # the code is shorter.) # # !!! How do we get it to also install any extra files that we require # for a particular content file (e.g., the SQL code for Tutorial 3)? !!! # install-questions: questions @$(TEST) -d $(HANDBOOK_INSTALL_ROOT) @$(MKDIR_P) $(INSTALL_DIRECTORY) @$(foreach f,$(QUESTION_INSTALL_FILES),if $(TEST) ! -f $(INSTALL_DIRECTORY)/$(f) -o $(f) -nt $(INSTALL_DIRECTORY)/$(f); then $(ECHO) "Deploying $(f)"; $(CP) $(f) $(INSTALL_DIRECTORY); fi;) install-answers: answers @$(TEST) -d $(HANDBOOK_INSTALL_ROOT) @$(MKDIR_P) $(INSTALL_DIRECTORY) @$(foreach f,$(ANSWER_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. # clean: web-clean print-clean ifneq ($(strip $(ALL_CLEAN_FILES)),) -$(RM) -f $(ALL_CLEAN_FILES) endif web-clean: ifneq ($(strip $(WEB_CLEAN_FILES)),) -$(RM) -f $(WEB_CLEAN_FILES) endif print-clean: ifneq ($(strip $(PRINT_CLEAN_FILES)),) -$(RM) -f $(PRINT_CLEAN_FILES) endif ################################################################################ # # Debugging information, mostly lists of the generated variables. # debug: @$(ANNOUNCE) Externally defined variables @$(ECHO) "TEACHING_SHARED = [$(TEACHING_SHARED)]" @$(ECHO) "ALL_PAPERS_ROOT = [$(ALL_PAPERS_ROOT)]" @$(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) "SUBJECT_CODE = [$(SUBJECT_CODE)]" @$(ECHO) "PAPER_NUMBER = [$(PAPER_NUMBER)]" @$(ECHO) "PAPER_YEAR = [$(PAPER_YEAR)]" @$(ECHO) "PAPER_PERIOD = [$(PAPER_PERIOD)]" @$(ECHO) "PAPER_ROOT = [$(PAPER_ROOT)]" @$(ECHO) "HANDBOOK_ROOT = [$(HANDBOOK_ROOT)]" @$(ECHO) "SECTION = [$(SECTION)]" @$(ECHO) "BASE_NAME = [$(BASE_NAME)]" @$(ECHO) "SOURCE_XML = [$(SOURCE_XML)]" @$(ECHO) "DERIVED_XML = [$(DERIVED_XML)]" @$(ECHO) "WEB_QUESTIONS_HTML = [$(WEB_QUESTIONS_HTML)]" @$(ECHO) "WEB_ANSWERS_HTML = [$(WEB_ANSWERS_HTML)]" @$(ECHO) "PRINT_QUESTIONS_TEX = [$(PRINT_QUESTIONS_TEX)]" @$(ECHO) "PRINT_ANSWERS_TEX = [$(PRINT_ANSWERS_TEX)]" @$(ECHO) "PRINT_QUESTIONS_PDF_1UP = [$(PRINT_QUESTIONS_PDF_1UP)]" @$(ECHO) "PRINT_ANSWERS_PDF_1UP = [$(PRINT_ANSWERS_PDF_1UP)]" @$(ECHO) "PRINT_QUESTIONS_PDF_2UP = [$(PRINT_QUESTIONS_PDF_2UP)]" @$(ECHO) "PRINT_ANSWERS_PDF_2UP = [$(PRINT_ANSWERS_PDF_2UP)]" @$(ECHO) "DERIVED_WEB_FILES = [$(DERIVED_WEB_FILES)]" @$(ECHO) "DERIVED_PRINT_FILES = [$(DERIVED_PRINT_FILES)]" @$(ECHO) "XSLT_STYLESHEETS = [$(XSLT_STYLESHEETS)]" @$(ECHO) "CONTENT_SRC = [$(CONTENT_SRC)]" @$(ECHO) "INSTALL_DIRECTORY = [$(INSTALL_DIRECTORY)]" @$(ECHO) "QUESTION_INSTALL_FILES = [$(QUESTION_INSTALL_FILES)]" @$(ECHO) "ANSWER_INSTALL_FILES = [$(ANSWER_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)
################################################################################ # # File: $Id$ # # Standard variables and rules for building a particular document within a # section of the handbook (e.g., a single tutorial). Altering these # definitions will affect ALL DOCUMENT 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 ################################################################################ # # 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 ################################################################################ # # We make quite a lot of reference to files in the handbook directory, # so set a variable to point to it. PAPER_ROOT is defined in the include # file paper_variables.make. # HANDBOOK_ROOT:=$(PAPER_ROOT)/Handbook ################################################################################ # # Include XSLT functions. # include $(GLOBAL_HANDBOOK_INCLUDE)/xslt_functions.make ################################################################################ # # Defines which section we are currently building. This is actually the # path to the main folder for the section. Normally this is passed in as # an argument to make from a higher-level makefile (i.e., "make # SECTION=path/to/section"). # # Hmm, sh seems to convert uppercase letters in my paths to lowercase. # I'm not sure whether this will break anything or not... # # I _can_ confirm that having spaces anywhere in the parent path causes # serious breakage, because notdir returns bogus results in such cases. # All of the make functions assume whitespace delimitation, and there # doesn't seem to be any obvious way to work around this other than # eliminating spaces from the parent path (quoting the result of the # shell function below makes no difference). Fortunately, this is pretty # easy to do :) # # SECTION?=$(notdir $(shell cd ..; pwd)) ################################################################################ # # Set up the context for the current document. # # We use the same base name for both the directory and the document, which # makes life very easy :) # BASE_NAME:=$(notdir $(CURDIR)) # # SOURCE_XML is the original source XML, from which DERIVED_XML is # generated (the derived source has the includes for questions, etc., # inserted). # SOURCE_XML:=$(BASE_NAME).xml DERIVED_XML:=$(SOURCE_XML:.xml=-derived.xml) # # Define the names of the output files. # WEB_QUESTIONS_HTML:=$(BASE_NAME)-questions.html WEB_ANSWERS_HTML:=$(BASE_NAME)-answers.html PRINT_QUESTIONS_TEX:=$(WEB_QUESTIONS_HTML:.html=.tex) PRINT_ANSWERS_TEX:=$(WEB_ANSWERS_HTML:.html=.tex) PRINT_QUESTIONS_PDF_1UP:=$(PRINT_QUESTIONS_TEX:.tex=.pdf) PRINT_ANSWERS_PDF_1UP:=$(PRINT_ANSWERS_TEX:.tex=.pdf) PRINT_QUESTIONS_PDF_2UP:=$(PRINT_QUESTIONS_TEX:.tex=-2up.pdf) PRINT_ANSWERS_PDF_2UP:=$(PRINT_ANSWERS_TEX:.tex=-2up.pdf) # # Groupings of various web- and print-related files, for easy reference. # Feel free to add to these as necessary :) # DERIVED_WEB_FILES:=$(WEB_QUESTIONS_HTML) $(WEB_ANSWERS_HTML) DERIVED_PRINT_FILES:=$(PRINT_QUESTIONS_TEX) $(PRINT_ANSWERS_TEX) \ $(PRINT_QUESTIONS_PDF_1UP) $(PRINT_ANSWERS_PDF_1UP) \ $(PRINT_QUESTIONS_PDF_2UP) $(PRINT_ANSWERS_PDF_2UP) # # List of XSL stylesheets. If any of these change, we need to rebuild # everything. # # We can't use the resolver approach under Windows because of the DOS # pathnames. The style sheets come out of the resolver with paths like # C:\bar\foo\..., and make interprets the colon as an extra dependency # delimiter (tested and behaviour verified). Of course, this works fine on # any platform with sensible path standards. Quoting the value doesn't # help, unfortunately. Bugger :( # #XSLT_STYLESHEETS:=$(shell $(JAVA) org.apache.xml.resolver.apps.resolver -u file:///xml2html.xsl uri | ( $(GREP) 'Result: file:' || $(ECHO) '::xml2html.xsl' ) | $(CUT) -d':' -f3-) $(shell $(JAVA) org.apache.xml.resolver.apps.resolver -u file:///xml2latex.xsl uri | ( $(GREP) 'Result: file:' || $(ECHO) '::xml2latex.xsl' ) | $(CUT) -d':' -f3-) XSLT_STYLESHEETS:=$(TEACHING_SHARED)/Authoring/XML/xml2html.xsl $(TEACHING_SHARED)/Authoring/XML/xml2xhtml.xsl $(TEACHING_SHARED)/Authoring/XML/xml2latex.xsl $(TEACHING_SHARED)/Authoring/XML/xml2xelatex.xsl ################################################################################ # # Extract the list of included filenames from the source template. Hooray # for the shell function and Perl! Include file paths are found within the # href attributes of XML Include elements (<xi:include href="..." />). # All paths are relative to $(PAPER_ROOT). We don't use # $(PAPER_ROOT)/$(SECTION), because some of the include directories may be # in relatively arbitrary locations. # CONTENT_SRC:=$(shell $(PERL) -ne 'print "$(PAPER_ROOT)/$$2\n" if m{<xi:include .*href="(\.\./)*([^"]+)"};' $(SOURCE_XML)) ################################################################################ # # Directory to install files into on web server. # INSTALL_DIRECTORY:=$(HANDBOOK_INSTALL_ROOT)/$(SUBJECT_CODE)$(PAPER_NUMBER)/$(SECTION)/$(BASE_NAME) ################################################################################ # # Files to be installed on web server. # QUESTION_INSTALL_FILES:=$(WEB_QUESTIONS_HTML) $(PRINT_QUESTIONS_PDF_1UP) \ $(PRINT_QUESTIONS_PDF_2UP) $(wildcard *.png) ANSWER_INSTALL_FILES:=$(WEB_ANSWERS_HTML) $(PRINT_ANSWERS_PDF_1UP) \ $(PRINT_ANSWERS_PDF_2UP) $(wildcard *.png) ################################################################################ # # Lists of files for cleaning up. Add to these (using +=) as necessary in # derived makefiles. Note that ALL_CLEAN_FILES comprises files that need # to be deleted _in addition_ to those listed in WEB_CLEAN_FILES and # PRINT_CLEAN_FILES (that is, it's the list of additional files for the # "clean" target, which depends on "web-clean" and "print-clean" anyway). # WEB_CLEAN_FILES:=$(DERIVED_WEB_FILES) *-web*.png PRINT_CLEAN_FILES:=$(DERIVED_PRINT_FILES) *-print*.png *.pdf ALL_CLEAN_FILES:=$(DERIVED_XML) ################################################################################ # # List of possible targets. If you need to add to this for a specific # case, use TARGETS+=xxx in the actual makefile. # TARGETS:=all content targets debug install-questions install-answers \ web web-questions web-answers \ print print-questions print-answers \ questions answers \ 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. # web: web-questions web-answers web-questions: content $(WEB_QUESTIONS_HTML) $(WEB_QUESTIONS_HTML): $(DERIVED_XML) @$(ANNOUNCE) "Building $@ from $<" $(call xslt,$<,xml2html.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,period-code,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'no'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ web-answers: content $(WEB_ANSWERS_HTML) $(WEB_ANSWERS_HTML): $(DERIVED_XML) @$(ANNOUNCE) "Building $@ from $<" $(call xslt,$<,xml2html.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,period-code,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'no'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ ################################################################################ # # Build print version only. We add code to the LaTeX source to mark the # first and last pages of the document, so that an individual PDF for this # document can be generated later. \markfirstpage and \marklastpage are # macros defined in handbook_template.tex that write the current physical # page number to the .aux file. # print: print-questions print-answers print-questions: content $(PRINT_QUESTIONS_TEX) $(PRINT_QUESTIONS_TEX): $(DERIVED_XML) @$(ANNOUNCE) "Building $@ from $<" @$(ECHO) "\\markfirstpage{$(SECTION)/$(BASE_NAME)/$(@:.tex=.pdf)}" > $@ $(call xslt,$<,xml2latex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,period-code,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'no'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'sections/$(SECTION)/$(BASE_NAME)'),$(call xslt_parameter,image-format,'pdf')) >> $@ @$(ECHO) "\\marklastpage{$(SECTION)/$(BASE_NAME)/$(@:.tex=.pdf)}" >> $@ %-questions.pdf: %-questions.tex @$(ANNOUNCE) "Generating $@" @$(if $(wildcard $(HANDBOOK_ROOT)/handbook.pdf),,$(error $(HANDBOOK_ROOT)/handbook.pdf is missing)) @gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@ \ -dFirstPage=$(shell $(GREP) '$@.1up.first' $(HANDBOOK_ROOT)/handbook.aux | $(CUT) -d= -f2) \ -dLastPage=$(shell $(GREP) '$@.1up.last' $(HANDBOOK_ROOT)/handbook.aux | $(CUT) -d= -f2) $(HANDBOOK_ROOT)/handbook.pdf %-questions-2up.pdf: %-questions.tex @$(ANNOUNCE) "Generating $@" @$(if $(wildcard $(HANDBOOK_ROOT)/handbook-2up.pdf),,$(error $(HANDBOOK_ROOT)/handbook-2up.pdf is missing)) @gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@ \ -dFirstPage=$(shell $(GREP) '$(@:-2up.pdf=.pdf).2up.first' $(HANDBOOK_ROOT)/handbook.aux | $(CUT) -d= -f2) \ -dLastPage=$(shell $(GREP) '$(@:-2up.pdf=.pdf).2up.last' $(HANDBOOK_ROOT)/handbook.aux | $(CUT) -d= -f2) $(HANDBOOK_ROOT)/handbook-2up.pdf print-answers: content $(PRINT_ANSWERS_TEX) $(PRINT_ANSWERS_TEX): $(DERIVED_XML) @$(ANNOUNCE) "Building $@ from $<" @$(ECHO) "\\markfirstpage{$(SECTION)/$(BASE_NAME)/$(@:.tex=.pdf)}" > $@ $(call xslt,$<,xml2latex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,period-code,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'no'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'sections/$(SECTION)/$(BASE_NAME)'),$(call xslt_parameter,image-format,'pdf')) >> $@ @$(ECHO) "\\marklastpage{$(SECTION)/$(BASE_NAME)/$(@:.tex=.pdf)}" >> $@ %-answers.pdf: %-answers.tex @$(ANNOUNCE) "Generating $@" @$(if $(wildcard $(HANDBOOK_ROOT)/handbook-answers.pdf),,$(error $(HANDBOOK_ROOT)/handbook-answers.pdf is missing)) @gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@ \ -dFirstPage=$(shell $(GREP) '$@.1up.first' $(HANDBOOK_ROOT)/handbook-answers.aux | $(CUT) -d= -f2) \ -dLastPage=$(shell $(GREP) '$@.1up.last' $(HANDBOOK_ROOT)/handbook-answers.aux | $(CUT) -d= -f2) $(HANDBOOK_ROOT)/handbook-answers.pdf %-answers-2up.pdf: %-answers.tex @$(ANNOUNCE) "Generating $@" @$(if $(wildcard $(HANDBOOK_ROOT)/handbook-answers-2up.pdf),,$(error $(HANDBOOK_ROOT)/handbook-answers-2up.pdf is missing)) @gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=$@ \ -dFirstPage=$(shell $(GREP) '$(@:-2up.pdf=.pdf).2up.first' $(HANDBOOK_ROOT)/handbook-answers.aux | $(CUT) -d= -f2) \ -dLastPage=$(shell $(GREP) '$(@:-2up.pdf=.pdf).2up.last' $(HANDBOOK_ROOT)/handbook-answers.aux | $(CUT) -d= -f2) $(HANDBOOK_ROOT)/handbook-answers-2up.pdf ################################################################################ # # Generate the derived XML source from the original XML template. # This is done by simply running the original source through xmllint # with the --xinclude option to process all the xi:include elements. # The result of this could have just been piped into the XSLT processor, # except that (a) not all of the processors support input from stdin, # and (b) combining both xmllint and XSLT processing into one command # means that make won't stop if there's any errors from xmllint. # # Sed is used to add a comment to the derived XML file, warning that this # is generated and shouldn't be edited. Sed was used because the <?xml?> # processing instruction MUST be on the first line. The implication here # is that all input source files have an <?xml?> processing instruction # (which they should anyway). # $(DERIVED_XML): $(SOURCE_XML) $(XSLT_STYLESHEETS) @$(ANNOUNCE) "Generating $@" @$(XMLLINT) --xinclude $< >$@ @$(SED) -i -e '1a <!-- THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! -->' $@ ################################################################################ # # If any of the content files change, touch the XML template to # ensure that the document gets fully rebuilt. # $(SOURCE_XML): $(CONTENT_SRC) @$(TOUCH) $@ ################################################################################ # # Build the individual content files, etc., as necessary. Note above that # all the primary targets depend on the "content" target, _before_ # anything else. This ensures that the content gets rebuilt (if necessary) # before anything else happens. # # This may seem redundant, given that SOURCE_XML depends on CONTENT_SRC in # the rule above. However, this rule only works if we change one of the # actual content files. What if instead, we change a graphic associated # with one of the content files, without changing the content file itself? # In this case, make assumes that nothing needs to be done, because the # content file is older than the target, and this makefile knows nothing # about any dependencies that the content file might have (that's dealt # with by the makefile in the appropriate content directory). This is the # main downside of having independent makefiles. # # So, the slightly convoluted workaround using the empty "content" target # ensures that the content files will always be checked, regardless of # whether they've changed. If any of their prerequisites for a particular # content file change, then the content file itself will be touched, thus # activating the SOURCE_XML rule above. This process is particularly # important to ensure that associated graphics get rebuilt when they # change. # # All that aside, however, the _real_ trick is to ensure that this rule is # only executed once. If we do a "make", this rule would nominally get # executed four times (once for each of the targets that depend on # "content"). The first time through the rule, therefore, we create a # marker file called "content-checked". If this file exists, the rule # isn't executed. These marker files are cleaned up by a one-off find # command when the makefile is first run (see the include file # one-time-init.make). # # Note: using the wildcard function to test for the existence of the # marker file doesn't work when the makefile is run standalone, because # the function result is expanded at the time the makefile is _loaded_, # _before_ the one-time initialisation has a change to kick in and delete # the file. This has the rather bizarre side-effect of the makefile only # re-checking the content on every second run, and means that we can't use # make conditionals to control rule execution. The solution is to prefix # every command in the rule with "test ! -f" to check whether the marker # file exists. # # Ack! The tribulations of not using a monolithic makefile... # content: # Of course, there's little point in doing anything if there's no content! ifneq ($(strip $(CONTENT_SRC)),) @if $(TEST) ! -f content-checked; then \ $(ANNOUNCE) "Checking content for $(BASE_NAME)"; \ fi # Sanity check: do the content files referenced from the original source # actually exist? The "$(TRUE)" is included because there needs to # be something in the body of the if --- you can't just leave it empty. We # can use the wildcard function here because these files should already # exist --- if they don't, then by definition the filename is wrong! @if $(TEST) ! -f content-checked; then \ $(foreach f,$(CONTENT_SRC),$(if $(wildcard $f),,$(error Content file $f referenced from $(SOURCE_XML) does not exist)) $(TRUE);) \ fi # Remake each individual content file. @if $(TEST) ! -f content-checked; then \ $(foreach f,$(CONTENT_SRC),if $(MAKE) -C $(dir $f) $(notdir $f) BUILD_DIR=$(CURDIR); then $(TRUE); else exit 1; fi;) \ fi # Create the marker file so that this rule doesn't get executed again. @if $(TEST) ! -f content-checked; then \ $(TOUCH) content-checked; \ fi endif ################################################################################ # # Deploy the appropriate files into a shared folder, which is then synchronised # with Blackbaord. 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. # # This checks each file in the build directory 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. # # I was going to do the testing using a target rule that dealt with # each file individually, but for some weird reason it would ignore any # additional files appended to the *_INSTALL_FILES variables. So I've done # it with a foreach instead, which _does_ work. (Ick, although ironically # the code is shorter.) # # !!! How do we get it to also install any extra files that we require # for a particular content file (e.g., the SQL code for Tutorial 3)? !!! # install-questions: questions @$(TEST) -d $(HANDBOOK_INSTALL_ROOT) @$(MKDIR_P) $(INSTALL_DIRECTORY) @$(foreach f,$(QUESTION_INSTALL_FILES),if $(TEST) ! -f $(INSTALL_DIRECTORY)/$(f) -o $(f) -nt $(INSTALL_DIRECTORY)/$(f); then $(ECHO) "Deploying $(f)"; $(CP) $(f) $(INSTALL_DIRECTORY); fi;) install-answers: answers @$(TEST) -d $(HANDBOOK_INSTALL_ROOT) @$(MKDIR_P) $(INSTALL_DIRECTORY) @$(foreach f,$(ANSWER_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. # clean: web-clean print-clean ifneq ($(strip $(ALL_CLEAN_FILES)),) -$(RM) -f $(ALL_CLEAN_FILES) endif web-clean: ifneq ($(strip $(WEB_CLEAN_FILES)),) -$(RM) -f $(WEB_CLEAN_FILES) endif print-clean: ifneq ($(strip $(PRINT_CLEAN_FILES)),) -$(RM) -f $(PRINT_CLEAN_FILES) endif ################################################################################ # # Debugging information, mostly lists of the generated variables. # debug: @$(ANNOUNCE) Externally defined variables @$(ECHO) "TEACHING_SHARED = [$(TEACHING_SHARED)]" @$(ECHO) "ALL_PAPERS_ROOT = [$(ALL_PAPERS_ROOT)]" @$(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) "SUBJECT_CODE = [$(SUBJECT_CODE)]" @$(ECHO) "PAPER_NUMBER = [$(PAPER_NUMBER)]" @$(ECHO) "PAPER_YEAR = [$(PAPER_YEAR)]" @$(ECHO) "PAPER_PERIOD = [$(PAPER_PERIOD)]" @$(ECHO) "PAPER_ROOT = [$(PAPER_ROOT)]" @$(ECHO) "HANDBOOK_ROOT = [$(HANDBOOK_ROOT)]" @$(ECHO) "SECTION = [$(SECTION)]" @$(ECHO) "BASE_NAME = [$(BASE_NAME)]" @$(ECHO) "SOURCE_XML = [$(SOURCE_XML)]" @$(ECHO) "DERIVED_XML = [$(DERIVED_XML)]" @$(ECHO) "WEB_QUESTIONS_HTML = [$(WEB_QUESTIONS_HTML)]" @$(ECHO) "WEB_ANSWERS_HTML = [$(WEB_ANSWERS_HTML)]" @$(ECHO) "PRINT_QUESTIONS_TEX = [$(PRINT_QUESTIONS_TEX)]" @$(ECHO) "PRINT_ANSWERS_TEX = [$(PRINT_ANSWERS_TEX)]" @$(ECHO) "PRINT_QUESTIONS_PDF_1UP = [$(PRINT_QUESTIONS_PDF_1UP)]" @$(ECHO) "PRINT_ANSWERS_PDF_1UP = [$(PRINT_ANSWERS_PDF_1UP)]" @$(ECHO) "PRINT_QUESTIONS_PDF_2UP = [$(PRINT_QUESTIONS_PDF_2UP)]" @$(ECHO) "PRINT_ANSWERS_PDF_2UP = [$(PRINT_ANSWERS_PDF_2UP)]" @$(ECHO) "DERIVED_WEB_FILES = [$(DERIVED_WEB_FILES)]" @$(ECHO) "DERIVED_PRINT_FILES = [$(DERIVED_PRINT_FILES)]" @$(ECHO) "XSLT_STYLESHEETS = [$(XSLT_STYLESHEETS)]" @$(ECHO) "CONTENT_SRC = [$(CONTENT_SRC)]" @$(ECHO) "INSTALL_DIRECTORY = [$(INSTALL_DIRECTORY)]" @$(ECHO) "QUESTION_INSTALL_FILES = [$(QUESTION_INSTALL_FILES)]" @$(ECHO) "ANSWER_INSTALL_FILES = [$(ANSWER_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)
Ignore Space
Show notes
View
make-includes/build_misc_rules.make
################################################################################ # # File: $Id$ # # Standard variables and rules for building a general standalone document # that doesn't fall into any partcular category (such as lecture, tutorial). # The makefile assumes a single document source file. Anything more # complex than this will need to be handled by a custom makefile. # # Altering these definitions will affect ALL 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! # ################################################################################ ################################################################################ # # Include XSLT functions. # include $(TEACHING_SHARED)/Authoring/Handbook/make-includes/xslt_functions.make ################################################################################ # # Required make variables. These should be defined by the calling makefile. # # BASE_NAMES # The base name(s) of the document source file(s). It may be a list, which # enables multiple different documents to be built by the one Makefile. # BASE_NAMES?=$(error The required make variable BASE_NAMES has not been defined. Please set it to the base name(s) of the document source file(s)) ################################################################################ # # Set up the context for the current document. # # SOURCE_XML is the original source XML, from which DERIVED_XML is # generated (the derived source has the includes for questions, etc., # inserted). # SOURCE_XML:=$(foreach n,$(BASE_NAMES),$(n).xml) DERIVED_XML:=$(SOURCE_XML:.xml=-derived.xml) # # Define the names of the output files. # ifdef HAS_ANSWERS WEB_QUESTIONS_HTML:=$(SOURCE_XML:.xml=-questions.html) WEB_ANSWERS_HTML:=$(SOURCE_XML:.xml=-answers.html) PRINT_QUESTIONS_TEX:=$(WEB_QUESTIONS_HTML:.html=.tex) PRINT_ANSWERS_TEX:=$(WEB_ANSWERS_HTML:.html=.tex) PRINT_QUESTIONS_PDF_1UP:=$(PRINT_QUESTIONS_TEX:.tex=.pdf) PRINT_ANSWERS_PDF_1UP:=$(PRINT_ANSWERS_TEX:.tex=.pdf) PRINT_QUESTIONS_PDF_2UP:=$(PRINT_QUESTIONS_TEX:.tex=-2up.pdf) PRINT_ANSWERS_PDF_2UP:=$(PRINT_ANSWERS_TEX:.tex=-2up.pdf) else WEB_HTML:=$(SOURCE_XML:.xml=.html) PRINT_TEX:=$(SOURCE_XML:.xml=.tex) PRINT_PDF_1UP:=$(SOURCE_XML:.xml=.pdf) PRINT_PDF_2UP:=$(SOURCE_XML:.xml=-2up.pdf) endif # # List of XSL stylesheets. If any of these change, we need to rebuild # everything. # # We can't use the resolver approach under Windows because of the DOS # pathnames. The style sheets come out of the resolver with paths like # C:\bar\foo\..., and make interprets the colon as an extra dependency # delimiter (tested and behaviour verified). Of course, this works fine on # any platform with sensible path standards. Quoting the value doesn't # help, unfortunately. Bugger :( # #XSLT_STYLESHEETS:=$(shell $(JAVA) org.apache.xml.resolver.apps.resolver -u file:///xml2html.xsl uri | ( $(GREP) 'Result: file:' || $(ECHO) '::xml2html.xsl' ) | $(CUT) -d':' -f3-) $(shell $(JAVA) org.apache.xml.resolver.apps.resolver -u file:///xml2latex.xsl uri | ( $(GREP) 'Result: file:' || $(ECHO) '::xml2latex.xsl' ) | $(CUT) -d':' -f3-) XSLT_STYLESHEETS:=$(TEACHING_SHARED)/Authoring/XML/xml2html.xsl $(TEACHING_SHARED)/Authoring/XML/xml2xhtml.xsl $(TEACHING_SHARED)/Authoring/XML/xml2latex.xsl $(TEACHING_SHARED)/Authoring/XML/xml2xelatex.xsl ################################################################################ # # Add standard file suffixes. # include $(GLOBAL_HANDBOOK_INCLUDE)/standard_suffixes.make ################################################################################ # # Standard directories. # IMGDIR=images ################################################################################ # # Standard paths. # include $(GLOBAL_HANDBOOK_INCLUDE)/standard_paths.make ################################################################################ # # Files to be installed on web server. # ifdef HAS_ANSWERS QUESTION_INSTALL_FILES:=$(WEB_QUESTIONS_HTML) $(PRINT_QUESTIONS_PDF_1UP) \ $(PRINT_QUESTIONS_PDF_2UP) ANSWER_INSTALL_FILES:=$(WEB_ANSWERS_HTML) $(PRINT_ANSWERS_PDF_1UP) \ $(PRINT_ANSWERS_PDF_2UP) else INSTALL_FILES:=$(WEB_HTML) $(PRINT_PDF_1UP) $(PRINT_PDF_2UP) endif ################################################################################ # # Files to be cleaned by the various "clean" targets. Note that we don't # "tidy" .aux files because they may be needed by the xr package for inter- # document cross references, but won't get regenerated if the final target # PDF files exist. They will be caught by by the "clean" target though. # TIDY_FILES+=*.tmp *.out *.log *.nav *.toc *.snm *.head *.dvi *-derived.xml CLEAN_FILES+=*.aux $(IMGDIR)/*-print.pdf $(IMGDIR)/*-print.png \ $(IMGDIR)/*-web.png $(IMGDIR)/*-web-zoom.png ifdef HAS_ANSWERS TIDY_FILES+=$(PRINT_QUESTIONS_TEX) $(PRINT_ANSWERS_TEX) CLEAN_FILES+=$(WEB_QUESTIONS_HTML) $(WEB_ANSWERS_HTML) \ $(PRINT_QUESTIONS_PDF_1UP) $(PRINT_ANSWERS_PDF_1UP) \ $(PRINT_QUESTIONS_PDF_2UP) $(PRINT_ANSWERS_PDF_2UP) else TIDY_FILES+=$(PRINT_TEX) CLEAN_FILES+=$(WEB_HTML) $(PRINT_PDF_1UP) $(PRINT_PDF_2UP) endif ################################################################################ # # Various environment variables. # include $(GLOBAL_HANDBOOK_INCLUDE)/standard_environment.make # # List of standard "phony" build targets. Varies depending on whether # answers are enabled. # TARGETS+=web print $(BASE_NAMES) ifdef HAS_ANSWERS TARGETS+=web-questions web-answers \ print-questions print-answers \ questions answers endif # .PHONY: $(TARGETS) ################################################################################ # # Build everything. # all: web print ################################################################################ # # Build questions or answers only. # ifdef HAS_ANSWERS questions: web-questions print-questions answers: web-answers print-answers endif ################################################################################ # # Build web version only. # ifdef HAS_ANSWERS web: web-questions web-answers web-questions: $(WEB_QUESTIONS_HTML) $(WEB_IMAGES) $(WEB_FILES) $(WEB_QUESTIONS_HTML): %-questions.html: %-derived.xml ifdef UNICODE $(call xslt,$<,xml2xhtml.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ else $(call xslt,$<,xml2html.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ endif web-answers: $(WEB_ANSWERS_HTML) $(WEB_IMAGES) $(WEB_FILES) $(WEB_ANSWERS_HTML): %-answers.html: %-derived.xml ifdef UNICODE $(call xslt,$<,xml2xhtml.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ else $(call xslt,$<,xml2html.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ endif else web: $(WEB_HTML) $(WEB_IMAGES) $(WEB_FILES) endif ################################################################################ # # Build print version only. # ifdef HAS_ANSWERS print: print-questions print-answers print-questions: $(PRINT_QUESTIONS_PDF_1UP) $(PRINT_QUESTIONS_PDF_2UP) $(PRINT_QUESTIONS_PDF_1UP): $(PRINT_IMAGES) $(PRINT_FILES) $(PRINT_QUESTIONS_TEX): %-questions.tex: %-derived.xml ifdef UNICODE $(call xslt,$<,xml2xelatex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'pdf')) > $@ else $(call xslt,$<,xml2latex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'pdf')) > $@ endif print-answers: $(PRINT_ANSWERS_PDF_1UP) $(PRINT_ANSWERS_PDF_2UP) $(PRINT_ANSWERS_PDF_1UP): $(PRINT_IMAGES) $(PRINT_FILES) $(PRINT_ANSWERS_TEX): %-answers.tex: %-derived.xml ifdef UNICODE $(call xslt,$<,xml2xelatex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'pdf')) > $@ else $(call xslt,$<,xml2latex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'pdf')) > $@ endif else print: $(PRINT_PDF_1UP) $(PRINT_PDF_2UP) $(PRINT_PDF_1UP): $(PRINT_IMAGES) $(PRINT_FILES) endif ################################################################################ # # Generate the derived XML source from the original XML template. # This is done by simply running the original source through xmllint # with the --xinclude option to process all the xi:include elements. # The result of this could have just been piped into the XSLT processor, # except that (a) not all of the processors support input from stdin, # and (b) combining both xmllint and XSLT processing into one command # means that make won't stop if there's any errors from xmllint. # # Sed is used to add a comment to the derived XML file, warning that this # is generated and shouldn't be edited. Sed was used because the <?xml?> # processing instruction MUST be on the first line. The implication here # is that all input source files have an <?xml?> processing instruction # (which they should anyway). # $(DERIVED_XML): %-derived.xml: %.xml $(XSLT_STYLESHEETS) $(XMLLINT) --xinclude $< >$@ @$(SED) -i -e '1a <!-- THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! -->' $@ ################################################################################ # # Build the test document. # test: test.pdf test.pdf: test.tex ################################################################################ # # 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. # # See build_document_rules.make for an explanation of why the install # uses a foreach. # # Note that this won't do anything clever if you give it files that are # in subdirectories of the current directory. Everything will be flattened # at the other end. That is, something like "images/foo.pdf" will go into # the installation directory as "foo.pdf", not "images/foo.pdf". # install: all @$(ANNOUNCE) "Deploying files into $(INSTALL_DIRECTORY)" @$(TEST) -d $(HANDBOOK_INSTALL_ROOT) @$(MKDIR_P) $(INSTALL_DIRECTORY) @if $(TEST) -n "$(WEB_IMAGES)"; then $(MKDIR_P) $(INSTALL_DIRECTORY)/$(IMGDIR); fi ifdef HAS_ANSWERS @$(foreach f,$(QUESTION_INSTALL_FILES) $(ANSWER_INSTALL_FILES),if $(TEST) ! -f $(INSTALL_DIRECTORY)/$(f) -o $(f) -nt $(INSTALL_DIRECTORY)/$(f); then $(ECHO) "Deploying $(f)"; $(CP) $(f) $(INSTALL_DIRECTORY); fi;) else @$(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;) endif @$(foreach f,$(WEB_IMAGES),if $(TEST) ! -f $(INSTALL_DIRECTORY)/$(IMGDIR)/$(f) -o $(IMGDIR)/$(f) -nt $(INSTALL_DIRECTORY)/$(IMGDIR)/$(f); then $(ECHO) "Deploying $(IMGDIR)/$(f)"; $(CP) $(IMGDIR)/$(f) $(INSTALL_DIRECTORY)/$(IMGDIR); fi;) @$(ANNOUNCE) "Synchronising with Blackboard" @$(SITECOPY) --update Blackboard$(PAPER_NUMBER) ################################################################################ # # Debugging: print the values of the standard variables. # debug: @announce Externally defined variables @echo "TEACHING_SHARED = [$(TEACHING_SHARED)]" @announce Internally defined variables @echo "GLOBAL_HANDBOOK_INCLUDE = [$(GLOBAL_HANDBOOK_INCLUDE)]" @echo "BASE_NAMES = [$(BASE_NAMES)]" @echo "SOURCE_XML = [$(SOURCE_XML)]" @echo "DERIVED_XML = [$(DERIVED_XML)]" @echo "SUBJECT_CODE = [$(SUBJECT_CODE)]" @echo "PAPER_NUMBER = [$(PAPER_NUMBER)]" @echo "HAS_ANSWERS = [$(HAS_ANSWERS)]" ifdef HAS_ANSWERS @echo "WEB_QUESTIONS_HTML = [$(WEB_QUESTIONS_HTML)]" @echo "WEB_ANSWERS_HTML = [$(WEB_ANSWERS_HTML)]" @echo "PRINT_QUESTIONS_TEX = [$(PRINT_QUESTIONS_TEX)]" @echo "PRINT_ANSWERS_TEX = [$(PRINT_ANSWERS_TEX)]" @echo "PRINT_QUESTIONS_PDF_1UP = [$(PRINT_QUESTIONS_PDF_1UP)]" @echo "PRINT_ANSWERS_PDF_1UP = [$(PRINT_ANSWERS_PDF_1UP)]" @echo "PRINT_QUESTIONS_PDF_2UP = [$(PRINT_QUESTIONS_PDF_2UP)]" @echo "PRINT_ANSWERS_PDF_2UP = [$(PRINT_ANSWERS_PDF_2UP)]" @echo "QUESTION_INSTALL_FILES = [$(QUESTION_INSTALL_FILES)]" @echo "ANSWER_INSTALL_FILES = [$(ANSWER_INSTALL_FILES)]" else @echo "WEB_HTML = [$(WEB_HTML)]" @echo "PRINT_TEX = [$(PRINT_TEX)]" @echo "PRINT_PDF_1UP = [$(PRINT_PDF_1UP)]" @echo "PRINT_PDF_2UP = [$(PRINT_PDF_2UP)]" @echo "INSTALL_FILES = [$(INSTALL_FILES)]" endif @echo "XSLT_STYLESHEETS = [$(XSLT_STYLESHEETS)]" @echo "PRINT_IMAGES = [$(PRINT_IMAGES)]" @echo "PRINT_FILES = [$(PRINT_FILES)]" @echo "WEB_IMAGES = [$(WEB_IMAGES)]" @echo "WEB_FILES = [$(WEB_FILES)]" @echo "TIDY_FILES = [$(TIDY_FILES)]" @echo "CLEAN_FILES = [$(CLEAN_FILES)]" @echo "DRAFT = [$(DRAFT)]" @echo "LATEX_OPTS = [$(LATEX_OPTS)]" @echo "TARGETS = [$(TARGETS)]" ################################################################################ # # Clean up: get rid of all the temporary files. # tidy: $(RM) -f $(TIDY_FILES) # # Clean up: get rid of everything except the original source. # clean: tidy $(RM) -f $(CLEAN_FILES) ################################################################################ # # List all "phony" build targets. # targets: @echo "targets: $(TARGETS)" ################################################################################ # # Standard default rules. # include $(GLOBAL_HANDBOOK_INCLUDE)/standard_rules.make
################################################################################ # # File: $Id$ # # Standard variables and rules for building a general standalone document # that doesn't fall into any partcular category (such as lecture, tutorial). # The makefile assumes a single document source file. Anything more # complex than this will need to be handled by a custom makefile. # # Altering these definitions will affect ALL 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! # ################################################################################ ################################################################################ # # Include XSLT functions. # include $(TEACHING_SHARED)/Authoring/Handbook/make-includes/xslt_functions.make ################################################################################ # # Required make variables. These should be defined by the calling makefile. # # BASE_NAMES # The base name(s) of the document source file(s). It may be a list, which # enables multiple different documents to be built by the one Makefile. # BASE_NAMES?=$(error The required make variable BASE_NAMES has not been defined. Please set it to the base name(s) of the document source file(s)) ################################################################################ # # Set up the context for the current document. # # SOURCE_XML is the original source XML, from which DERIVED_XML is # generated (the derived source has the includes for questions, etc., # inserted). # SOURCE_XML:=$(foreach n,$(BASE_NAMES),$(n).xml) DERIVED_XML:=$(SOURCE_XML:.xml=-derived.xml) # # Define the names of the output files. # ifdef HAS_ANSWERS WEB_QUESTIONS_HTML:=$(SOURCE_XML:.xml=-questions.html) WEB_ANSWERS_HTML:=$(SOURCE_XML:.xml=-answers.html) PRINT_QUESTIONS_TEX:=$(WEB_QUESTIONS_HTML:.html=.tex) PRINT_ANSWERS_TEX:=$(WEB_ANSWERS_HTML:.html=.tex) PRINT_QUESTIONS_PDF_1UP:=$(PRINT_QUESTIONS_TEX:.tex=.pdf) PRINT_ANSWERS_PDF_1UP:=$(PRINT_ANSWERS_TEX:.tex=.pdf) PRINT_QUESTIONS_PDF_2UP:=$(PRINT_QUESTIONS_TEX:.tex=-2up.pdf) PRINT_ANSWERS_PDF_2UP:=$(PRINT_ANSWERS_TEX:.tex=-2up.pdf) else WEB_HTML:=$(SOURCE_XML:.xml=.html) PRINT_TEX:=$(SOURCE_XML:.xml=.tex) PRINT_PDF_1UP:=$(SOURCE_XML:.xml=.pdf) PRINT_PDF_2UP:=$(SOURCE_XML:.xml=-2up.pdf) endif # # List of XSL stylesheets. If any of these change, we need to rebuild # everything. # # We can't use the resolver approach under Windows because of the DOS # pathnames. The style sheets come out of the resolver with paths like # C:\bar\foo\..., and make interprets the colon as an extra dependency # delimiter (tested and behaviour verified). Of course, this works fine on # any platform with sensible path standards. Quoting the value doesn't # help, unfortunately. Bugger :( # #XSLT_STYLESHEETS:=$(shell $(JAVA) org.apache.xml.resolver.apps.resolver -u file:///xml2html.xsl uri | ( $(GREP) 'Result: file:' || $(ECHO) '::xml2html.xsl' ) | $(CUT) -d':' -f3-) $(shell $(JAVA) org.apache.xml.resolver.apps.resolver -u file:///xml2latex.xsl uri | ( $(GREP) 'Result: file:' || $(ECHO) '::xml2latex.xsl' ) | $(CUT) -d':' -f3-) XSLT_STYLESHEETS:=$(TEACHING_SHARED)/Authoring/XML/xml2html.xsl $(TEACHING_SHARED)/Authoring/XML/xml2xhtml.xsl $(TEACHING_SHARED)/Authoring/XML/xml2latex.xsl $(TEACHING_SHARED)/Authoring/XML/xml2xelatex.xsl ################################################################################ # # Add standard file suffixes. # include $(GLOBAL_HANDBOOK_INCLUDE)/standard_suffixes.make ################################################################################ # # Standard directories. # IMGDIR=images ################################################################################ # # Standard paths. # include $(GLOBAL_HANDBOOK_INCLUDE)/standard_paths.make ################################################################################ # # Files to be installed on web server. # ifdef HAS_ANSWERS QUESTION_INSTALL_FILES:=$(WEB_QUESTIONS_HTML) $(PRINT_QUESTIONS_PDF_1UP) \ $(PRINT_QUESTIONS_PDF_2UP) ANSWER_INSTALL_FILES:=$(WEB_ANSWERS_HTML) $(PRINT_ANSWERS_PDF_1UP) \ $(PRINT_ANSWERS_PDF_2UP) else INSTALL_FILES:=$(WEB_HTML) $(PRINT_PDF_1UP) $(PRINT_PDF_2UP) endif ################################################################################ # # Files to be cleaned by the various "clean" targets. Note that we don't # "tidy" .aux files because they may be needed by the xr package for inter- # document cross references, but won't get regenerated if the final target # PDF files exist. They will be caught by by the "clean" target though. # TIDY_FILES+=*.tmp *.out *.log *.nav *.toc *.snm *.head *.dvi *-derived.xml CLEAN_FILES+=*.aux $(IMGDIR)/*-print.pdf $(IMGDIR)/*-print.png \ $(IMGDIR)/*-web.png $(IMGDIR)/*-web-zoom.png ifdef HAS_ANSWERS TIDY_FILES+=$(PRINT_QUESTIONS_TEX) $(PRINT_ANSWERS_TEX) CLEAN_FILES+=$(WEB_QUESTIONS_HTML) $(WEB_ANSWERS_HTML) \ $(PRINT_QUESTIONS_PDF_1UP) $(PRINT_ANSWERS_PDF_1UP) \ $(PRINT_QUESTIONS_PDF_2UP) $(PRINT_ANSWERS_PDF_2UP) else TIDY_FILES+=$(PRINT_TEX) CLEAN_FILES+=$(WEB_HTML) $(PRINT_PDF_1UP) $(PRINT_PDF_2UP) endif ################################################################################ # # Various environment variables. # include $(GLOBAL_HANDBOOK_INCLUDE)/standard_environment.make # # List of standard "phony" build targets. Varies depending on whether # answers are enabled. # TARGETS+=web print $(BASE_NAMES) ifdef HAS_ANSWERS TARGETS+=web-questions web-answers \ print-questions print-answers \ questions answers endif # .PHONY: $(TARGETS) ################################################################################ # # Build everything. # all: web print ################################################################################ # # Build questions or answers only. # ifdef HAS_ANSWERS questions: web-questions print-questions answers: web-answers print-answers endif ################################################################################ # # Build web version only. # ifdef HAS_ANSWERS web: web-questions web-answers web-questions: $(WEB_QUESTIONS_HTML) $(WEB_IMAGES) $(WEB_FILES) $(WEB_QUESTIONS_HTML): %-questions.html: %-derived.xml ifdef UNICODE $(call xslt,$<,xml2xhtml.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ else $(call xslt,$<,xml2html.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ endif web-answers: $(WEB_ANSWERS_HTML) $(WEB_IMAGES) $(WEB_FILES) $(WEB_ANSWERS_HTML): %-answers.html: %-derived.xml ifdef UNICODE $(call xslt,$<,xml2xhtml.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ else $(call xslt,$<,xml2html.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'png')) > $@ endif else web: $(WEB_HTML) $(WEB_IMAGES) $(WEB_FILES) endif ################################################################################ # # Build print version only. # ifdef HAS_ANSWERS print: print-questions print-answers print-questions: $(PRINT_QUESTIONS_PDF_1UP) $(PRINT_QUESTIONS_PDF_2UP) $(PRINT_QUESTIONS_PDF_1UP): $(PRINT_IMAGES) $(PRINT_FILES) $(PRINT_QUESTIONS_TEX): %-questions.tex: %-derived.xml ifdef UNICODE $(call xslt,$<,xml2xelatex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'pdf')) > $@ else $(call xslt,$<,xml2latex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'no'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'pdf')) > $@ endif print-answers: $(PRINT_ANSWERS_PDF_1UP) $(PRINT_ANSWERS_PDF_2UP) $(PRINT_ANSWERS_PDF_1UP): $(PRINT_IMAGES) $(PRINT_FILES) $(PRINT_ANSWERS_TEX): %-answers.tex: %-derived.xml ifdef UNICODE $(call xslt,$<,xml2xelatex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'pdf')) > $@ else $(call xslt,$<,xml2latex.xsl,$(call xslt_parameter,subject-code,'$(SUBJECT_CODE)'),$(call xslt_parameter,paper-number,'$(PAPER_NUMBER)'),$(call xslt_parameter,paper-year,'$(PAPER_YEAR)'),$(call xslt_parameter,paper-period,'$(PAPER_PERIOD)'),$(call xslt_parameter,standalone,'yes'),$(call xslt_parameter,showanswers,'yes'),$(call xslt_parameter,base-path,'.'),$(call xslt_parameter,image-format,'pdf')) > $@ endif else print: $(PRINT_PDF_1UP) $(PRINT_PDF_2UP) $(PRINT_PDF_1UP): $(PRINT_IMAGES) $(PRINT_FILES) endif ################################################################################ # # Generate the derived XML source from the original XML template. # This is done by simply running the original source through xmllint # with the --xinclude option to process all the xi:include elements. # The result of this could have just been piped into the XSLT processor, # except that (a) not all of the processors support input from stdin, # and (b) combining both xmllint and XSLT processing into one command # means that make won't stop if there's any errors from xmllint. # # Sed is used to add a comment to the derived XML file, warning that this # is generated and shouldn't be edited. Sed was used because the <?xml?> # processing instruction MUST be on the first line. The implication here # is that all input source files have an <?xml?> processing instruction # (which they should anyway). # $(DERIVED_XML): %-derived.xml: %.xml $(XSLT_STYLESHEETS) $(XMLLINT) --xinclude $< >$@ @$(SED) -i -e '1a <!-- THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! -->' $@ ################################################################################ # # Build the test document. # test: test.pdf test.pdf: test.tex ################################################################################ # # Deploy the appropriate files into a shared folder, which is then synchronised # with Blackbaord. 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. # # See build_document_rules.make for an explanation of why the install # uses a foreach. # # Note that this won't do anything clever if you give it files that are # in subdirectories of the current directory. Everything will be flattened # at the other end. That is, something like "images/foo.pdf" will go into # the installation directory as "foo.pdf", not "images/foo.pdf". # install: all @$(ANNOUNCE) "Deploying files into $(INSTALL_DIRECTORY)" @$(TEST) -d $(HANDBOOK_INSTALL_ROOT) @$(MKDIR_P) $(INSTALL_DIRECTORY) @if $(TEST) -n "$(WEB_IMAGES)"; then $(MKDIR_P) $(INSTALL_DIRECTORY)/$(IMGDIR); fi ifdef HAS_ANSWERS @$(foreach f,$(QUESTION_INSTALL_FILES) $(ANSWER_INSTALL_FILES),if $(TEST) ! -f $(INSTALL_DIRECTORY)/$(f) -o $(f) -nt $(INSTALL_DIRECTORY)/$(f); then $(ECHO) "Deploying $(f)"; $(CP) $(f) $(INSTALL_DIRECTORY); fi;) else @$(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;) endif @$(foreach f,$(WEB_IMAGES),if $(TEST) ! -f $(INSTALL_DIRECTORY)/$(IMGDIR)/$(f) -o $(IMGDIR)/$(f) -nt $(INSTALL_DIRECTORY)/$(IMGDIR)/$(f); then $(ECHO) "Deploying $(IMGDIR)/$(f)"; $(CP) $(IMGDIR)/$(f) $(INSTALL_DIRECTORY)/$(IMGDIR); fi;) @$(ANNOUNCE) "Synchronising with Blackboard" @$(SITECOPY) --update Blackboard$(PAPER_NUMBER) ################################################################################ # # Debugging: print the values of the standard variables. # debug: @announce Externally defined variables @echo "TEACHING_SHARED = [$(TEACHING_SHARED)]" @announce Internally defined variables @echo "GLOBAL_HANDBOOK_INCLUDE = [$(GLOBAL_HANDBOOK_INCLUDE)]" @echo "BASE_NAMES = [$(BASE_NAMES)]" @echo "SOURCE_XML = [$(SOURCE_XML)]" @echo "DERIVED_XML = [$(DERIVED_XML)]" @echo "SUBJECT_CODE = [$(SUBJECT_CODE)]" @echo "PAPER_NUMBER = [$(PAPER_NUMBER)]" @echo "HAS_ANSWERS = [$(HAS_ANSWERS)]" ifdef HAS_ANSWERS @echo "WEB_QUESTIONS_HTML = [$(WEB_QUESTIONS_HTML)]" @echo "WEB_ANSWERS_HTML = [$(WEB_ANSWERS_HTML)]" @echo "PRINT_QUESTIONS_TEX = [$(PRINT_QUESTIONS_TEX)]" @echo "PRINT_ANSWERS_TEX = [$(PRINT_ANSWERS_TEX)]" @echo "PRINT_QUESTIONS_PDF_1UP = [$(PRINT_QUESTIONS_PDF_1UP)]" @echo "PRINT_ANSWERS_PDF_1UP = [$(PRINT_ANSWERS_PDF_1UP)]" @echo "PRINT_QUESTIONS_PDF_2UP = [$(PRINT_QUESTIONS_PDF_2UP)]" @echo "PRINT_ANSWERS_PDF_2UP = [$(PRINT_ANSWERS_PDF_2UP)]" @echo "QUESTION_INSTALL_FILES = [$(QUESTION_INSTALL_FILES)]" @echo "ANSWER_INSTALL_FILES = [$(ANSWER_INSTALL_FILES)]" else @echo "WEB_HTML = [$(WEB_HTML)]" @echo "PRINT_TEX = [$(PRINT_TEX)]" @echo "PRINT_PDF_1UP = [$(PRINT_PDF_1UP)]" @echo "PRINT_PDF_2UP = [$(PRINT_PDF_2UP)]" @echo "INSTALL_FILES = [$(INSTALL_FILES)]" endif @echo "XSLT_STYLESHEETS = [$(XSLT_STYLESHEETS)]" @echo "PRINT_IMAGES = [$(PRINT_IMAGES)]" @echo "PRINT_FILES = [$(PRINT_FILES)]" @echo "WEB_IMAGES = [$(WEB_IMAGES)]" @echo "WEB_FILES = [$(WEB_FILES)]" @echo "TIDY_FILES = [$(TIDY_FILES)]" @echo "CLEAN_FILES = [$(CLEAN_FILES)]" @echo "DRAFT = [$(DRAFT)]" @echo "LATEX_OPTS = [$(LATEX_OPTS)]" @echo "TARGETS = [$(TARGETS)]" ################################################################################ # # Clean up: get rid of all the temporary files. # tidy: $(RM) -f $(TIDY_FILES) # # Clean up: get rid of everything except the original source. # clean: tidy $(RM) -f $(CLEAN_FILES) ################################################################################ # # List all "phony" build targets. # targets: @echo "targets: $(TARGETS)" ################################################################################ # # Standard default rules. # include $(GLOBAL_HANDBOOK_INCLUDE)/standard_rules.make
Ignore Space
Show notes
View
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 # # 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)
################################################################################ # # 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 # # 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 Blackbaord. 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)
Show line notes below