pablobm
pablobm

Reputation: 2066

Make: variable requirements that depend on the target

Make: variable requirements that depend on the target

I have a Makefile that looks roughly like this:

default: en

.PHONY: default en es

en: NUMBER=number
es: NUMBER=numero

TARGET=$(NUMBER)-word
INTERMEDIATE=$(NUMBER)-tmp

en: number
es: number

number: $(INTERMEDIATE)
  touch $(TARGET)

$(INTERMEDIATE):
  @echo Please provide file $(INTERMEDIATE)
  @exit 1

clean:
  rm *-word *-tmp

To use it, you'd call make en (also a default) or make es. As I see it, this Makefile has two main features:

When I run this, I get the following:

$ make
Please provide file number-tmp
make: *** [-tmp] Error 1

This error suggests to me that variables are resolved one stage too late for what I intend. The failing rule is -tmp, implying it can't tell the value of $(NUMBER) when deciding what rules to run. However it's resolved by the time it's running the rule.

So how could I make this work?

Upvotes: 1

Views: 576

Answers (1)

MadScientist
MadScientist

Reputation: 100781

The documentation is clear that you cannot use target-specific variable values inside targets or prerequisites:

The other exception is target-specific variable values. This feature allows you to define different values for the same variable, based on the target that make is currently building. As with automatic variables, these values are only available within the context of a target’s recipe (and in other target-specific assignments).

There are multiple ways you could handle this. The simplest would be to change the selection to using a variable instead of a target, and use constructed macro names. Suppose you stored the value in the LV variable (you should not use LANG etc. because this is special to the shell), like this:

# Must be set on the command line
LV =

en_NUMBER := number
es_NUMBER := numero

TARGET := $($(LV)_NUMBER)-word
INTERMEDIATE := $($(LV)_NUMBER)-tmp

ifeq ($(TARGET),-word)
  $(error Missing/invalid LV value: '$(LV)')
endif

number: $(INTERMEDIATE)
        touch $(TARGET)

clean:
        rm *-word *-tmp

If you run make LV=en you'll get number-word. If you run make LV=es you'll get numero-word. If you run make (no setting) or make LV=foo (invalid setting) you'll get an error.

There are other ways to do this but without a complete understanding of what you want we can't say for sure.

Upvotes: 4

Related Questions