Checking whether a variable set by the parent exis

2019-09-10 05:59发布

Suppose the following Makefile (see here what it's good for):

target-1-raw:
    target-1-body
target-2-raw:
    target-2-body
target-3-raw:
    target-3-body

%-raw:
    echo "Error: Target $@ does not exist!"    
%:
    @$(MAKE) $@-raw 3>&2 2>&1 1>&3

I am trying to make sure that the user invoked it without the suffix -raw, i.e. like this:

make target-1

and not like this:

make target-1-raw

So, I would like to set a variable in the rule of the target % and check from all other targets that this variable was set:

check:
    #??? If FLAG is not set, then abort with an error message. 

target-1-raw: check
    target-1-body
target-2-raw: check
    target-2-body
target-3-raw: check
    target-3-body

%-raw:
    echo "Error: Target $@ does not exist!"    
%:
    #??? set FLAG
    @$(MAKE) $@-raw 3>&2 2>&1 1>&3

I tried various ways of implementing the lines starting with #??? without success. If I use the facilities of make (such as ifndef and ifeq, then things seem to get evaluated not when I want them to). I tried to use the shell's if [] also, but without success. So, if this is at all possible to achieve, then what tool is my friend here?

标签: bash makefile sh
1条回答
小情绪 Triste *
2楼-- · 2019-09-10 06:12

I am trying to make sure that the user invoked it without the suffix -raw

I don't see what purpose is served by this. make and Makefiles are tools aimed at people whom one normally relies upon to have some idea of what they are doing. There is no particular reason to actively prevent users of your Makefile from performing a build without stream swapping, if that's what they really want.

So, I would like to set a variable in the rule of the target % and check from all other targets that this variable was set.

Not possible. Each logical line in a make recipe is executed by a separate shell. The commands are shell commands, not make commands, and no variables you set via such commands survive the exit of the shell at the completion of the command.

So, if this is at all possible to achieve, then what tool is my friend here?

The main mechanism by which a make recipe can record persistent information for subsequent commands or rules is by writing files. The content of such files or even their mere existence can be used to influence subsequent commands. For a job such as yours, however, that seems likely to be extremely fragile. Nevertheless, it might look like this:

target-1-raw:
    temp='$@'; test -e $${temp%-raw}-check \
      || echo warning: target '$@' made directly
    target-1-body

%-raw:
    echo "Error: Target $@ does not exist!"    
%:
    touch $@-check
    @$(MAKE) $@-raw 3>&2 2>&1 1>&3
    rm $@-check

I assure you, however, that if I ever received a Makefile containing such a construct then I would not be impressed, and my first impulse would be to rip it out. I suggest that you stop viewing your users' freedom as a problem to solve.

查看更多
登录 后发表回答