Make is a brilliant little tool you can use to automate eg. compiling your C programs or run scripts from the command line.
You can set up your commands/rules in a file called
Makefile and then run them from the command line.
What I wanted to do is to automate compiling multiple C programs into separate executables. My project folder looks something like this:
. Makefile src/ prog1.c prog2.c prog3.c build/ prog1 prog2 prog3
What I wanted to do is run a simple command like
make all and have all the
.c files with the program’s source in them compiled into the corresponding files in
Here is the
Makefile I came up with:
srcfiles = $(notdir $(wildcard src/*.c)) outputs = $(basename $(srcfiles)) all: $(outputs) $(outputs): %: src/%.c gcc -o build/$@ $<
I’ll break down what it does.
In the first section we declare some variables.
srcfiles is the list of C source files,
outputs is the list of executable files we want to build.
The first line creates a list of all the
.c files in the
src folder (
$(wildcard src/*.c)), then removes the part of the path that’s the directory with
$(notdir). What we end up there is a list of files:
srcfiles = prog1.c prog2.c prog3.c.
The next line uses the list above to create the list of compiled executable files by removing the file extension with
The next part sets up a rule called “all” and tells it to run this rule on all names in
outputs. At this point Make doesn’t yet know what we want it to do, but we’re about to solve that.
The last section sets up a rule that is valid for all files in the
outputs list. This means whenever any other rule in this Makefile would effect a name from the
outputs list, Make will look at this rule and use it. This is what we’re declaring by starting the line with
After the first colon we declare that every file in the
outputs list (
% basicall means “every element”) depends on the file with the same name and a
.c extension in the
All that’s left to do here is run the C compiler “gcc” and give it all the needed input. The
-o flag tells the compiler what the output file it compiles into should be. Here we use the special variable
$@ which points to the filename of the target of the rule, in our case the file from the
outputs list. At the end
$< points to the first dependency, in out case
src/%.c which Make then interprets as
src/NAME FROM OUTPUTS.c.
With this Makefile if we run
make all in the project directory, all the files in
src/ will be compiled into
build/ under the correct name.
If you’d like to read a bit more on how to manipulate filenames and text with Make, I recommend the documentation for GNU Make, especially the sections on text functions, filename functions and automatic variables.