I want to write a single Makefile
to compile 3 different C files with their own independent targets. All these three files reside in the same directory along with other unused files as well. For example, the directory may contain files a.cpp
, b.cpp
, c.cpp
and d.cpp
. Out of these four, I want the Makefile to only run the build command for the first three files i.e. a.cpp
, b.cpp
and c.cpp
. I'm storing these three files in a variable in the Makefile
. Similarly, I'm also storing their targets in another variable. I want make
to use a.cpp
to compile the target a
, b.cpp
to compile the target b
, and c.cpp
to compile the target c
. This is, however, just an example. The real project has hundereds of targets. Therefore, I do not want to write the rules for each of the targets manually. Is there a way in which I can tell make
to compile each target using it's specific dependency?
To test out different ways to do this, I created a small test project with four files: the Makefile
, aa
, bb
, and cc
. Using the Makefile
, I want to generate the targets a
, b
and c
. All these three targets have only one dependency which is their source file. For example, a
has dependency on aa
. I wrote a test Makefile
to do this which is pasted below:
TARGETS = a b c
DEPS = aa bb cc
$(TARGETS): $(DEPS)
@echo $@ $<
This Makefile
simply prints out the targets and their dependencies. When I execute this Makefile
, I get:
a aa
However, what I want is the following:
a aa
b bb
c cc
How can I accomplish this? Note that I need to specifically build the objects which are stored in the variable TARGETS
and nothing else.
CodePudding user response:
The reason it only builds one target is that make only builds the first target in the makefile by default. In your example after variables are expanded make sees these rules:
a b c: aa bb cc
@echo $@ $<
This is identical (to make) as if you'd written this:
a: aa bb cc
@echo $@ $<
b: aa bb cc
@echo $@ $<
c: aa bb cc
@echo $@ $<
Since a
is the first target, when you type make
it will just build a
. If you want make to build ALL the targets, make your first target something that depends on them all, such as:
TARGETS = a b c
DEPS = aa bb cc
all: $(TARGETS)
$(TARGETS): $(DEPS)
@echo $@ $<
But of course you can see above that this isn't what you want because each target has ALL the prerequisites so when bb
changes, all of a
, b
, and c
are rebuilt.
To do this you need to use a pattern rule. For example if you want to build a
from a.cpp
you can write your makefile like this:
TARGETS = a b c
DEPS = aa bb cc
all: $(TARGETS)
%: %.cpp
@echo $@ $<
CodePudding user response:
If the target name is not derived from the dependency name, you could also do something like this:
TARGETS = a b foo
all:$(TARGETS)
a:aa
b:bb
foo:bar
$(TARGETS):
@echo $@ $<
.PHONY: all
.PHONY: $(TARGETS)
Note that I declared your TARGETS as PHONY as your recipe does not create files with those names.