I have a Makefile which has two variables:
SOURCE_DIR := ./source
BUILD_DIR := ./build
C_FILES := $(shell find $(SOURCE_DIR) -name '*.c')
BIN_FILES := $(patsubst $(SOURCE_DIR)%.c,$(BUILD_DIR)%, $(C_FILES))
Both $(C_FILES)
and $(BIN_FILES)
are two strings. One with the paths of all the existing .c
files separated by SPACE and another is a string of all corresponding executable files (which have no extension and are yet to be generated)
My next intended step is to write a rule that builds a binary for each "element" in BIN_FILES using its corresponding "element" in C_FILES. However, I am very new to make and I still cannot figure out how to write a rule that can iterate over a pair of variables.
I tried:
$(BIN_FILES): %:%.c
cc $< -o $@
all: $(BIN_FILES)
But when I ran make all
it kept insisting that build/ch01/hello.c
which makes sense since it is looking for ./build/...
like patterns. How do I make make
look for s./ource/...
patterns for prerequisites, and at the same time build the executable in ./build/..
Any help on generating and calling the rules using the variables $(BIN_FILES)
and $(C_FILES)
would be much appreciated.
In situations like this, we're looking for a 'pattern' rule.
The pattern is:
To make ./build/<file>
we depend on ./source/<file.c>
So the pattern rule would look like:
$(BUILD_DIR)/%: $(SOURCE_DIR)/%.c
if the two %
signs match up in terms of source and destination, then it will be able to build.
So if we have ./source/a.c
we want to end up with ./build/a
The entirety of the makefile for this would look something like:
SOURCE_DIR := ./source
BUILD_DIR := ./build
C_FILES := $(shell find $(SOURCE_DIR) -name '*.c')
BIN_FILES := $(patsubst $(SOURCE_DIR)%.c,$(BUILD_DIR)%, $(C_FILES))
all: $(BIN_FILES)
$(BUILD_DIR)/%: $(SOURCE_DIR)/%.c
$(CC) $< -o $@