No pun intended, but you are making make a bit harder than it needs to be. In your case with the source and headers all in the same directory, it is quite simple to use wildcards to allow make to handle the rest. For example with three simple variable declartions in your Makefile
, you can tell make what your sources are, your includes and how to generate an object file for each of the source files that isn't the application name.
For starters, specify your application name:
# application name
APPNAME := justify
If needed, set your compiler variables, e.g.
# compiler
CC := gcc
CCLD := $(CC)
Now make knows your application name is held in APPNAME
which you access like any other variable in a Makefile
as $(APPNAME)
.
Now just use wildcard
to collect all sources and includes in variables as well, and let make
associate the object file output:
# source/include/object variables
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:%.c=%.o)
Set your compiler/linker/library flags:
# compiler and linker flags
CFLAGS := -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
LDFLAGS :=
# libraries
LIBS :=
Now create your default target for make
(note: there must be a tab-character '\t'
in front of each rule):
all: $(OBJECTS)
$(CCLD) -o $(APPNAME) $(OBJECTS) $(CFLAGS) $(LDFLAGS) $(LIBS)
A rule to compile all sources to objects:
$(OBJECTS): %.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
(see: What do the makefile symbols $@ and $< mean? for explanation of the automatic variables used)
And finally a target for clean:
clean:
rm -rf $(APPNAME) *.o
A complete example for your files would be:
# application name
APPNAME := justify
# compiler
CC := gcc
CCLD := $(CC)
# compiler and linker flags
CFLAGS := -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
LDFLAGS :=
# libraries
LIBS :=
# source/include/object variables
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:%.c=%.o)
# target for all
all: $(OBJECTS)
$(CCLD) -o $(APPNAME) $(OBJECTS) $(CFLAGS) $(LDFLAGS) $(LIBS)
# strip only if -DDEBUG not set
ifneq ($(debug),-DDEBUG)
strip -s $(APPNAME)
endif
$(OBJECTS): %.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -rf $(APPNAME) *.o
(note: a rule to strip
the executable was also added to the all:
target)
Example Build
With your Makefile
source and include files in a common directory, e.g.
$ ll
total 24
-rw-r--r-- 1 david david 668 Nov 6 12:38 Makefile
-rw-r--r-- 1 david david 161 Nov 6 12:31 justify.c
-rw-r--r-- 1 david david 106 Nov 6 12:32 line.c
-rw-r--r-- 1 david david 37 Nov 6 12:31 line.h
-rw-r--r-- 1 david david 104 Nov 6 12:32 word.c
-rw-r--r-- 1 david david 36 Nov 6 12:32 word.h
Just type make
to have your application built:
$ make
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o word.o word.c
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o line.o line.c
gcc -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast -c -o justify.o justify.c
gcc -o justify word.o line.o justify.o -Wall -Wextra -pedantic -finline-functions -std=c11 -Wshadow -Ofast
strip -s justify
No errors, you can check all files were created as expected:
$ ll
total 44
-rw-r--r-- 1 david david 668 Nov 6 12:38 Makefile
-rwxr-xr-x 1 david david 6312 Nov 6 13:01 justify
-rw-r--r-- 1 david david 161 Nov 6 12:31 justify.c
-rw-r--r-- 1 david david 1760 Nov 6 13:01 justify.o
-rw-r--r-- 1 david david 106 Nov 6 12:32 line.c
-rw-r--r-- 1 david david 37 Nov 6 12:31 line.h
-rw-r--r-- 1 david david 1496 Nov 6 13:01 line.o
-rw-r--r-- 1 david david 104 Nov 6 12:32 word.c
-rw-r--r-- 1 david david 36 Nov 6 12:32 word.h
-rw-r--r-- 1 david david 1496 Nov 6 13:01 word.o
Test your executable:
$ ./justifiy
I'm in the main.
read_word
write_line
Lastly, clean your build directory with make clean
, e.g.
$ make clean
And confirm all build files are removed.
That's about the easiest way to go about writing minimal make files. You can list each object individually and the required includes to support them, but why? the automatic variables will take care of that for you. There is much, much more you can do with Makefiles, but for getting started, this will make your life easier.