... Martin Ohlerich, Martin.Ohlerich@lrz.de Parallel Programming of High Performance Systems
Outline 1 2 3 Leibniz Rechenzentrum 2 / 42
Outline 1 2 3 Leibniz Rechenzentrum 3 / 42
Common Situation Larger software project: many developers, many files, maybe different languages,... Questions Solution How to automate build process? Build only necessary parts during development? Different build options (Debug, Release, Hardware Optimization,...) : c, autotools base on it Leibniz Rechenzentrum 4 / 42
First Example Typical Situation prog-path include src Makefile main.cxx $ ls -F include/ Makefile src/ $ g++ -o prog src/main.cxx Goal Create executable prog! Makefile.PHONY: clean prog: src/main.cxx TAB g++ -o prog src/main.cxx clean: TAB @rm -rf prog $ ls -F prog* include/ Makefile src/ $ clean Leibniz Rechenzentrum 5 / 42
Getting help: $ -h... Get version: $ -v GNU Make 4.0... GNUfile, file or Makefile in current directory: $ g++ -O3 -I./include -o src/file1.o src/file1.cxx... Leibniz Rechenzentrum 6 / 42
Makefile with different name (mymakefile): $ -f mymakefile... Parallel resources available: $ -j 20... Different target (like clean above): $ clean... Leibniz Rechenzentrum 7 / 42
Set some variable(s) used inside the Makefile: $ VAR=2... Call from a different directory: $ ls -F prog-path $ ls -F prog-path include/ Makefile src/ $ -C prog-path... helpful for recursive calls of Leibniz Rechenzentrum 8 / 42
Get info about variable settings, etc.: $ -p... $ -p grep -i verbose... $ VERBOSE=1 -p grep -i verbose... Fake: Just prints command sequence but isn t really doing $ -n... Leibniz Rechenzentrum 9 / 42
Makefile Elements : similar to BASH SHELL variables Rules: targets, prerequisites, shell commands Directives: control structures, include and conditionals Comments: ignored by, everthing after # Leibniz Rechenzentrum 10 / 42
by Example A.h (class A declaration) A.cxx (implementation) main.cxx Makefile version 1 (03_MakefileVersion1).PHONY: clean prog: src/main.cxx src/a.cxx include/a.h TAB g++ -o prog -I./include src/main.cxx src/a.cxx clean: TAB @rm -rf prog src/*.o *~ */*~ No gain! Still all files recompiled. Leibniz Rechenzentrum 11 / 42
by Example - better solution A.h A.cxx main.cxx Makefile version 2 (03_MakefileVersion2).PHONY: clean prog: src/main.o src/a.o TAB g++ -o prog src/main.o src/a.o src/a.o: src/a.cxx include/a.h TAB g++ -c -I./include -o src/a.o src/a.cxx src/main.o: src/main.cxx include/a.h TAB g++ -c -I./include -o main.o src/main.cxx clean: TAB @rm -rf prog src/*.o *~ */*~ Leibniz Rechenzentrum 12 / 42
Syntax for explicit Rules targets... : prerequisites... TAB shell command Targets: file names or labels Prerequisites: file names or other targets separated by spaces; necessary to create the target Shell commands: interpreted by /bin/sh Note! (02_HelloMakeDiffTab) Tab character at beginning of command lines is mandatory! (unless.recipeprefix is set differently in newer versions) Leibniz Rechenzentrum 13 / 42
Command Lines Command Part Issues (01_HelloMake) Commands /bin/sh, unless SHELL set differently Split line: @echo "Hello" \ echo " World!" @ Command: Command NOT printed to screen - Command: failure is ignored, e.g. rm FileNotExist # Command line: just printed to screen Leibniz Rechenzentrum 14 / 42
Goals and the Default Goal Note! Goals = selected targets for update: $ src/main.o must match exactly one of Makefile s targets Default goal can be set via.default_goal inside Makefile else, 1st target in 1st rule of 1st file not starting with dot (".") Order of explicit rules not significant, except maybe for determining the default goal Leibniz Rechenzentrum 15 / 42
PHONY and Empty Targets.PHONY targets.phony targets = targets without real file possible files with same name as.phony target are ignored control Makefile behavior; typical.phony targets: clean, test, all Declare all.phony targets as such! Empty Targets print: src/a.cxx src/main.cxx TAB @echo $? TAB @touch print Only source files printed that changed since last call of $ print Leibniz Rechenzentrum 16 / 42
by Example Makefile version 3 (03_MakefileVersion3) PNAME=prog CXX=g++ INC=-I./include.PHONY: clean $(PNAME): src/main.o src/a.o TAB $(CXX) -o $(PNAME) src/main.o src/a.o src/a.o: src/a.cxx include/a.h TAB $(CXX) -c $(INC) src/a.cxx src/main.o: src/main.cxx include/a.h TAB $(CXX) -c $(INC) src/main.cxx clean: TAB @rm -rf $(PNAME) src/*.o *~ */*~ Leibniz Rechenzentrum 17 / 42
Overview Variable names case-sensitive: a_bla1 A_bla1 ${variablename} or $(variablename) for substitution Variable referenced in targets, prerequisites, commands, most directives, and new variable values Leibniz Rechenzentrum 18 / 42
User defined variables Recursively Expanded Example (Definition of recursively expanded variables) name = value variables stored as verbatim text; not expanded until referencing Advantage Order of definition NOT significant Problems name = ${name} anothervalue infinite recursion! referenced in definition of such variables are executed every time the variable is expanded execution much slower/unpredictable Leibniz Rechenzentrum 19 / 42
User defined variables Simply Expanded Example (Definition of simply expanded variables) name := value value of such variable scanned once Advantages No infinite recursions No slow down of Better style Leibniz Rechenzentrum 20 / 42
Appending More Text to Example (Simply Expanded ) name := value name += anothervalue # is equivalent to name := value name := ${name} anothervalue Example (Recursively Expanded ) name = value name += anothervalue # is equivalent to name = value temp = ${name} name = ${temp} anothervalue # except that temp not needed using "+=" Leibniz Rechenzentrum 21 / 42
Overriding variables How variables get their values 1 transforms BASH environment variables into variables with same name/value 2 Variable defined in Makefile any environment variable of same name ignored 3 are overridden on command line: $ PNAME=bla -f Makefile 4 Prevent any overriding by (in Makefile) override variablename = value works also for ":=" and "+=" operators Leibniz Rechenzentrum 22 / 42
Wildcard Characters in File Names Similar to BASH wildcards * Matches any string, including the null string? Matches any single character [... ] Matches any one of the enclosed characters / denotes your home directory john/ denotes John s home directory Leibniz Rechenzentrum 23 / 42
Build-in Searching Directories for Prerequisites VPATH: directories to look for prerequisites Rules can be written, as if all prerequisite files current directory VPATH: colon- or space-separated list of directories Example # Suppose foo.c is found in./src/. VPATH = src foo.o : foo.c Caution! (03_MakefileVersion6) Object files created in CURRENT directory! Leibniz Rechenzentrum 24 / 42
Used by Built-In for executable Programs ${FC} Fortran Compiler ${CC} C Compiler ${CPP} C Preprocessor ${CXX} C++ Compiler for Flags ${FFLAGS} Flags for the Fortran Compiler ${CFLAGS} Flags for the C Compiler ${CPPFLAGS} Flags for the C Preprocessor ${CXXFLAGS} Flags for the C++ Compiler ${LDFLAGS} Flags for the linker Leibniz Rechenzentrum 25 / 42
by Example Makefile version 4 (03_MakefileVersion4) PNAME=prog CXX=g++ INC=-I./include OBJS=src/main.o src/a.o.phony: clean $(PNAME): $(OBJS) TAB $(CXX) -o $@ $ˆ %.o: %.cxx include/a.h TAB $(CXX) -c $(INC) -o $@ $< clean: TAB @rm -rf $(PNAME) $(OBJS) *~ */*~ Leibniz Rechenzentrum 26 / 42
Syntax for implicit Rules target-pattern : prerequisites... TAB shell command target-pattern contains exactly one %! Note! Order of appearance of rules in Makefile important Most important automatic $@ File name of target of rule $< Name of first prerequesite $? Names of all prerequesites newer than target $ˆ Names of all prerequesites with spaces between them Leibniz Rechenzentrum 27 / 42
by Example Makefile version 5 (03_MakefileVersion7) PNAME=prog VPATH=include CXX=g++ INC=-I./include SRC = $(wildcard src/*.cxx) OBJS = $(SRC:.cxx=.o) # same as OBJS = $(patsubst %.cxx,%.o,$src).phony: clean bin/$(pname): $(OBJS) TAB @mkdir -p bin TAB $(CXX) -o $@ $ˆ %.o: %.cxx A.h TAB $(CXX) -c $(INC) -o $@ $< clean: TAB @rm -rf $(PNAME) bin *~ */*~ Leibniz Rechenzentrum 28 / 42
for String Substitution and Analysis $(subst from,to,text) replaces each occurence of from in text by to $(patsubst pattern,repl,text) finds whitespace-separated words in text matching the pattern and replaces with repl; % in pattern = wildcard; may also appear in repl $(filter patterns...,text) returns all whitespace-separated words in text which match any of whitespace-separated patterns $(filter-out patterns...,text) does exact opposite of filter $(subst ee,oo,feet) $(patsubst %.o,%.f90,foo.o) $(filter %.f90,foo.f90 bar.o) $(filter-out %.f90,foo.f90 bar.o) # = foot # = foo.f90 # = foo.f90 # = bar.o Leibniz Rechenzentrum 29 / 42
Further $(wildcard pattern): explicitely request wildcard expansion for file names; pattern may contain bash s wildcard characters *,?, [... ] $(foreach var,list,text): similar to bash s for or Perl s foreach $(call variable,arg1,arg2,...): expand appropriately defined variable as function $(shell command): execute command in a shell and process its output Many more functions available see user manual! Leibniz Rechenzentrum 30 / 42
by Example Makefile version 5 (03_MakefileVersion8) PNAME=prog CXX=g++ ifdef INTEL CXX=icpc endif INC=-I./include OBJS=$(patsubst %.cxx,%.o,$(wildcard src/*.cxx)).phony: clean $(PNAME): $(OBJS) TAB $(CXX) -o $@ $ˆ %.o: %.cxx include/a.h TAB $(CXX) -c $(INC) -o $@ $<... $ INTEL=1 or $ export INTEL=1 && Leibniz Rechenzentrum 31 / 42
Conditional Parts in Makefiles control what sees/ignores Example (Syntax of a simple conditional) ifeq (arg1, arg2) # take this if arguments equal endif all variable references in both arguments are expanded first, then arguments are compared Example (Syntax of another simple conditional) ifneq (arg1, arg2) # take this if arguments are not equal endif Leibniz Rechenzentrum 32 / 42
More complex conditionals Example (General syntax of conditionals) conditional-directive # take this if first condition is met [ else conditional-directive # take this if this condition is met # Note: available since v3.81 [... ] ] [ else # take this if no condition is true ] endif conditional-directive may be one of ifeq (arg1, arg2) ifneq (arg1, arg2) ifdef arg ifndef arg Leibniz Rechenzentrum 33 / 42
Include Directive Syntax include Make.inc useful to switch between e.g. compilers (incl. their flags, options, libraries) or hardware can be combined with conditionals ( command line switches or environmental variables) Example Please, have a look in the PTScotch Library, or other GNU suite programms! Leibniz Rechenzentrum 34 / 42
Exercise 04_Exercise include A.h src A.cxx main.cxx libb include B.h src B.cxx 04_Exercise Create Makefile(s)! Compile programm named prog into bin of top-level directory! main depends on A.h and B.h. Class B should become a library, located in lib of the top-level directory! Hint How to build dynamic libraries under Linux using gcc, please look here. Leibniz Rechenzentrum 35 / 42
Outline 1 2 3 Leibniz Rechenzentrum 36 / 42
Header Situation (05_Example) A.h B.h A.cxx main.cxx B.cxx or even more complex (C++ class hierarchies) Always a solution... If headers are modified: $ clean && Disadvantage: all source files have to be recompiled Leibniz Rechenzentrum 37 / 42
Header Or... (05_Example) PNAME := prog CXX := g++ INC := -I./include CXXFLAGS := -O3 $(INC) SRCS := $(wildcard src/*.cxx) OBJS := $(patsubst %.cxx,%.o,$(srcs)) DEPDIR :=.d $(shell mkdir -p $(DEPDIR)/src > /dev/null) DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d.PHONY: clean $(PNAME) : $(OBJS) TAB $(CXX) -o $@ $ˆ... Leibniz Rechenzentrum 38 / 42
Header... cont d (05_Example)... %.o : %.cxx TAB $(COMPILE.cc) -o $@ $< TAB $(POSTCOMPILE).PRECIOUS: $(DEPDIR)/%.d -include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))) clean: TAB @rm -rf $(DEPDIR) $(PNAME) $(OBJS) *~ */*~ $ cat.d/src/a.d src/a.o: src/a.cxx include/a.h include/a.h: Leibniz Rechenzentrum 39 / 42
Debugging Debugging existing Makefile or Variable settings $ -p $ -n in combination with pipes and grep etc. Debugging specific Variable settings (06_Make_DEBUG) insert rule into Makefile: print-%: TAB @echo $*=$($*) and call for instance: $ VAR=1 print-var Leibniz Rechenzentrum 40 / 42
Outline 1 2 3 Leibniz Rechenzentrum 41 / 42
user manual: https://www.gnu.org/software//manual/.html or in PDF form: https://www.gnu.org/software//manual/.pdf Specifically: Reference in Appendix A error messages: https://www.gnu.org/software//manual/html_node/error- Messages.html Leibniz Rechenzentrum 42 / 42