Hi,
I tried to execute the examples which came with rake.
When executing Rakefile1 then gcc gets invoked even when main is properly build.
However rake -f Rakefile2 works fine.
Is it an error or do I miss anything?
Manfred
Hi,
I tried to execute the examples which came with rake.
When executing Rakefile1 then gcc gets invoked even when main is properly build.
However rake -f Rakefile2 works fine.
Is it an error or do I miss anything?
Manfred
Its an error in Rakefile1 in the examples. I have a file task (“main”)
depending on a normal task (:obj). Since the time stamp of normal tasks
is always the current time, “main” is always out of date. (Perhaps this
approach needs some more thought. This means a file task should never
depend on a non-file task … an unfortunate restriction.)
Apply the attached patch to correct Rakefile1.
I’ll have to review the examples. I intended to write some annotations
to the examples but haven’t done that yet.
Thanks for the feedback.
On Fri, 2003-03-21 at 14:44, Manfred wrote:
Hi,
I tried to execute the examples which came with rake.
When executing Rakefile1 then gcc gets invoked even when main is properly build.
However rake -f Rakefile2 works fine.
Is it an error or do I miss anything?
“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)
— Rakefile1 19 Mar 2003 12:48:05 -0000 1.1
+++ Rakefile1 21 Mar 2003 23:47:43 -0000
@@ -17,9 +17,10 @@
Sys.run “gcc #{src} -c -o #{t.name}”
end
-task :obj => [“a.o”, “b.o”, “main.o”]
+OBJFILES = [“a.o”, “b.o”, “main.o”]
+task :obj => OBJFILES
-file “main” => [:obj] do |t|
+file “main” => OBJFILES do |t|
Sys.run “gcc -o #{t.name} main.o a.o b.o”
end
Jim,
“Jim Weirich” jweirich@one.net wrote in message
Apply the attached patch to correct Rakefile1.
Sorry for being ignorant about this, but how do I “apply” this patch.
Is there any utility that does this automatically or do I have to do it
manually.
On the same note, how did you generate this output. Some form of “diff” ?
— Rakefile1 19 Mar 2003 12:48:05 -0000 1.1
+++ Rakefile1 21 Mar 2003 23:47:43 -0000
@@ -17,9 +17,10 @@
Sys.run “gcc #{src} -c -o #{t.name}”
end-task :obj => [“a.o”, “b.o”, “main.o”]
+OBJFILES = [“a.o”, “b.o”, “main.o”]
+task :obj => OBJFILES-file “main” => [:obj] do |t|
+file “main” => OBJFILES do |t|
Sys.run “gcc -o #{t.name} main.o a.o b.o”
end
Thanks,
– shanko
Jim Weirich jweirich@one.net wrote in message news:1048292858.3875.140.camel@traken…
On Fri, 2003-03-21 at 14:44, Manfred wrote:
Hi,
I tried to execute the examples which came with rake.
When executing Rakefile1 then gcc gets invoked even when main is properly build.
However rake -f Rakefile2 works fine.
Is it an error or do I miss anything?
Its an error in Rakefile1 in the examples. I have a file task (“main”)
depending on a normal task (:obj). Since the time stamp of normal tasks
is always the current time, “main” is always out of date. (Perhaps this
approach needs some more thought. This means a file task should never
depend on a non-file task … an unfortunate restriction.)Apply the attached patch to correct Rakefile1.
I’ll have to review the examples. I intended to write some annotations
to the examples but haven’t done that yet.Thanks for the feedback.
–
– Jim Weirich jweirich@one.net http://w3.one.net/~jweirich“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)— Rakefile1 19 Mar 2003 12:48:05 -0000 1.1
+++ Rakefile1 21 Mar 2003 23:47:43 -0000
@@ -17,9 +17,10 @@
Sys.run “gcc #{src} -c -o #{t.name}”
end-task :obj => [“a.o”, “b.o”, “main.o”]
+OBJFILES = [“a.o”, “b.o”, “main.o”]
+task :obj => OBJFILES-file “main” => [:obj] do |t|
+file “main” => OBJFILES do |t|
Sys.run “gcc -o #{t.name} main.o a.o b.o”
end
Jim,
Thanks a lot. That did the trick.
I like rake very much. Last year I tried some of the make-alternatives
but all those were in some way still unsatisfactory for what I was
looking for.
Xake + ruby = rake is a perfect match. You did a great job. Thanks.
Manfred
Apply the attached patch to correct Rakefile1.
…
— Rakefile1 19 Mar 2003 12:48:05 -0000 1.1
+++ Rakefile1 21 Mar 2003 23:47:43 -0000
@@ -17,9 +17,10 @@
Sys.run “gcc #{src} -c -o #{t.name}”
end-task :obj => [“a.o”, “b.o”, “main.o”]
+OBJFILES = [“a.o”, “b.o”, “main.o”]
+task :obj => OBJFILES-file “main” => [:obj] do |t|
+file “main” => OBJFILES do |t|
Sys.run “gcc -o #{t.name} main.o a.o b.o”
end
With rake-0.2.1 I can’t duplicate the original problem, i.e. I can set it
back to “main” => [:obj] and it works:
$ rm main
$ rake
(in /v/build/rake-0.2.1/doc/example)
gcc -o main main.o a.o b.o
$ rake
(in /v/build/rake-0.2.1/doc/example)
$
However, where you have
Sys.run “gcc -o #{t.name} main.o a.o b.o”
I thought it might be better to put
Sys.run "gcc -o #{t.name} #{OBJFILES.join(' ')}"
since you’ve factored out the filenames anyway. The syntax is somehow
unattractive. Assuming you keep ‘file “main” => OBJFILES’ then I notice you
can do
#{t.prerequisites.join(’ ')}
but that won’t work in the general case where the dependencies may come in
groups (say .o files and .a files) which need handling differently.
Hmm, how about some sugar:
#{t.sources(‘.o’)}
i.e. the first parameter is a suffix or regex, and an optional second
parameter if you want to join with something other than space. But if you
set “main” => [:obj] instead of “main” => OBJFILES then it would need to
traverse a level down to find the actual source files.
One other idea. If you have a large project with components in
subdirectories, it would be really cool if you could have a top-level
Rakefile which includes the sub-Rakefiles and generates a single dependency
graph automatically. As far as I can see all you would need is something
like
require 'subdir/Rakefile'
except that all the files/dependencies would need ‘subdir’ prepended to them
in the global dependency graph (perhaps using a global $prefix). Or maybe the
graph should be built with only absolute pathnames in it? so
file “foo”
would generate basename($0)+“foo” ?
There’s an excellent article here about why this could work extremely well
for large projects:
http://www.tip.net.au/~millerp/rmch/recu-make-cons-harm.html
Regards,
Brian.
P.S. I’m not sure I like the searching for Rakefile in parent directories.
If I am in doc/example and type ‘rake’ then I get the testsuite built; it’s
a bit unexpected!
On Sat, Mar 22, 2003 at 09:23:21AM +0900, Jim Weirich wrote:
Shashank,
Sorry for being ignorant about this, but how do I “apply”
this patch. Is there any utility that does this
automatically or do I have to do it manually.
The Unix "patch" command can apply this patch. See the man page for
more information.
On the same note, how did you generate this output.
Some form of “diff” ?
diff -u
Hope this helps!
- Warren Brown
Jim Weirich jweirich@one.net wrote in message news:1048292858.3875.140.camel@traken…
[…]Since the time stamp of normal tasks
is always the current time, “main” is always out of date. (Perhaps this
approach needs some more thought. This means a file task should never
depend on a non-file task … an unfortunate restriction.)
Jim,
Thanks a lot. That did the trick.
I’ve uploaded version 0.2.1 of rake that modifies the way timestamps for
non-file tasks are calculated. Essentially non-file tasks will take on
the latest timestamp of their prerequisites (it will default to the
current time if there are no prereqs). The original example will now
work with 0.2.1, and I think this behavior is more intuitive, at the
cost of making the timestamp more expensive to calculate.
On Sat, 2003-03-22 at 03:07, Manfred wrote:
“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)
With rake-0.2.1 I can’t duplicate the original problem, i.e. I can set it
back to “main” => [:obj] and it works:
[… thoughts on object files and prerequisites elided …]
Hmm, how about some sugar:
#{t.sources(‘.o’)}
These are some good thoughts. Before I make any changes in this area,
I’m going to think the problem through and experiment with Rake on
projects that are a bit larger. The suggestion sounds promising
however. Thanks.
One other idea. If you have a large project with components in
subdirectories, it would be really cool if you could have a top-level
Rakefile which includes the sub-Rakefiles and generates a single dependency
graph automatically. As far as I can see all you would need is something
likerequire 'subdir/Rakefile'
except that all the files/dependencies would need ‘subdir’ prepended to them
in the global dependency graph (perhaps using a global $prefix). Or maybe the
graph should be built with only absolute pathnames in it? so
file “foo”
would generate basename($0)+“foo” ?There’s an excellent article here about why this could work extremely well
for large projects:
http://www.tip.net.au/~millerp/rmch/recu-make-cons-harm.html
In general, I prefer to see a single Rakefile at the top of a project
tree, rather than a bunch of little rakefiles scattered about. In part,
this preference was inspired by the “Recursive Make Considered Harmful”
article that you reference (although its been a long time since I read
it, I should review it again in light of Rake).
If all we are doing with the sub-directory rakefile is record
dependencies, then there are several ways of handling it. For example
(1) Record dependencies in a rakefile in each subdirectory and
recursively include them.
(2) Calculate and append the dependencies to a master Rakefile.
(3) Calculate and store the dependencies in a single file, but separate
from the master Rakefile.
(4) Recalculate the dependencies dynamically each time Rake is invoked.
(5) Calculate and store the dependencies in a serialized format (e.g.
using Marshall or PStore).
I’ve done both (2) and (3) using Makefiles and both would work with
Rake. (4) is nice that you never have to ask for the dependecies to be
regenerated, but I’m afraid that recalculating the dependencies on each
invocation would be annoyingly slow. (5) is an interesting idea that
currently can’t be done in Make, but might require some refactoring so
that dependencies could be stored outside of task definitions.
I’m not ready to dictate which method can be used, but am willing to
make sure that Rake supports whatever style the developer chooses.
P.S. I’m not sure I like the searching for Rakefile in parent directories.
If I am in doc/example and type ‘rake’ then I get the testsuite built; it’s
a bit unexpected!
I got the idea from ant. In real life it would be less confusing
because (1) you would have only a single Rakefile and running rake would
consistently use it no matter where you are in the project tree, or (2)
you have multiple Rakefiles, but they are named the same so you always
get the most local version.
Thanks for the feedback. You’ve certainly given me some things to think
about.
On Sat, 2003-03-22 at 05:30, Brian Candler wrote:
“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)
“Warren Brown” wkb@airmail.net wrote in message
The Unix "patch" command can apply this patch. diff -u Hope this helps!
Oh yes … perfect !
- Warren Brown
Thanks Warren.
Jim Weirich wrote:
I’ve uploaded version 0.2.1 of rake that modifies the way timestamps for
non-file tasks are calculated. Essentially non-file tasks will take on
the latest timestamp of their prerequisites (it will default to the
current time if there are no prereqs). The original example will now
work with 0.2.1, and I think this behavior is more intuitive, at the
cost of making the timestamp more expensive to calculate.
Good idea. This is indeed more intuitive.
Manfred
When you say ‘calculate dependencies’ do you mean like ‘make depend’ - i.e.
running the source code through the preprocessor to determine which
additional files it uses?
I was just thinking about explicit (hand-written) rules. If you have a
subdirectory with certain source files in it, then to me it makes sense to
include the build rules within that directory - especially if that directory
ends up getting grafted into a different project. I don’t think it should be
much less efficient than having a central file.
As for ‘make depend’-type dependencies: fixing that would be a big bonus.
ISTM that whenever you compile foo.c to foo.o, that is the right time also
to determine (and store) the automatic dependencies. gcc -M or -MD gives you
output in Makefile format of course, so it still needs to be parsed - but
sticking it into a serialised object seems a very good way to make it
persist (whether that be one per directory, or one per project)
Doing it this way would mean never having to do a ‘make depend’!
Regards,
Brian.
On Sat, Mar 22, 2003 at 10:19:41PM +0900, Jim Weirich wrote:
If all we are doing with the sub-directory rakefile is record
dependencies, then there are several ways of handling it. For example(1) Record dependencies in a rakefile in each subdirectory and
recursively include them.
(2) Calculate and append the dependencies to a master Rakefile.
(3) Calculate and store the dependencies in a single file, but separate
from the master Rakefile.
(4) Recalculate the dependencies dynamically each time Rake is invoked.
(5) Calculate and store the dependencies in a serialized format (e.g.
using Marshall or PStore).
Oops, missed that first time round
It’s no more expensive to calculate than listing the dependencies
explicitly. But I think it could be worth caching; say for example you have
1000 source files, each of which depends on
task :includes => [‘header1.h’, ‘header2.h’, ‘header3.h’ …]
then you have N*M stat() calls to do, even if everything is up to date.
Regards,
Brian.
On Sat, Mar 22, 2003 at 06:47:23PM +0900, Manfred Lotz wrote:
I’ve uploaded version 0.2.1 of rake that modifies the way timestamps for
non-file tasks are calculated. Essentially non-file tasks will take on
the latest timestamp of their prerequisites (it will default to the
current time if there are no prereqs). The original example will now
work with 0.2.1, and I think this behavior is more intuitive, at the
cost of making the timestamp more expensive to calculate.Good idea. This is indeed more intuitive.
When you say ‘calculate dependencies’ do you mean like ‘make depend’ - i.e.
running the source code through the preprocessor to determine which
additional files it uses?
Yes. I’m a strong believer in letting the computer figure out
bookkeeping details.
I was just thinking about explicit (hand-written) rules. If you have a
subdirectory with certain source files in it, then to me it makes sense to
include the build rules within that directory - especially if that directory
ends up getting grafted into a different project. I don’t think it should be
much less efficient than having a central file.
True. Actually, I just reread the “Recursive Make Considered Harmful”
article and there are a lot of suggestions there that I think would be
benificial. The article premotes dependency files in each subdirectory
that are automatically rebuilt. It would be a good goal to strive to
make this easy in Rake.
On Sat, 2003-03-22 at 08:45, Brian Candler wrote:
“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)
I’m a little worried that caching timestamps may miss some
dependencies. I’ll have to think this through. My worries may be
misplaced.
On Sat, 2003-03-22 at 05:39, Brian Candler wrote:
It’s no more expensive to calculate than listing the dependencies
explicitly. But I think it could be worth caching; say for example you have
1000 source files, each of which depends ontask :includes => [‘header1.h’, ‘header2.h’, ‘header3.h’ …]
then you have N*M stat() calls to do, even if everything is up to date.
“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)
I never said it was easy
AFAICS if Task#timestamp is defined as max(@prerequisites.timestamps) then
changing any timestamp means invalidating or updating the timestamps of
those tasks which have this one as a prerequisite, recursively. Doing that
efficiently might mean changing the data structures. But if done, I think
timestamp can become an instance variable.
Incidentally, I just noticed:
def timestamp
File.new(name.to_s).mtime
end
Wouldn’t File.stat(name.to_s).mtime be better? File.new actually opens the
file in read mode, I believe.
Regards,
Brian.
On Sat, Mar 22, 2003 at 11:14:48PM +0900, Jim Weirich wrote:
On Sat, 2003-03-22 at 05:39, Brian Candler wrote:
It’s no more expensive to calculate than listing the dependencies
explicitly. But I think it could be worth caching; say for example you have
1000 source files, each of which depends ontask :includes => [‘header1.h’, ‘header2.h’, ‘header3.h’ …]
then you have N*M stat() calls to do, even if everything is up to date.
I’m a little worried that caching timestamps may miss some
dependencies. I’ll have to think this through. My worries may be
misplaced.