Reputation: 365
In the following makefile for loop, how can I edit the string, that the i variable represents, with a pattern substitution in the middle of the string? In my case, I wish to replace any / character in the string with a _ character.
for i in $(MODULES:%.cpp=%); do \
g++ -c Sources/$$i.cpp -o Build/$$i.o; \
done
For example if MODULES = Directory/File.cpp then the inner line should expand to
g++ -c Sources/Directory/File.cpp -o Build/Directory_File.o
Upvotes: 0
Views: 772
Reputation: 28965
This answer is valid only with GNU make and bash.
Simple bash substitution (${parameter/pattern/string}
) in the context of a make recipe (double $
):
for i in $(MODULES:%.cpp=%); do \
g++ -c Sources/$$i.cpp -o Build/$${i//\//_}.o; \
done
Warning: this works only if the shell used by make is bash. So, add maybe a:
SHELL := bash
at the beginning of your Makefile.
Explanation:
${i/X/_}
expands as the value of variable i
in which the first occurrence of X
is replaced by _
.${i//X/_}
expands as the value of variable i
in which all occurrences of X
are replaced by _
.X
is the /
character and it must be escaped (\/
): ${i//\//_}
.Note that there is probably a less bash and more make way to do the same. Something like:
SRCS := $(shell find Sources -type f -name *.cpp)
OBJS :=
define OBJ_rule
obj := Build/$$(subst /,_,$$(patsubst Sources/%.cpp,%,$(1))).o
OBJS += $$(obj)
$$(obj): $(1)
g++ -c $$< -o $$@
endef
$(foreach s,$(SRCS),$(eval $(call OBJ_rule,$(s))))
.PHONY: objs
objs: $(OBJS)
Which instantiates one rule per module and should do the same... with the significant advantage that, when you type make objs
, only the outdated object files are rebuilt. But it's a bit more tricky.
Upvotes: 1