Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change a make variable, and call another rule, from a recipe in same Makefile?

I have already seen How to manually call another target from a make target?, but my question is a bit different; consider this example (note, stackoverflow.com changes the tabs to spaces in display; but tabs are preserved in source, if you try to edit):

TEXENGINE=pdflatex

pdflatex:
    echo the engine is $(TEXENGINE)

lualatex:
    TEXENGINE=lualatex
    echo Here I want to call the pdflatex rule, to check $(TEXENGINE) there!

Here, if I run the default target (pdflatex), I get the expected output:

$ make pdflatex 
echo the engine is pdflatex
the engine is pdflatex

But, with the target lualatex, I want to:

  • change the make variable TEXENGINE to lualatex, and then
  • call the same code as in pdflatex (which uses it).

How could I do that?

Clearly, in my lualatex rule I don't even manage to change the TEXENGINE variable, because I get this when I try it:

$ make lualatex 
TEXENGINE=lualatex
echo Here I want to call the pdflatex rule, to check pdflatex there!
Here I want to call the pdflatex rule, to check pdflatex there!

... so I would really like to know if something like this is possible in Makefiles.

like image 942
sdaau Avatar asked Oct 15 '14 12:10

sdaau


People also ask

Can you have multiple rules in a makefile?

There can only be one recipe to be executed for a file. If more than one rule gives a recipe for the same file, make uses the last one given and prints an error message. (As a special case, if the file's name begins with a dot, no error message is printed.

What is $@ in makefile?

The variable $@ represents the name of the target and $< represents the first prerequisite required to create the output file.

How do I call a target in makefile?

When you type make or make [target] , the Make will look through your current directory for a Makefile. This file must be called makefile or Makefile . Make will then look for the corresponding target in the makefile. If you don't provide a target, Make will just run the first target it finds.

What is $( make in makefile?

And in your scenario, $MAKE is used in commands part (recipe) of makefile. It means whenever there is a change in dependency, make executes the command make --no-print-directory post-build in whichever directory you are on.


2 Answers

Use a target-specific variable

There is one more special feature of target-specific variables: when you define a target-specific variable that variable value is also in effect for all prerequisites of this target, and all their prerequisites, etc. (unless those prerequisites override that variable with their own target-specific variable value).

TEXENGINE=pdflatex

pdflatex:
    echo the engine is $(TEXENGINE)

lualatex: TEXENGINE=lualatex
lualatex: pdflatex
    echo Here I want to call the pdflatex rule, to check $(TEXENGINE) there!

The output is:

$ make pdflatex
echo the engine is pdflatex
the engine is pdflatex
$ make lualatex
echo the engine is lualatex
the engine is lualatex
echo Here I want to call the pdflatex rule, to check lualatex there!
Here I want to call the pdflatex rule, to check lualatex there!
like image 198
Jonathan Wakely Avatar answered Oct 04 '22 20:10

Jonathan Wakely


Well, I managed to get to a sort of a workaround, but I don't exactly understand it much - so a more learned answer will be appreciated. For me here, these links helped:

  • Set a variable from within a rule
  • make : rule call rule
  • Passing additional variables from command line to make

So here is the example modified - apparently, to call a rule from a rule afterwards (not as a prerequisite, rather, as a postrequisite), I can only recursively call make, while having the new variable value specified on its command line:

TEXENGINE=pdflatex

pdflatex:
    echo the engine is $(TEXENGINE)

lualatex:
    echo Here I want to call the pdflatex rule, to check $(TEXENGINE) there!
    $(MAKE) TEXENGINE=lualatex pdflatex

The output is somewhat more verbose than I'd like it, but it works:

$ make lualatex 
echo Here I want to call the pdflatex rule, to check pdflatex there!
Here I want to call the pdflatex rule, to check pdflatex there!
make TEXENGINE=lualatex pdflatex
make[1]: Entering directory `/tmp'
echo the engine is lualatex
the engine is lualatex
make[1]: Leaving directory `/tmp'

... which is what I wanted purely command-line interaction-wise, but I know is not the best solution (see @JonathanWakely's comment below)

like image 37
sdaau Avatar answered Oct 04 '22 19:10

sdaau