- 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.logsmake 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 [1] 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 % smakeNothing happens here, I'd have expected a "cp b a" to happen, but
% touch c % smake cp c b cp b aThat 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: [2]
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:
- 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? AM Not sure, but I guess it is brown and it is a cow, so that will do :)]
- A "red cow" has a brown colour
- Brown is a colour
- Is a "red cow" an animal?
- Does a "red cow" have a colour?
Setok I just created a git repository of the stuff I had (doesn't include any of these patches yet). See the smake page for details.