290 likes | 469 Views
Makefiles What you wanted to know but were afraid to ask. Presentation for ACM By James Haiston Rias Graduate student At South Dakota School of mines and Technology. Shakespeare on Makefiles . To make, or not to make, that is the question: Whether ‘tis nobler in the mind to suffer
E N D
MakefilesWhat you wanted to knowbut were afraid to ask. Presentation for ACM By James Haiston Rias Graduate student At South Dakota School of mines and Technology
Shakespeare on Makefiles. To make, or not to make, that is the question: Whether ‘tis nobler in the mind to suffer The slings and arrows of Visual Studio, Or to take arms against a sea of compiler issues, And by opposing end them; to make, and compile.
What is a Makefile? Make is a utility that automatically builds executable programs and libraries from source code by reading files called makefiles which specify how to derive a target program. The makefile is a set of instructions that determine the compilation of a program or instruction set.
How to Write a Simple Makefile • Suppose that you were writing a program that consists of: • Three C language source files • main.c • iodat.c • dorun.c • Assembly language code in li.s, called by one of the C sources. • A set of library routines in /usr/fred/lib/crtn.a.
How to Write a Simple Makefile • If you built the program by hand, the complete set of commands would be: • $ cc –c main.c • $ cc –c iodat.c • $ cc –c dorun.c • $ as –o l0.0 lo.s • $ cc –o program main.oiodat.odorun.olo.o /usr/fred/lib/crtn.a
How to Write a Simple Makefile The equivalent makefile would be; 1 program : main.ooidat.odorun.olo.o /usr/fred/lib/crtn.a 2 cc –o program main.oiodat.odorun.olo.o /usr/fred/lib/crtn.a 3 main.o : main.c 4 cc –c main.c 5 iodat.o : iodat.c 6 cc –c iodat.c 7 dorun.o : dorun.c 8 cc –c dorun.c 9 lo.o : lo.s 10 as –o lo.olo.s Dependency Line Command line
How to Write a Simple Makefile Suppose you have multiple versions of a program to compile, one as a terminal and one as a window. Description of a file that handles both 1 plot_prompt : basic.oprompt.o 2 cc –o plot_promptbasic.oprompt.o 3 plot_win : basic.owindow.o 4 cc –o plot_winbasic.owindow.o 5 basic.o : basic.c 6 cc –c basic.c 7 prompt.o : prompt.c 8 cc –c prompt.c 9 window.o : window.c 10 cc –c window.c
How to Write a Simple Makefile • The previous examples assume that: • The project files, as well as the description files, reside in the same directory. • The description files are named makefile or Makefile. • The directory containing these files is the current directory when you enter the make command. • Given these conditions, you can build any target in the description file by entering the command $ make target
How to Write a Simple Makefile • If some intermediate files are up to date, make skips their commands. The description file executes only the minimal set of commands rebuild the program. • If no prerequisite files were modified or removed since the last time target was created, make issues the message. ‘target’ is up to date • If you attempt to make a target that is not contained in the description file make will respond like this: make: Don’t know how to make nontarget. Stop. • Or like this: ‘nontarget’ is up to date.
Some Basic Rules of Syntax • The most important rule is to begin every command with a tab. • If you want to check the tabs in your description file, issue the command, $cat –v –t –e makefile • You can continue a long line by placing a backslash (\) at the end. • Make sure the backslash is right before the newline; don’t let any white space slip in between. A set of lines continued by backslashes is parsed as one line. • Use the # sign to begin a comment.
Some Basic Rules of Syntax Commands need not occupy separate lines in the description file. You can place a command on a dependency line, preceded by a semicolon: Plot_prompt : prompt.0; cc –o plot_promptprompt.o A single target can appear on multiple dependency lines. This can be a useful practice when you are indicating different kinds of dependencies: File.o : /usr/src/file.c cc –c /usr/src/file.c . . File.o : global.hdefs.h
Macros • Description files of the form name = text stringare macro definitions. • Subsequent references to • $(name) • ${name} are interpereted as text string • These for instance are all valid macro definitions: LIBES = -1X11 objs = drawable.oplot_points.oroot_data.o CC = /usr/fred/bin/cc 23 = “This is the (23)rd run” OPT = DEBUG_FLAG = # empty now, but assign –g for debugging BINDER = /usr/local/bin
Macros • An entry in the same description file might look like this: plot: ${objs} ${CC} –o plot $(DEBUG_FLAG) ${objs} ${LIBES} mv plot /usr/local/bin • When you invoke make plot, the command evaluates to: /usr/fred/bin/cc –o plot drawable.oplot_points.oroot_data.o -1X11 mv plot /usr/local/bin
Macros • Reason for macros; • You can refer conveniently to files or command options that appear repeatedly in the description file. • Macros permit variations from one build to the next.
Macros • Syntax for macros • A macro definition is a line containing an equal sign. • Single-character macro names do not require either parentheses or braces; A=XYZ can be referred to as $A, $(A), or ${A} • It is permissible to use macros in macro definitions, as in ABC = XYZ FILE = TEXT.$(ABC) • If you refer to a macro without defining it make substitutes a NULL string. • The order that macros are defined is not important.
Internally Defined Macros • make predefines a number of common commands in macros. • The ${CC} macro is always recognized by make as the C compiler. • The ${LD} macro is always recognized as the linker. • If you see a description file like this: basic.o : basic.c ${CC} –c basic.c Is normally the same as basic.o : basic.c cc –c basic.c
Macro Definitions on the Command Line You can define macros on the make command line. The following invocation: $ make jgref DIR=/usr/proj If the definition on your command line consists of several words, enclose them in double or single quotes. $ make jgref“DIR=/usr/proj /usr/lib /usr/proj/lib“ In the Bourne and Korn shells, you can define the macro before the make command: $ DIR=/usr/projmake jgref
Priority of Macro Assignments • Here is the priority from least to greatest • Internal (default) definitions of make. • Current shell environment variables. This includes macros that you enter on the make command line, if they precede the make command itself. • Description file macro definitions. • Macros that you enter on the make command line, if they follow the make command itself. • This may be changed by invoking make with the –e option • Internal (default) definitions of make. • Description file macro definitions. • Current shell environment variables. This includes macros that you enter on the make command line, if they precede the make command itself. • Macros that you enter on the make command line, if they follow the make command itself.
Macro String Substitution Suppose you have the macro definition, SRCS = defs.credraw.ccalc.c The description file command, ls ${SRCS: .c=.o} then produces the output, calc.odefs.oredraw.o String substitution is severely restricted; can take place only at the end of the macro or immediately before white space. LETTERS = xyz xyzabcabcxyz … echo $(LETTERS: xyz=DEF) produces the output, DEF xyzabcabcDEF
Internal Macros for Prerequisites and Targets • make defines several macros of its own each time it reads a dependency line. • The $@ macro evaluates to the current target. An entry compiling an executable program uses @ as the name of the output file: plot_prompt : basic.oprompt.o cc –o $@ basic.oprompt.o • The $? macro evaluates to a list of prerequisites that are newer than the current target. The following description entry rebuilds the library with any object files that are newer than the library itself: libops : interact.osched.ogen.o ar r $@ $? • The $^ expands to a space delimited list of the prerequisites.
Clean • The clean is used to remove unwanted/unused files from the program being compiled. This is done in two different ways • $ clean – used to remove –o files. • $ make clean – used to remove –o files as well as executables. • An example of these can be seen in the example below; clean: rm –f *-o *.~ core cleanall: rm –f *-o *.~ core $(EXE)
Sample Makefile This is a primordial makefile made famous by Dr. John Weiss.
References "Make (software)." Wikipedia, the Free Encyclopedia. Web. 17 Jan. 2012. <http://en.wikipedia.org/wiki/Make_(software)>. Oram, Andrew, and Steve Talbott. Managing Projects with Make. Sebastopol, CA: O'Reilly & Associates, 1993. Print.
Appendix A, Options. • Standard options are: • -b Accept description files from previous implementations of make. • -d Debug mode – print detailed information about internal flags and the last-modified times of files. • -e Let environment variables override macro definitions inside description files. • -f Following argument is a description file. • -i Ignore error codes. Same as .IGNORE: in description file. • -k Error terminates work on current branch of hierarchy, but not on other branches. • -n Echo command lines, but do not execute them. Even lines beginning with @ are echoed.
Appendix A, Options (cont.). • Standard options are: • -p Print out macro definitions, suffixes, suffix rules, and explicit description file entries. • -q Return zero or non-zero status, depending on whether the target file is or is not up to date. • -r Do not use the default rules. • -s Do not echo command lines. Same as .SILENT: in description file. • -t Touch target files (making them appear up to date), without executing any other commands.
Appendix B, Internal Macros. • Standard options are: • $? The list of prerequisites that have been changed more recently than the current target. Can be used only in normal description file entries, not suffix rules. • $@ The name of the current target, except in description file entries for making libraries, where it becomes the library name. • $$@ The name of the current target. Can be used only to the right of the colon in dependency lines. • $< The name of the current prerequisite that has been modified more recently than the current target. Can be used only in suffix rules and the .DEFAULT entry. • $* The name – without the suffix – of the current prerequisite that has been modified more recently than the current target. Can be used only in suffix rules. • $% The name of the corresponding .o file when the current target is a library module. Can be used in both normal description file entries and suffix rules.