0

I am using target-specific variable values in make, they are OK but it's not applied in targets and prerequisites, just in recipes. Here is the Makefile:

CXX := g++
TARGET := exec

BIN.PATH =

SOURCES := $(wildcard *.cpp)
OBJECTS.NAME := $(patsubst %.cpp, %.o, $(SOURCES))
OBJECTS.PATH = $(addprefix $(BIN.PATH)/, $(OBJECTS.NAME))

debug: BIN.PATH = debug
debug: $(TARGET)

$(TARGET): $(OBJECTS.PATH)
    @echo $(BIN.PATH) # debug
    @echo $(OBJECTS.PATH) # debug/main.o
    @echo $^ # /main.o
    # ...

$(BIN.PATH)/%.o: %.cpp
    @echo $@ # /main.o
    # ...

Any ideas how to fix it? Or it's not possible?

Kanony
  • 509
  • 2
  • 12
  • It's unclear what you are asking. You would like the value of `${OBJECTS.PATH)` to be different depending on the target? – tripleee Feb 17 '21 at 07:06
  • @tripleee yes, that is what I want – Kanony Feb 17 '21 at 07:19
  • Please [edit] your question in more detail to explain what you would hope to happen there. This is a reasonably common FAQ anyway; did you search for solutions before asking? There is no simple way to make a variable not have the value you define at the top of the Makefile but there are various hacks which may or may not solve your particular problem. – tripleee Feb 17 '21 at 07:21

2 Answers2

1

Don't reuse targets by adding target-specific variables to dependencies. Only one variant of a given target $(TARGET) will be built. This makes it non-deterministic. Generally, target-specific variables are considered harmful.

The manual:

Be aware that a given prerequisite will only be built once per invocation of make, at most. If the same file is a prerequisite of multiple targets, and each of those targets has a different value for the same target-specific variable, then the first target to be built will cause that prerequisite to be built and the prerequisite will inherit the target-specific value from the first target. It will ignore the target-specific values from any other targets.

Answering the title question, the one way I know to do it is through macros in their glorious readability. Here we change the target, dependencies and output directory:

define build_rule
$1: $2
     $(CC) $< -o $3/$@
endef

$(eval $(call build_rule z.o,z.c,objs.debug))

Such macros are barely supportable and grow into a quite horrible code.

This problem is better solved with pattern rules, but you cannot set arbitrary dependencies there. If you provide an example of what you need to achieve, you could get an example solution.

Victor Sergienko
  • 13,115
  • 3
  • 57
  • 91
1

You may be looking for secondary expansion.

MadScientist
  • 92,819
  • 9
  • 109
  • 136