2

I want to declare a variable using a for from bash in a makefile. That's what I tried:

SRCS="path/to/foo.c path/to/boo.c path/to/bar.c"
OBJS=$(for file in $SRCS; do TEMP="$TEMP $(basename $file .c).o"; done; echo $TEMP)

This command:

for file in $SRCS; do TEMP="$TEMP $(basename $file .c).o"; done

works on bash when echoing TEMP. But OBJS in makefile is empty. What am I missing here?

Desired output:

foo.o boo.o bar.o
4
  • How do you plan to use the variables? Using the internal macro $% to get foo.o when the recipe is applied to foo.c is probably cleaner than trying to build the lists yourself. Commented Mar 28, 2018 at 17:32
  • This way: gcc -shared -lm -o output $(OBJS) Commented Mar 28, 2018 at 17:34
  • 3
    If you are using GNU make, then OBJS := $(patsubst %.c,%.o,$(SRCS)) might be what you want. Commented Mar 28, 2018 at 17:50
  • OP was looking to strip the path name as well, so it would be OBJS := $(notdir $(patsubst %.c,%.o,$(SRCS)) or $(notdir $(SRCS:.c=.o)) Commented Mar 28, 2018 at 18:41

1 Answer 1

2

First of all there's better ways to do this without using bash's for. You could use the make constructs to generate these lists. See the documentation on $(notdir), $(addprefix...) and $(addsuffix ...)

However, to answer your question on this particular example:

First, you are putting quotes around sources. Make does not interpret quotes as special characters, and thus SRCS will expand to "path/to/foo.c path/to/boo.c path/to/bar.c" (including the quotes). This will mess up your for loop later on.

The next thing is the reference to $SRCS -- make will interpret this as $S followed by the literal RCS (which is not what you want). You have to use braces around multi0letter variables in bash as so -- $(SRCS)

Next, TEMP=$TEMP.... When make sees $TEMP, it will immediately attempt to expand it. Because TEMP is not set to anything in the make context, it will expand to a null string -- this is before it invokes the bash shell... What you wanted to do in this case is use $$TEMP, which make will expand to $TEMP.

The following does what you want: note the $(info) lines are just for debugging.

SRCS:=path/to/foo.c path/to/boo.c path/to/bar.c
OBJS:=$(shell for file in $(SRCS); do TEMP="$$TEMP $$(basename $$file .c).o"; done; echo $$TEMP)
$(info for file in $(SRCS); do TEMP="$$TEMP $$(basename $$file .c).o"; done; echo $$TEMP)    
$(info OBJS=$(OBJS))

If you wanted to do this in makefile without bash or sh, you might try:

OBJS:=$(notdir $(SRCS:.c=.o))

Note: this is gnu-make specific syntax and may not work on other makes.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.