Recursive tclmakes

tclmake supports recusion in the same way that make does. In addition, its option-rules can be used to avoid having to write recursion explicitly for every target.

Here is a command that performs a recursive clean. It assumes that there is a make-variable named DIRS:

clean:
        @if { [glob -nocomplain *~ core #*# ,*] == "" } {
	    break
	}
	eval file delete [glob -nocomplain *~ core #*# ,*]
        @foreach dir {$(DIRS)} {
	   if { [file isdirectory $dir] && [file executable $dir] } {
		cd $dir
		$(MAKE) $(MFLAGS) $(MAKEVARS) clean
		cd $(MAKEDIR)
	    }
	}
For each sub-directory in the DIRS make-variable, tclmake will call itself recursively. (Each recursive call creates a new Tcl interpreter, to ensure that there are no problems with sub-tclmakes corrupting global state.)

Although this works, it means that every rule that is to be recursively processed needs to be written this way. tclmake has a better solution: use an option-rule (see Option rules). For recursion, the option-rule needed is this:

-r --recursive:
        @foreach dir {$(DIRS)} {
	    if { [file isdirectory $dir] && [file executable $dir] } {
		cd $dir
		$(MAKE) $(MFLAGS) $(MAKEVARS) $!
		cd $(MAKEDIR)
	    }
	}
Now, the recursion can be invoked in one of two ways. First, it can simply be specified on the command line, as in:
    tclmake --recursive clean
Second, it can be added to any rule as a dependency. Thus, the recursive clean rule above is written as
clean: --recursive
        @if { [glob -nocomplain *~ core #*# ,*] == "" } {
	    break
	}
	eval file delete [glob -nocomplain *~ core #*# ,*]
In this case, make clean will recursively clean directories. (Personally, I don't write my rules like this, because I prefer to have the recursion only when I ask for it.)