2003-11-20 [VI] I just love [smake]. Mostly because I have tclsh across all the platforms I work on. I thought there was something called "Jam", but couldn't find it. In any case I like the simple smake to the more complex (and more capable) [bras]. Some notes about smake follow. I have also emailed the author. * The documentation describes "uptarget". The command is really "upTarget", note the uppercase T * In the code after the depend, the variable "target" is the current target being worked on. * If a target doesn't exist and if all the dependencies are up-to-date, then smake doesn't run the rule, which is counterintuitive, more on this below. * stdout and stderr redirection on the exec doesn't work. ---- Hm, didn't see your email. Maybe it got mixed up in all the spam :P Will look at these issues when I have a bit of time. --[Setok] ---- When a target doesn't exist but all the dependencies are up-to-date, smake doesn't run the rule, which is counter-intuitive. e.g. target a { depend {b.o c.o} { link a [list b.o c.o] } } Here you would expect that if a doesn't exist, but b.o and c.o are up-to-date, then the link will run. That doesn't seem to happen for me (I could be just using it wrong). In any case, to fix this here's what I added: Just before this: if {$update} { uplevel 1 $op uplevel 1 {set targetUpdate 1} } in the proc "depend", I added this: if !$update { set thistarget [lindex $SmakeTargetPath end] if ![file exists $thistarget] { dputs 3 "Target $thistarget hasn't been made yet, update" set update 1 } } Hope this helps someone! 2003-11-20 [VI] : A possible cleaner way to do the set this target is to do it like this: if !$update { upvar target thistarget if ![file exists $thistarget] { dputs 3 "Target $thistarget hasn't been made yet, update" set update 1 } } ---- 2003-11-20 [VI] : stdout and stderr redirection doesn't work. I often write a command like exec grep -n Error $logfile > errors.log smake nicely renames exec and prints the line before executing, but in this case the redirection doesn't work. To fix that, I change: eval "exec_old $args >@ stdout 2>@ stderr" to just eval "exec_old $args" I'm not sure why the >@ and 2>@ are there. When would it be needed? ---- 2003-12-03 [VI] : I do know now why 2>@ is required. If you don't do that then the stuff printed to stderr causes the tcl [exec] to think that there's been an error. So like make if we want to be just return code based, then we need to add the 2>@. A naive implementation : proc exec {args} { global TCL_ERROR if {![regexp {>&} $args] && ![regexp {[|][&]} $args] && ![regexp {2>} $args]} { append args " 2>@ stderr" } puts $args set rc [catch { eval "exec_old $args" } errmsg] if {$rc == $TCL_ERROR} { puts stderr "$::errorCode $::errorInfo" error $errmsg } } I also found that sometimes I have stuff that I want to print the stuff I'm doing in Tcl to the stdout because many things that were external commands in make become internal. e.g. file mkdir. So I added another trivial proc: proc tcl {args} { puts $args eval $args } So I can mix exec and tcl calls in my commands and everything gets printed... Should the eval above really be uplevel? And perhaps there's a better way of writing those three regexps in that expression.. ---- 2003-12-19 [VI] I also like the way make lets you set variables on the command line, so: } elseif {[string equal $arg "--version"]} { # Show version puts $SmakeVersion exit } elseif {[regexp {^(.*)=(.*)$} $arg => name value]} { set ::$name $value } else { set parsed_args [lappend $parsed_args $arg] } The two lines starting with the regexp are added to the parse_opt proc. ---- 2003-12-26 [VI] Some bright guy added this line, saying this: TMK [http://www.tmk-site.org] is also very capable and easy to use. in the middle of a paragraph which I wrote with MY name in the beginning. I have never used TMK and do not have any opinion on it. I rather resent somebody putting a statement like I wrote it. Feel free to add a paragraph, or a few paragraphs or a whole page anywhere, but please don't make it sound like it came from me! ---- 2004-04-27 [VI] Two more features of make that I like. One is the ability to define variables on the command line the second is to have multiple targets. The original code uses a variable value as the first argument to lappend, which I think is not the intent: In parse_opt, replace: } else { set parsed_args [lappend $parsed_args $arg] } with: } elseif {[regexp {^(.*)=(.*)$} $arg => name value]} { set ::$name $value } else { lappend parsed_args $arg } The first branch allows for VAR=value on the command line. For multiple targets you also need to change (towards the end of smake.tcl) set target [lindex $argv 0] to: set target $argv ---- 2004-08-04 [VI] another bug. If a name exists as a target, then any file depending on this target is not rebuilt, unless this is rebuilt. An example is clearer target a { depend {b} { exec cp b a } } target b { depend {c} { exec cp c b } } . % touch c % smake cp c b cp b a % touch b % smake Nothing happens here, I'd have expected a "cp b a" to happen, but % touch c % smake cp c b cp b a That is because c isn't a target, but b is. The fix is to add these in the proc depend. The first three lines below already exist. the next 7 are new set update [expr $update || [execTargetCode [convertTargetToProc $target] $target]] if {!$update && [file exists $thistarget]} { upvar target thistarget if {[file mtime $thistarget] < [file mtime $target]} { dputs 2 "target $target wasn't rebuilt but is newer than $thistarget" set update 1 } } ---- OCZ (5 aout 2004) I suggere to look at another method of construction of make which I have program on the site: [http://www.larochelle-innovation.com/tcltk/609] ---- 2004-08-06 [VI] Thanks for the pointer. Nice. Even with my limited french. But I think smake is still cool. And the makefiles look so much like tcl. so much like tcl. ---- [AM] I have taken an interest in smake - for various reasons, mostly having to do with a wish to automate all manner of things in a project. I read the source code, wonderfully compact, and I came up with a bunch of ideas to enhance it: * The implementation of the compile and link commands is a bit UNIX-centric. A port to Windows (using MSVC as the compiler/linker tool chain) would involve changing the command lines. Perhaps via a configuration file? * You could easily use smake in a Tcl-based IDE - but then the procedures should be tucked away in a namespace of their own (or perhap a slave interpreter) to prevent interaction with the rest of the code. * As it is basically an implementation of logical inferences, you could also adapt it to search "knowledge bases". This is just a wild, unelaborated idea, but look at this: I have the following facts: * A mammal is an animal * A cow is a mammal * A cow has four legs * A "red cow" is a cow (I do not know the proper English term for "roodbont") [[AMG: Hereford, perhaps?]] * A "red cow" has a brown colour * Brown is a colour We can now ask the following questions: * Is a "red cow" an animal? * Does a "red cow" have a colour? The processing of these questions looks a lot like the dependency tree of a program ... (Oh, one more remark: the examples in the documentation are a trifle out of touch with the text)