Search code examples
bashshellmakefileeval

How to use eval in Makefile


I am learning makefile. I have problem in understanding usage of eval in makefile.

This is my Makefile:

testt:
    @R=5
    $(eval $(echo $R))

when I run make testt, nothing is displayed. Could you please show me what is the reason ? Thanks a lot.


Solution

  • When make reads in your makefile, it stores the block of shell commands for testt as a single recursively expanded variable. Nothing untoward has happened yet.

    After reading in your makefile, make now decides what to build. testt is the first target so it has a go at that. You have no file called testt in your file system, so make decides it has to run the block of shell commands.

    At this point it tries to expand the variable that it squirreled away earlier. It starts off with

    @R=5
    $(eval $(echo $R))
    

    First is expands $R. The expansion is empty, leaving make with

    @R=5
    $(eval $(echo ))
    

    Now, it expands $(echo ). This variable does not exist either, and make has got as far as

    @R=5
    $(eval )
    

    Make does know about $(eval ...), but its output is always empty. So now make has

    @R=5
    

    The expansion is finished, and make now passes each line separately and sequentially to fresh invocations of the shell, checking the return code of each. So, the shell sees R=5. This command (a simple assignment to a shell variable) completes without error. Make does not echo this to stdout due to the @ prefix. All done.

    Always run make with --warn-undefined-variables.

    $ make --warn-undefined-variables
    Makefile:3: warning: undefined variable `R'
    Makefile:3: warning: undefined variable `echo '
    make: Nothing to be done for `testt'.
    

    (Notice that extra space at the end of the variable name: `echo ' (yes, you can have variable names that include spaces).)

    Oh, and while I'm at it, $(eval ...) is truly useful, but do not use it in shell commands. It rarely makes sense.