[Rake-devel] FileTask#needed? and FileTask#timestamp "bug"

Patrick Bennett patrick.bennett at inin.com
Mon Sep 5 22:05:16 EDT 2005

philipp.neubeck at gmx.de wrote:

>so if you do the opposite ( main.cpp is missing => no creation of main.obj ) the problem is that main.obj is simply in a _wrong_ state. the programmer should be able to recognize that there is something missing/wrong and so it should be tried to rebuild the main.obj or (if you say the prerequisites are a must) Rake should through an error.
>ok i think the second would be better: no invokation of main.obj but Rake throwing an error. missing prerequisites should be counted as missing.
>so let me repeat the example with main.cpp and main.obj as i think it should be:
>file main.cpp
>file main.obj => main.cpp
>(let out timestamp) main.obj get's invoked (not yet excecuted), so rake first tries to create the prerequisites. the file task main.cpp sees that the file is missing and says it is "needed" (see the FileTask#needed? code). file main.cpp gets invoked and excecuted but since there's no attached action rake throughs an error, that it can't create a needed file.
>the timestamp stuff should reflect this, so timestamp of a missing file must return "now" as it is always needed to be invoked.
This isn't the behavior you would want with auto-generated dependencies 
of header files.  I guess it wouldn't really matter in my case since the 
prerequisite tasks my dependency generation code creates are special 
'Header' tasks which have different timestamp and needed? behaviors.  
It's quite possible I changed the base FileTask code originally because 
I hadn't defined CSourceFileTask (which know when to generate 
dependencies) and HeaderFileTask classes yet.  In case you're 
interested, I also ended up modifying all base 'timestamp' methods to 
take a parent task name parameter so that a task like CSourceFileTask 
could check if it was newer than its parent and bypass having to 
generate dependencies if so (why scan all headers for main.cpp if 
main.cpp got changed and is newer than main.o ?).

>i see the point you state with the platform dependend prerequisites. and therefore you would need something like optional dependencies. but i don't see a way how to distinguish optional and needed prerequisites on c++ site, because (i think you did that too) the dependencies are autogenerated by gcc.
Well, actually, my code generates the dependencies and does it far 
faster than any other dependency system I've used.  Since my dependency 
scanner doesn't try to be a full preprocessor (there's hardly any reason 
honestly) and simply greps for #include lines, it pulls in *all* 
possible include's.  Of course, my scanner has to replicate the search 
order and file resolution rules of the preprocessor, but that was easy.  
So the net effect is, worst case, if say a header for a windows-only 
compiles changed, it would still cause the source files dependent on 
that header to recompile under linux.  Of course, unless you're doing 
full cross-compilation from the same build area, this really isn't an 
issue.  We happen to be doing so, but I'd much prefer the occasional 
over-zealous recompile of a module then having things skipped that 
should've been recompiled.  Of course, the fact that all #include's are 
defined as as prerequisites makes it imperative for a missing file to 
not be treated as 'now' as it would *always* cause recompilation.

>hmm... or does gcc -MM -MG utilize the precompiler and then read the dependencies? (#include keyword is for the precompiler too) then you should be able to solve this problem with common #defines for your platforms (i think you did this anyway, or you would get compile errors, because of missing includes)
Using the full preprocessor is hopelessly slow for generating 
dependencies (particularly if it has to output to a file before the 
output can be scanned).  A preprocessor step would create 10+MB files 
for almost any source file in one of our projects and take quite a while 
per file.  With the simple regex grep method, it's no more than a second 
or so per file (and previously fetched header dependency trees are 
cached) so it gets faster once its scanned a source file or two.

>anyway, i think all we said is better than the current implementation. because the current throws exceptions and you don't know where they come from.

*Patrick Bennett* | Software Engineer
phone & fax +1.317.715.8302 | patrick.bennett at inin.com
*Interactive Intelligence Inc.*
Deliberately Innovative
www.inin.com <http://www.inin.com/>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://rubyforge.org/pipermail/rake-devel/attachments/20050905/4197d281/attachment-0001.htm

More information about the Rake-devel mailing list