makefilecommand-line-argumentsbuild-system

How do I force a target to be rebuilt if a variable is set?


Assume I have a build-target foo:

foo:foo.c
    $(CC) $(CFLAGS) $(ARGS) -c foo.c -o foo

Now, ARGS is something that I pass on the command line:

$ make ARGS:=-DX=1 foo

So, I need to bypass make's cleverness, because the foo target does not only depend on which files have changed, but also on the value of ARGS.

Is there something in make to do this? My hack (see answer) doesn't seem to be the most elegant but it works. Anything better?


Solution

  • Here is a general solution to your specific problem.

    You want to be able to depend on a variable as a prerequisite. That is, you can make it a prerequisite to any target in your makefile, and when the value of the variable changes, you rebuild those targets.

    Here is a function that does that, you use this function to declare a variable to be dependable, and then you can use it as a prerequisite.

    Note that if the variable is not used on the command line, it will still mean that variable still has a value, namely, the empty string.

    define DEPENDABLE_VAR
    
    .PHONY: phony
    $1: phony
        @if [[ `cat $1 2>&1` != '$($1)' ]]; then \
            echo -n $($1) > $1 ; \
        fi
    
    endef
    
    #declare ARGS to be dependable
    $(eval $(call DEPENDABLE_VAR,ARGS))
    
    
    foo:foo.c ARGS
        $(CC) $(CFLAGS) $(ARGS) -c foo.c -o foo
    

    In fact, we could omit the need for "declaration", and just write a similar function that will make all variables dependable by default. But I don't like that. I prefer that the users that modify makefiles I write, declare their intentions explicitly. It is good for them :)