I'm attempting to do some string manipulation in a Makefile using the string functions that Make offers. I want to do two conversions on my strings, I have a variable that lists source files similar to:
C_SRCS += \
./src/foo.c \
./src/bar.c \
...
I want to take this string and convert it in a new variable holding all the object files. The Objects will be stored in a different directory, and obvious will have a .o extension instead of the .c. Effectively they should change from:
./src/<file>.c
to
./artifacts/src/<file>.o
I can do this with two rules like:
OBJS1 := $(C_SRCS:%.c=%.o)
OBJS = $(subst ./,./artifacts/,$(OBJS1))
that will work fine, but I was hoping to combine these two rules and remove the intermediate variable. I tried:
OBJS = $($(subst ./,./artifacts/,$(C_SRCS)):%.c=%.o)
and that just left OBJS empty, I thought maybe it would be better if I used two of the exact same function type so I tried:
OBJS = $(subst %.c,%.o,$(subst ./,./artifacts/,$(C_SRCS)))
and that executed the nested rule only and OBJS was set to ./artifacts/src/foo.c ./artifacts/src/bar.c ...
I started reading through some Make documentation, but I can't find anything about nesting string functions. Is it possible to nest string functions in Makefiles? If so what am I doing wrong here?
Yes, you can nest string functions.
You cannot use the shorthand :X=Y notation on the result of a function though.
So when you combined OBJS1 := $(C_SRCS:%.c=%.o) and OBJS = $(subst ./,./artifacts/,$(OBJS1)) you didn't do that correctly (or the obvious way) you did something else. You wrote OBJS = $($(subst ./,./artifacts/,$(C_SRCS)):%.c=%.o) when the obvious (and correct) nesting would have been OBJS = $(subst ./,./artifacts/,$(C_SRCS:%.c=%.o)). (Maybe that was a typo I'm not sure).
The :X=Y shorthand is a shorthand for patsubst (an automatically % prefixed shorthand) not subst which is why your line OBJS = $(subst %.c,%.o,$(subst ./,./artifacts/,$(C_SRCS))) didn't work (consider otherwise that $(C_SRCS:.c=.o) would happen in more places than just the end of the values).
See below for working versions.
C_SRCS += \
./src/foo.c \
./src/bar.c
pv = $(warning $1: $($1))
$(call pv,C_SRCS)
$(warning RAW: $(subst ./,./artifacts/,$(C_SRCS:%.c=%.o)))
OBJS = $(patsubst %.c,%.o,$(subst ./,./artifacts/,$(C_SRCS)))
$(call pv,OBJS)
You're doing it the wrong way around. Just "expand the macro" and replace $(OBJS1) in $(OBJS):
OBJS1 := $(C_SRCS:%.c=%.o)
OBJS = $(subst ./,./artifacts/,$(OBJS1))
becomes:
OBJS = $(subst ./,./artifacts/,$(C_SRCS:%.c=%.o))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With