iter
iter

Reputation: 4313

Extract macro parameters from target name in Makefile

I have a bunch of lines like this in my makefile, in different permutations. I want to automate them with a general rule, so if I type $ make foo-WHATEVER, make knows how to build it from foo.c and relevant -D flags.

foo-PARAMA.o: foo.c
foo-PARAMA.o: CPPFLAGS += -DPARAMA

foo-PARAMA-PARAMB.o: foo.c
foo-PARAMA-PARAMB.o: CPPFLAGS += -DPARAMA -DPARAMB

foo-PARAMA-PARAMB-PARAMC.o: foo.c
foo-PARAMA-PARAMB-PARAMC.o: CPPFLAGS += -DPARAMA -DPARAMB -DPARAMC

Upvotes: 1

Views: 153

Answers (2)

Vroomfondel
Vroomfondel

Reputation: 2898

It looks like you want to do configuration management inside make. The problem is that make itself is not really equipped with such functionality. My guess is that at the time of its invention the extreme diversity of platforms which one day will run some unixoid build system simply wasn't foreseeable - so the main use case was to easily define a rather homogenous build with some small deviations. Now, its 2019 and make is still around and supposedly with a larger user base than ever before. One possible remedy which has the advantage that it doesn't require any other tool is to use gmtt which is a GNUmake library for exactly this configuration purpose. Below I sketch a hypothetical config scenario:

include gmtt/gmtt.mk

PLATFORM := $(shell uname)

# table of platforms with 2 columns. Don't forget that the leading element of every table must be an integer denoting the number of columns!
define AVAILABLE-PLATFORMS :=
2
CYGWIN?NT-4.?     toolX
CYGWIN?NT-10.?    toolY
Linux*            toolZ
FreeBSD           toolXYZ
endef

define ADDITIONAL-FLAGS :=
2
toolX   -Dfoo
toolY   -Dbar
toolZ   -Dbaz
toolXYZ  -Dfoo
toolXYZ  -Dbar
toolXYZ  -Dbaz
endef

# select column 2 from the table line(s) which glob-match the current platform:
USED-TOOL := $(call select,2,$(AVAILABLE-PLATFORMS),$$(call glob-match,$(PLATFORM),$$1))

# now select the right flags for the tool
CFLAGS_OPT := $(call select,2,$(ADDITIONAL-FLAGS),$$(call str-eq,$(USED-TOOL),$$1))

$(info $(USED-TOOL)  Options: $(CFLAGS_OPT))

Admittedly, this is a lemma on Greenspun's tenth rule but the other options (composing configuration information with a handful of external tools) aren't so attractive either.

Upvotes: 0

MadScientist
MadScientist

Reputation: 100946

Well, you can try something like this:

foo-%.o : foo.c
        $(CC) $(CPPFLAGS) $(addprefix -D,$(subst -, ,$*)) $(CFLAGS) -o $@ -c $<

but my suspicion is that you're really going to want to do this for "any source file" not just foo.c. That's much harder because you can't have multiple patterns in a single target or prerequisite.

For that you'll have to know the list of source files up-front and use eval:

SRCS = foo.c bar.c baz.c biz.c

define make-pattern
$1-%.o : $1.c
        $$(CC) $$(CPPFLAGS) $$(addprefix -D,$$(subst -, ,$$*)) $$(CFLAGS) -o $$@ -c $$<
endif

$(foreach S,$(SRCS),$(eval $(call make-pattern,$S)))

Upvotes: 4

Related Questions