Search code examples
makefilegnu-make

Makefile variable dependecy execution behaviour


Sorry I'm newbie in makefiles, I've the following makefile

RESULTS_FILE := "benchmark_results"


all: $(RESULTS_FILE)
    @echo "all executed" 

$(RESULTS_FILE):
    touch ${RESULTS_FILE}

clean:
    rm -rf ${RESULTS_FILE}

rt7@rt7-laptop-vivo:~/Desktop$ make
touch "benchmark_results"
all executed
rt7@rt7-laptop-vivo:~/Desktop$ make
touch "benchmark_results"
all executed
rt7@rt7-laptop-vivo:~/Desktop$ make
touch "benchmark_results"
all executed
rt7@rt7-laptop-vivo:~/Desktop$ 

whenever I call make, it always executes the "touch" command to create a benchmark_results file however when I call again, it still executes the command even though the file exists.

when i replace the $(...) with actual file name it's okay, it creates once and doesn't execute second. only prints "all executed"

what am i missing here?

RESULTS_FILE := "benchmark_results"


all: benchmark_results
    @echo "all executed" 

benchmark_results:
    touch benchmark_results

clean:
    rm -rf ${RESULTS_FILE}
rt7@rt7-laptop-vivo:~/Desktop$ make
touch benchmark_results
all executed
rt7@rt7-laptop-vivo:~/Desktop$ make
all executed
rt7@rt7-laptop-vivo:~/Desktop$ make
all executed

Solution

  • That's because this:

    RESULTS_FILE := "benchmark_results"
    
    $(RESULTS_FILE):
            touch ${RESULTS_FILE}
    

    doesn't tell make that you want a file named benchmark_results, which is what your recipe creates. It tells make that you want a file named "benchmark_results", and that's not what your recipe created.

    Make doesn't care about quotes. As far as make is concerned, quotes are just like any other character, an a or an x or whatever.

    If you really did want your filename to contain quotes you need to except them from the shell; this will work:

    RESULTS_FILE := "benchmark_results"
    
    all: $(RESULTS_FILE)
            @echo "all executed" 
    
    $(RESULTS_FILE):
            touch '${RESULTS_FILE}'
    
    clean:
            rm -rf '${RESULTS_FILE}'
    

    But, you most likely didn't want the quotes in which case you should not include them in the makefile variable used to create the target and prerequisite:

    RESULTS_FILE := benchmark_results
    
    all: $(RESULTS_FILE)
            @echo "all executed" 
    
    $(RESULTS_FILE):
            touch '${RESULTS_FILE}'
    
    clean:
            rm -rf '${RESULTS_FILE}'