Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Makefile: Generate rules from a pair of variables

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

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 $@
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading