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?
$(shell)
grabs the output from the shell command. Butread
reads input in a variable (REPLY
by default) and does not output it. Here's a quick fix: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
or
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 ifCVSUSER
is not set.Best regards,
Eric Melski
http://blog.electric-cloud.com