Reputation: 157
I am currently studying K&R and I would like to create a Makefile in order to automate the compiling process.
I have a directory structured as follows :
k-r/
chapter-1/
exe/
1-1/
program1.c
program2.c
...
1-2/
program3.c
program4.c
...
ch1.c
ch1.h
Most of the programs are self-contained but some require functions which are defined in k-r/chapter-1/ch1.c and k-r/chapter-1/ch1.h.
I would like to compile all the programs in k-r/chapter-1/1-1, k-r/chapter-1/1-2 and so on, and ship the executable binaries to k-r/chapter-1/exe.
Below is what I have so far and it works, but I would like to know if there is a more efficient way to do it, for example without having to list the filenames ?
CC := clang
CFLAGS := -Wall
LIB := ../ch1.c
BIN := ../exe/
.PHONY: all clean 1-1 1-2
all: 1-1 1-2
1-1:
cd 1-1 && \
$(CC) $(CFLAGS) program1.c -o $(BIN)program1.exe && \
$(CC) $(CFLAGS) program2.c -o $(BIN)program2.exe && \
1-2:
cd 1-2 && \
$(CC) $(CFLAGS) program3.c $(LIB) -o $(BIN)program3.exe && \
$(CC) $(CFLAGS) program4.c $(LIB) -o $(BIN)program4.exe && \
clean:
rm exe/*
Upvotes: 1
Views: 1336
Reputation: 68
I am assuming that by "efficient" you mean "more generic/automated". Here is the most "efficient" solution I could think of:
CC := gcc
CFLAGS := -Wall
BIN_DIR := exe
SRC_DIRS := $(wildcard *-*)
.PHONY: all clean $(SRC_DIRS)
all: $(SRC_DIRS)
clean:
del /s /q $(BIN_DIR)\*
define SETUP_TARGETS
$(1): $$(patsubst $(1)/%.c,$(BIN_DIR)/%.exe,$$(wildcard $(1)/*.c))
$(BIN_DIR)/%.exe: $(1)/%.c $$(wildcard *.c)
$(CC) $(CFLAGS) $$(addprefix -I ,$$(patsubst %/,%,$$(dir $$^))) $$^ -o $$@
endef
$(foreach target,$(SRC_DIRS),$(eval $(call SETUP_TARGETS,$(target))))
Observations about the makefile:
.exe
, I am assuming that you are running GNU Make on MS-Windows. Hence, I used Command Prompt syntax and .exe
extension.chapter-1/
in this case).TAB
character, not spaces.exe/
already exists and always will be there.*-*
(e.g. 1-1, 1-2, ...) and will create a target for each one.make target
(target is a subdirectory, e.g. 1-1, 1-2, ...) will create one executable in exe/
for each source file in the target subdirectory. I am assuming that each source file has a function main()
.*.c
from the root directory (ch1.c
in this case). I am assuming that these sources do not contain a function main()
.#include
header files from them to your programs.make
and make all
will build all the targets.make clean
will delete every file in exe/
.make: Nothing to be done for '1-1'
.Enjoy :)
Upvotes: 2