←to practical programming

Make utility

In POSIX systems make is a utility to manage pojects on a computer (programs, libraries, articles, reports, web-sites, and others) where files must be manipulated according to certain rules.

When make is run, it reads the description of the project from a makefile and then automatically updates the project, if necessary, according to the rules in the makefile.

Makefile

Makefile contains a description of the project in the declarative makefile language. By default a makefile must have the name makefile or Makefile. If the makefile is called SomethingElse then the make utility must be called as
make -f SomethingElse

A makefile resembles a cookbook and consists of macro definitions and rules.

Macro definitions

A macro definition looks like a normal assignment in a programming language, for example
MCS = mcs -optimize+ -platform:arm
The macro can then be called as $(MCS) and will return the string mcs -optimize+ -platform:arm.

Rules

A rule looks very much like an instruction for preparing a dish. It has the following syntax,
dish : ingredients
recipe
where the sign denotes the (mostly invisible, unfortunately) tabulator-sign. Yes, by default a recipie starts with the tabulator-sign. This aspect has been a subject of critisism, so in the GNU-make version 3.82+ one can change the default tabulator-sign to any other sign—for example a semicolon ;—by defining a macro .RECIPEPREFIX := ;.

The rule is interpreted like the following:

The GNU-make manual uses a somewhat different notation,

target : prerequisites
recipe

If the recipie consists of one command only, it can be written in the same line as the target,

target : prerequisites ; recipe

By default 'make' only builds the first target it finds in the makefile. Therefore if more than one targets must be built one makes a "phoney" target that depends on the targets that must be built by default,

.PHONEY: default
default : target1 target2 target3
One can also build a specific target, say 'test', with the command
make test
Hint: bash-completion feature actually works on the targets in the current Makefile.

'Hello world' example

Suppose we have a project to create a file out.txt with the text "hello world" using a 'hello world' C#-program wholly contained in the file "hello.cs".

The makefile for the project could look like this,

out.txt : hello.exe         # out.txt depends on bytecode executable hello.exe
mono hello.exe > out.txt  # run hello.exe in mono, redirect output into out.txt

hello.exe : hello.cs           # bytecode hello.exe depends on source-code hello.cs
mcs -out:hello.exe hello.cs   # compile hello.cs, output goes to hello.exe

.PHONEY:clean           # clean is a phoney target
clean:                  # does not depend on anything
rm --force out.txt hello.exe # remove the files produced by making
Comments start with the hash-sign, #.