Dreamk33
Dreamk33

Reputation: 247

Makefile : how to increment a variable when you call it? (var++ in bash)

Here is part of my makefile :

LISTEINC = $(DEST)/file.inc $(DEST)/otherfile.inc $(DEST)/anotherfile.inc
compteur = 1

$(DEST)/file: $(LISTEINC)
       #action

$(DEST)/%.inc: $(DEST)/%.jpg
      ./script $< $compteur $(DEST) > $@

How to have the variable compteur at 1 for file, 2 for otherfile, 3 for anotherfile?

$((compteur++)) would work in bash script, but here I really don't know what the equivalent is. I tried many combination of $$ () ++ +1 etc... Nothing worked. Anyone could help me please?

Upvotes: 7

Views: 11265

Answers (3)

Michael Livshin
Michael Livshin

Reputation: 401

Not sure if still relevant (the question is old...), but here is how you increment in GNU Make. Notes:

  1. The only operation that is implemented is increment.
  2. Numbers are reverse decimals with spaces between digits, because Make.
  3. Empty string is a valid zero (the number 0, that is, not the digit).
  4. Presumably this is good enough, because people asking for just the increment usually only want uniqueness.
  5. Obviously the choice of base 10 is entirely arbitrary. Tweak the next_* map to taste.
  6. Rendering "numbers" sans spaces or reversing them are left as exercises for the reader. :)
    define inc
      $(if $(1),$(call inc-rec,$(next_$(firstword $(1))),$(wordlist 2,$(words $(1)),$(1))),1)
    endef
    define inc-rec
      $(if $(filter 0,$(1)),0 $(call inc,$(2)),$(1) $(2))
    endef
    next_0 := 1
    next_1 := 2
    next_2 := 3
    next_3 := 4
    next_4 := 5
    next_5 := 6
    next_6 := 7
    next_7 := 8
    next_8 := 9
    next_9 := 0

Upvotes: 1

Tsyvarev
Tsyvarev

Reputation: 66081

Every time a line of receipt for some target should be evaluated, it uses own shell instance. So you just cannot modify shell variable, used for building file $(DEST)/otherfile.inc, while build file $(DEST)/file.inc.

Instead of shell variable compteur, you may use make variable:

$(DEST)/%.inc: $(DEST)/%.jpg
      ./script $< $(compteur) $(DEST) > $@

which has different values for different targets. It can be achieved by using target-specific variable values technique:

$(DEST)/file.inc: compteur = 1
$(DEST)/otherfile.inc: compteur = 2
$(DEST)/another.inc: compteur = 3

If you want to generate these variable-assignment rules, you are free to use any make facilities, working at parsing stage (as opposite to building stage, when make executes receipts for targets). E.g., you may change variable using shell after each variable-assignment rule is generated:

# For target, given by the first parameter, set current *compteur* value.
# After issuing the rule, issue new value for being assigned to *compteur*.
define set_compteur
$(1): compteur = $(compteur) # Variable-assignment rule
compteur = $(shell echo $$(($(compteur)+1))) # Update variable's value
endef

$(foreach t,$(LISTEINC),$(eval $(call set_compteur, $(t))))

Alternatively, you may create list of possible compteur values once, and use this list while generate variable-assignment rules:

# List of possible indicies in the list *LISTEINC*: 1 2 ...
indicies = $(shell seq $(words $(LISTEINC)))
# Corresponded *compteur* values actually are same as indicies.
compteurs = $(indicies)

# For target, specified with index, given by the first parameter, set corresponded *compteur* value.
define set_compteur
$(word $(1),$(LISTEINC)): compteur = $(word $(1),$(compteurs))
endef

$(foreach i,$(indicies),$(eval $(call set_compteur, $(i))))

Unlike to the first snippet, which parsing stage calls shell for every target in the list LISTEINC, the second snippet calls shell only once (seq command), which is faster.

Upvotes: 4

Bertrand Martel
Bertrand Martel

Reputation: 45432

It can be done with eval :

$(eval compteur=$(shell echo $$(($(compteur)+1))))

From the manual :

The eval function is very special: it allows you to define new makefile constructs that are not constant; which are the result of evaluating other variables and functions. The argument to the eval function is expanded, then the results of that expansion are parsed as makefile syntax. The expanded results can define new make variables, targets, implicit or explicit rules, etc

Upvotes: 12

Related Questions