Read Makefile variable from console if not set

2020-07-22 17:47发布

问题:

I'm updating a Makefile that accesses some resources from an external source, i.e. there is a rule of the form

$(External)/% : 
    cvs up $@

...which works as expected for unrestricted resources. Now, there has been a feature drift, and the external resources requires a more complex login, so the rule has changed to something not too different from this:

$(External)/% : 
    cvs -d :pserver:$(CVSUSER)@cvs-server up $@

...which makes the rule dependent on the variable CVSUSER. The quick and easy way to enforce this would be to abort with a helpful error message if it's undefined. But that's no fun, I'd like to read the variable CVSUSER from console if it's unset by the time it's needed. I naively tried

CVSUSER ?= $(shell read -p "User name: ")

but that obviously does not work :) How would you go about doing this?

回答1:

$(shell) grabs the output from the shell command. But read reads input in a variable (REPLY by default) and does not output it. Here's a quick fix:

CVSUSER ?= $(shell read -p "User name: ";echo $$REPLY)


回答2:

You've already found the solution yourself, but I would suggest that it's a bad practice to create a makefile that is dependent on user interaction at any point after being invoked. Doing so makes the build harder to integrate into automated build systems (eg, CruiseControl, AntHill, etc), and also makes it harder to integrate into distributed build systems (pvmgmake, etc).

A better approach would be to put the check for CVSUSER in a wrapper script that invokes the makefile, then make the makefile exit immediately with an error if CVSUSER is not set.

Best regards,

Eric Melski

http://blog.electric-cloud.com



回答3:

Ah, of course, I need a simply expanded variable, not a recursive one. That way I can let the variable depend on itself and use normal Make utilities to conditionally set it. The conditional assignment implicitly creates a normal (recursive) one, so I need to do either

CVSUSER := $(shell if [ -z $(CVSUSER) ] ; then read -p "User name: " REPLY ; echo $$REPLY ; fi )

or

ifndef CVSUSER
    CVSUSER := $(shell then read -p "User name: " REPLY ; echo $$REPLY ; fi )
endif