Makefile
Building HTTPd
HTTPd is the largest project you have worked on this year until now. As a project expands in size, it brings forth new challenges, including writing maintainable code and establishing a sustainable architecture.
Recursive Makefiles
Recursive Makefiles are not required, but they are a practical way to build
the httpd binary in a modular project. If you want to do a well-structured
build that scales with subdirectories, adopting a recursive layout is
encouraged.
In this section, we assume that you are already familiar with make and simple Makefiles. For a refresher, you may look into the various Piscine tutorials on Makefiles as well as the recorded conference.
When using make(1), the option -C can be used to specify the build directory.
Make will then move into the directory and run as usual, using the Makefile in
it.
42sh$ ls Test./
Makefile votai.c
42sh$ cat Test./Makefile
votai: votai.o
42sh$ make -C Test./
make: Entering directory '/home/lucasTheSpider/Test.'
cc -c -o votai.o votai.c
cc votai.o -o votai
make: Leaving directory '/home/lucasTheSpider/Test.'
42sh$ Test./votai
Votai Test.
This is equivalent to cd Test./ && make && cd - but with additional information
about which directory you are calling and which commands are called.
As you may recall, a Makefile is composed of rules, and rules are composed of
three things:
- targets (The goal to produce)
- dependencies (What the target needs prior)
- recipes (Composed of various commands to run)
Since recipes are composed of any command, it is possible to declare a rule that can call another Makefile if needed.
42sh$ tree
.
|-- Makefile
`-- Test.
|-- Makefile
`-- votai.c
2 directories, 3 files
42sh$ cat Makefile
all:
make -C Test./
42sh$ make
make -C Test.
make[1]: Entering directory '/home/lucasTheSpider/Test.'
cc -c -o votai.o votai.c
cc votai.o -o votai
make[1]: Leaving directory '/home/lucasTheSpider/Test.'
42sh$ Test./votai
Votai Test.
Now, the root Makefile is considered the top-level Makefile, and every Makefile called by it is considered as a sub-Makefile.
Each Makefile handles its own environment, so changing the flags of a sub-Makefile does not affect the top-level one, but modifying the top level will change the environment for the sub-Makefiles if the variable is exported.
export CC = gcc
Defining this variable in the top-level Makefile will make the variable available in every sub-Makefile.