Search code examples
makefilegnu-make

How to do integer arithmetic in Makefile prerequisites?


I have a file <n>.x and <n-1>.y and I want to create a dependency in my Makefile. Manually I can write each case as follows:

2.x : 1.y
3.x : 2.y
4.x : 3.y
...

Now I would like to be able to write this more generically:

%.x : <???>.y

Gnu Make doesn't seem to have integer arithmetic on its own and shell expansions ($$(( )), $(shell ) don't seem to work for prerequisites.

Is there a way do this in the Makefile itself or should I use an external script that can generate these dependencies and let the Makefile include them?

Edit: My specific case is dealing with files containing financial transactions. Each file (e.g. 2023.journal) represents transactions for a specific year and includes an opening statement (e.g. 2023_opening.journal), which is based on the closing statement of the year before that. This create a dependency between 2023_opening.journal and 2022.journal.


Solution

  • With GNU make:

    .SECONDEXPANSION:
    %.x: $$(shell expr $$* + 1).y
    

    All rules after the .SECONDEXPANSION special target have their list of prerequisites (and only that) processed twice by make: a first time, as everything else, when make parses the Makefile, plus a second time when make needs to check the prerequisites of a target. Contrary to the first phase, during the second phase the automatic variables are defined.

    So, after the first phase the rule becomes:

    %.x: $(shell expr $* + 1).y
    

    $* is the make automatic variable that expands as the stem in pattern rules. In your case it is the part that matches the %.

    And then, when make needs the list of prerequisites for 1.x, the rule is processed again, $(shell expr $* + 1).y is expanded, and becomes (step by step):

    1. 1.x: $(shell expr 1 + 1).y # $* --> 1
    2. 1.x: 2.y # $(shell expr 1 + 1) --> 2