Building Multi-File Programs with the Make Tool
Total Page:16
File Type:pdf, Size:1020Kb
Princeton University Computer Science 217: Introduction to Programming Systems Agenda Motivation for Make Building Multi-File Programs Make Fundamentals with the make Tool Non-File Targets Macros Implicit Rules 1 2 Multi-File Programs Motivation for Make (Part 1) intmath.h (interface) Building testintmath, approach 1: testintmath.c (client) #ifndef INTMATH_INCLUDED • Use one gcc217 command to #define INTMATH_INCLUDED #include "intmath.h" int gcd(int i, int j); #include <stdio.h> preprocess, compile, assemble, and link int lcm(int i, int j); #endif int main(void) { int i; intmath.c (implementation) int j; printf("Enter the first integer:\n"); #include "intmath.h" scanf("%d", &i); testintmath.c intmath.h intmath.c printf("Enter the second integer:\n"); int gcd(int i, int j) scanf("%d", &j); { int temp; printf("Greatest common divisor: %d.\n", while (j != 0) gcd(i, j)); { temp = i % j; printf("Least common multiple: %d.\n", gcc217 testintmath.c intmath.c –o testintmath i = j; lcm(i, j); j = temp; return 0; } } return i; } Note: intmath.h is int lcm(int i, int j) #included into intmath.c { return (i / gcd(i, j)) * j; testintmath } and testintmath.c 3 4 Motivation for Make (Part 2) Partial Builds Building testintmath, approach 2: Approach 2 allows for partial builds • Preprocess, compile, assemble to produce .o files • Example: Change intmath.c • Link to produce executable binary file • Must rebuild intmath.o and testintmath • Need not rebuild testintmath.o!!! Recall: -c option tells gcc217 to omit link changed testintmath.c intmath.h intmath.c testintmath.c intmath.h intmath.c gcc217 –c testintmath.c gcc217 –c intmath.c gcc217 –c testintmath.c gcc217 –c intmath.c testintmath.o intmath.o testintmath.o intmath.o gcc217 testintmath.o intmath.o –o testintmath gcc217 testintmath.o intmath.o –o testintmath testintmath testintmath 5 6 Partial Builds Partial Builds • Example: Change testintmath.c However, changing a .h file can be more dramatic • Must rebuild testintmath.o and testintmath • Example: Change intmath.h • Need not rebuild intmath.o!!! • intmath.h is #included into testintmath.c and intmath.c • Changing intmath.h effectively changes testintmath.c If program contains many .c files, could save many hours of build time and intmath.c • Must rebuild testintmath.o, intmath.o, and testintmath changed changed testintmath.c intmath.h intmath.c testintmath.c intmath.h intmath.c gcc217 –c testintmath.c gcc217 –c intmath.c testintmath.o intmath.o gcc217 –c testintmath.c gcc217 –c intmath.c testintmath.o intmath.o gcc217 testintmath.o intmath.o –o testintmath gcc217 testintmath.o intmath.o –o testintmath testintmath testintmath 7 8 Wouldn’t It Be Nice… Agenda Observation • Doing partial builds manually is tedious and error-prone • Wouldn䇻t it be nice if there were a tool Motivation for Make How would the tool work? Make Fundamentals • Input: • Dependency graph (as shown previously) Non-File Targets • Specifies file dependencies • Specifies commands to build each file from its dependents Macros • Date/time stamps of files Implicit Rules • Algorithm: • If file B depends on A and date/time stamp of A is newer than date/time stamp of B, then rebuild B using the specified command That䇻s make! 9 10 Make Command Syntax Dependency Rules in Makefile Command syntax Dependency rule syntax $ man make target: dependencies SYNOPSIS <tab>command make [-f makefile] [options] [targets] • target: the file you want to build • makefile • dependencies: the files on which the target depends • Textual representation of dependency graph • command: (after a TAB character) what to execute to • Contains dependency rules create the target • Default name is makefile, then Makefile Dependency rule semantics • Build target iff it is older than any of its dependencies • target • Use command to do the build • What make should build • Usually: .o file, or an executable binary file • Default is first one defined in makefile Work recursively; examples illustrate… 11 12 Makefile Version 1 Version 1 in Action testintmath.c intmath.h intmath.c At first, to build testintmath Use the touch command to make issues all three gcc change the date/time stamp gcc217 –c testintmath.c gcc217 –c intmath.c commands of intmath.c testintmath.o intmath.o $ make testintmath gcc217 -c testintmath.c gcc217 testintmath.o intmath.o –o testintmath gcc217 -c intmath.c gcc217 testintmath.o intmath.o -o testintmath $ touch intmath.c testintmath Makefile: $ make testintmath gcc217 -c intmath.c testintmath: testintmath.o intmath.o gcc217 testintmath.o intmath.o -o testintmath gcc217 testintmath.o intmath.o –o testintmath $ make testintmath make: `testintmath' is up to date. testintmath.o: testintmath.c intmath.h make does a partial build gcc217 -c testintmath.c $ make make: `testintmath' is up to date. make notes that the specified intmath.o: intmath.c intmath.h gcc217 -c intmath.c target is up to date The default target is testintmath, 13 the target of the first dependency rule 14 Agenda Non-File Targets Adding useful shortcuts for the programmer • make all: create the final executable binary file Motivation for Make • make clean: delete all .o files, executable binary file • make clobber: delete all Emacs backup files, all .o files, executable Make Fundamentals Commands in the example Non-File Targets • rm –f: remove files without querying the user • Files ending in 䇺~䇻 and starting/ending in 䇺#䇻 are Emacs backup files Macros Implicit Rules all: testintmath clobber: clean rm -f *~ \#*\# clean: rm -f testintmath *.o 15 16 Makefile Version 2 Version 2 in Action # Dependency rules for non-file targets make observes that 䇾clean䇿 target all: testintmath doesn䇻t exist; attempts to build it clobber: clean rm -f *~ \#*\# by issuing 䇾rm䇿 command clean: Same idea here, but rm -f testintmath *.o $ make clean rm -f testintmath *.o 䇾clobber䇿 depends upon 䇾clean䇿 # Dependency rules for file targets $ make clobber testintmath: testintmath.o intmath.o rm -f testintmath *.o gcc217 testintmath.o intmath.o –o testintmath rm -f *~ \#*\# testintmath.o: testintmath.c intmath.h $ make all gcc217 -c testintmath.c gcc217 -c testintmath.c gcc217 -c intmath.c intmath.o: intmath.c intmath.h gcc217 testintmath.o intmath.o -o testintmath gcc217 -c intmath.c $ make make: Nothing to be done for `all'. 䇾all䇿 depends upon 䇾testintmath䇿 䇾all䇿 is the default target 17 18 Agenda Macros make has a macro facility • Performs textual substitution Motivation for Make • Similar to C preprocessor’s #define Make Fundamentals Macro definition syntax Non-File Targets macroname = macrodefinition • make replaces $(macroname) with macrodefinition in remainder of Macros Makefile Implicit Rules Example: Make it easy to change build commands CC = gcc217 Example: Make it easy to change build flags CFLAGS = -D NDEBUG –O 19 20 Makefile Version 3 Version 3 in Action # Macros CC = gcc217 # CC = gcc217m Same as Version 2 CFLAGS = # CFLAGS = -g # CFLAGS = -D NDEBUG # CFLAGS = -D NDEBUG -O # Dependency rules for non-file targets all: testintmath clobber: clean rm -f *~ \#*\# clean: rm -f testintmath *.o # Dependency rules for file targets testintmath: testintmath.o intmath.o $(CC) $(CFLAGS) testintmath.o intmath.o -o testintmath testintmath.o: testintmath.c intmath.h $(CC) $(CFLAGS) -c testintmath.c intmath.o: intmath.c intmath.h $(CC) $(CFLAGS) -c intmath.c 21 22 Agenda Implicit Rules make has implicit rules for compiling and linking C programs • make knows how to build x.o from x.c Motivation for Make • Automatically uses $(CC) and $(CFLAGS) Make Fundamentals • make knows how to build an executable from .o files • Automatically uses $(CC) Non-File Targets intmath.o: intmath.c intmath.h Macros $(CC) $(CFLAGS) –c intmath.c Implicit Rules intmath.o: intmath.c intmath.h testintmath: testintmath.o intmath.o $(CC) testintmath.o intmath.o –o testintmath testintmath: testintmath.o intmath.o 23 24 Makefile Version 4 Version 4 in Action # Macros CC = gcc217 # CC = gcc217m Same as Version 2 CFLAGS = # CFLAGS = -g # CFLAGS = -D NDEBUG # CFLAGS = -D NDEBUG -O # Dependency rules for non-file targets all: testintmath clobber: clean rm -f *~ \#*\# clean: rm -f testintmath *.o # Dependency rules for file targets testintmath: testintmath.o intmath.o testintmath.o: testintmath.c intmath.h intmath.o: intmath.c intmath.h 25 26 Implicit Dependencies Makefile Version 5 has implicit rules for inferring dependencies make # Macros • make will assume that x.o depends upon x.c CC = gcc217 # CC = gcc217m CFLAGS = # CFLAGS = -g # CFLAGS = -D NDEBUG # CFLAGS = -D NDEBUG -O intmath.o: intmath.c intmath.h # Dependency rules for non-file targets all: testintmath clobber: clean rm -f *~ \#*\# clean: intmath.o: intmath.h rm -f testintmath *.o # Dependency rules for file targets testintmath: testintmath.o intmath.o testintmath.o: intmath.h intmath.o: intmath.h 27 28 Version 5 in Action iClicker Question Q: If you were making a Makefile for this program, what should a.o depend on? Same as Version 2 d.h A. a.c c.h a.h B. a.c a.h a.c b.c C. a.c c.h d.h a.o b.o D. a.c a.h c.h d.h a 29 Makefile Guidelines iClicker Question Q: If you were making a Makefile for this program, d.h what should a depend on? c.h a.h d.h a.c b.c A. a.o b.o c.h a.h a.o b.o a.o: a.h c.h d.h B. a.o b.o a.c b.c a.c b.c a C. a.o b.o a.h c.h d.h a.o b.o In a proper Makefile, each object file: D. a.c b.c a.h c.h d.h • Depends upon its .c file (but can rely on an implicit dependency) a • Does not depend upon any other .c file E.