views:

599

answers:

3

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  A: 

$(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)
laalto
Still, that would invoke the shell command each time the variable is accessed. That's not nice when you're doing a few hundred file updates :)
Christoffer
+1  A: 

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
Christoffer
+1  A: 

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

Eric Melski