COSC345 2013 Software Engineering

Lecture 10: Outline • The build process • Make • When to use make • How to use make • Suffix rules • Makedepend

• Warning: – Make is different everywhere you go! – The basics will work, though. Build Process • The build process can often: – Be complex – Rely on several different processes – Be time-consuming – Be difficult to remember

defs.h command.h

main.m kbd.m

main.o kbd.o

edit Steps towards make • Complex => write a shell script and run that • But that’s time consuming (compiling a million lines used to take 24 hours) • So just recompile the bits that need recompiling and relink • Do that using ‘if’ in scripts. • But that’s tricky and repetitive. • Sounds like a task for a little language! • Also, we can derive more than one artefact from the same sources (code, several kinds of library, static checks, listings, archives, …) Make combines 3 languages • A scripting language (normally sh) for commands

• A language for stating target(s)-depends-on- source(s) edges in a dependency graph

• A templating language for constructing the others

• Mixing several languages is always tricky; even if each one is simple, the combination may not be. Dependencies • If a header changes then the source must be recompiled – If command.h changes then • recompile kbd.m • relink edit • Actually, we must rebuild: – All files that include the header – All executables that depend on the object code – All libraries that depend on the object code – All executables that depend on the library – All web-listings, cross-references, &c • And all in the right order! What Make Does • We need some way of scripting the build process – When changes are made: • Only re-build the parts that are necessary • Automatically work out which parts those are • Make – Manages the creation of output files from source files – Uses a configuration file (makefile) to specify how – Uses file time-stamps to determine what’s out-of-date • Make also: – Enables those new to a project to build it without understanding the build process – Enables the developers to build: • Clean-up scripts • Install scripts What about Ant, Maven, &c? • There are many build tools. • They do basically the same job as Make. • They do it basically the same way. • Except that some are language-specific. • Ant is “Make redone in Java with unreadability as a core design goal.” • IDEs also solve this task, but often in a language- dependent way, and using proprietary formats to hide key information. • Ensure your tools can handle non-code artefacts! • Make is much simpler to get started with. When to use Make • When the project has more than one file • When the build process is more than just “compile” – It reduces compile / debug cycle time • When the build process is different on different machines • When you expect to go back to a project later – And won’t be able to remember how to build it

• In short… always – The time required to write a makefile is very small • It saves time if you’re going to compile more than once • Which is always. Make Scripting • Make uses a(“little language”) script to determine: – Which files need rebuilding – The order they should be rebuilt

• If you change only one thing then make will make changes only to files that depend on that change

• In a script (a makefile) you tell make – How to execute a series of commands to make a target from sources – What the target depends on • Call your makefile either makefile or Makefile Make Rules

• A makefile is made from a series of rules

:

is the name of the file to be built • is the name of a file needed to build it; the target depends on the source • is each command needed to create the target – Commands are indented by one TAB (not spaces!) • A rule describes how and when to perform an action • Unless specified otherwise make builds only the first target Sample Makefile edit : main.o kbd.o cc -o edit main.o kbd.o main.o : main.m defs.h cc -c main.m kbd.o : kbd.m defs.h command.h cc -c kbd.m clean : rm edit main.o kbd.o

• In the rule: edit : main.o kbd.o cc -o edit main.o kbd.o • The target is edit • The sources are main.o and kbd.o • The command is cc -o edit main.o kbd.o – which will result in edit being built What Make Does • Read the makefile • Generate a dependency graph for the first target • Starting at the target – For every source of that target • Target the source – If any source is more recent than the target • Execute the commands – If any target doesn’t exist • Execute the commands • The commands should normally (re)create the target • To run make on , MacOS, Cygwin: make • To run make on Windows: nmake Nmake is not Make • In the world: – There is the classic Unix Make. – There is Solaris Make (adds ‘include’). – There is GNU Make (adds extra hair, in great abundance), used in Linux and Mac OS X. – These are upwards compatible in that order.

• In the Windows world: – GNU Make runs under Cygwin and SUA – There is Nmake – These are not compatible! One key difference is that Make uses “sh” while Nmake uses Command.Exe – Dependency Graph • In the example: – If any of the .h or .m files is “touched” then edit is rebuilt

edit : main.o kbd.o defs.h command.h cc -o edit main.o kbd.o main.o : main.m defs.h main.m kbd.m cc -c main.m kbd.o : kbd.m defs.h command.h cc -c kbd.m main.o kbd.o clean : rm edit main.o kbd.o edit Commands • Make will execute one or more commands specified: – Each on separate line – Without blank lines between them clean : rm edit rm main.o kbd.o • Make does not execute commands directly, it calls a (configurable) shell to execute them • If a command returns an error (non-zero) then make stops – This stops the build process at the first error • Commands starting with ‘@’ are not echoed to the console (silent), ‘-’ have their return code ignored (can’t produce an error). Macros / Inference Rules • Macros can be defined objects = main.o kbd.o • And used edit : $(objects) cc -o edit $(objects) • So changes only need to be made in one place

• Some rules are inferred

main.o : defs.h kbd.o : defs.h command.h

• Make “knows” how to make .c files into .o files; Apple’s one “knows” about .m (Obj-C) files. Inference Rules

• main.o is made from main.m & defs.h by an inference rule: $(CC) -c $(CFLAGS) main.m • Inference rules can be specified in the makefile <.from><.to>: • Example .m.o: $(CC) -c $(CFLAGS) $<

• Make must be told about inference rules it doesn’t know .SUFFIXES: #Clear the suffix list .SUFFIXES: .m .o #Append to the suffix list Predefined Macros • Make has many built in default macros: – For it includes Flags CC CFLAGS CXX CXXFLAGS – For inference rules it includes:

Macro Definition $@ Current target's full name $< Source file with a later timestamp than the current target $? All sources with a later timestamp than the current target

$* Current target's path and base name minus file extension $+ All sources of the current target

– As well as the environment variables Other Rules • Multiple targets for a dependency main.o kdb.o : defs.h kbd.o : command.h • Targets built by multiple commands (::) libaspt.a :: kbd.o ar -rv libaspt.a kbd.o

libaspt.a :: another.o ar -rv libaspt.a another.o • Makefiles can include other makefiles include another.mak • # at the beginning of a line is a comment Dependencies • The dependencies must be kept up-to-date – Every new header file included must be accounted for – This is time consuming and prone to error

• Tools exist to build the dependencies – makedepend – mkdep – And others too, like mkmf

• For more on makedepend (on Linux) try man makedepend References • GNU make – http://www.gnu.org/software/make/manual/make.html – % info make • Classic Make – Chapter 16 of V7 Volume 2 (~ok/COSC345/v7vol2a.pdf pages 277-285) • NMAKE reference – http://msdn2.microsoft.com/en-us/library/dd9y37ha.aspx