build: Makefiles

Makefiles

If you are wondering what the best documentation for Makefiles is please visit the official manual

What do they do

A makefile tells make (which is a separate piece of software) what to do, and usually these instructions tell make how to compile and build a program. They are super useful when you have multi-file projects, but not only.

Syntax

target : prerequisites
    recipe

the target and prerequisites use make syntax while the recipe is written in bash

A simple example

hello: introduce
    @echo Hello World I have an interesting story to tell \
    my name is computer, and I love makefiles
introduce:
    echo "Let me Introduce myself"

What the makefile above will do is:

  1. Want to execute hello as it is the first function and will look if introduce has been satisfied.
  2. See that it is not satisfied so it will look for introduce and execute it first
  3. execute introduce
  4. execute target
  5. that’s it

Note:

  • can you see how I broke down the first echo with the use of \
  • @ character will not output the function being executed but rather only the output. It is called suppression.

A useful example

Scenario: we have a program a.cpp that depends on the prior compilation of b.cpp, with the latter using the library d.h

Not only that, but you are also a tidy person, and don’t want to leave any trace of the file executing, so the folder is nice and clean at the end

Let’s have a go at creating this:


all: execute clean

compile: a.o b.o 
	@g++ *.o -o output -I .

a.o: b.o 
	@g++ -c a.cpp -I .

b.o: 
	@g++ -c b.cpp -I .

.PHONY : clean

execute: compile
	@./output

clean:
	@echo "cleaning the folder"
	@rm *.o
	@rm output
	@echo "All done "

To have a look at what the above mini program does go to my exercises repo

Wildcard rules

If you want to define a rule that is applied to all .foo files when compiled

%.o: %.foo
    fooc $(FOOFLAGS) -o $@ -c $<

Condensed useful stuff

automatic variables look at the example below for more details
$@ This means the file that is being generated - the one on the left of the dots
$< First prerequisite - usually the source file
$^ All the prerequisites
$(wildcard *.cpp) will load all the *.c files
$(patsubst %.c,%.o,$(wildcard *.cpp)) Will substitute all the *.cpp into *.o. Note the use of % to denote EACH
$(shell pwd) Exectues the shell comnmand
all: library.cpp main.cpp

    $@ evaluates to all 
    $< evaluates to library.cpp
    $^ evaluates to library.cpp main.cpp

Makefiles are smart

Makefiles are quite smart as well

%.o : %.cpp
#this will generate obj files from all of the cpp files without the need of any other comand

Further resources

  • http://nuclear.mutantstargoat.com/articles/make/