Rake and timestamps (ideoms or methods?)

P

Phil Tomson

Here's my rakefile:

#begin rakefile
task :default => [ :sim_jtag_tb ] do
puts "done..."
end

task :sim_jtag_tb => [ :build_jtag_tb ] do
puts "simulate it..."
system("ncsim -gui jtag_tb:jtag_tb_behavior")
end

task :build_jtag_tb => [ :build_jtag, :build_jtag_driver ] do
puts "build jtag_tb"
raise "jtag_tb_c build failed " unless system("ncvhdl -linedebug
jtag_tb_c.vhd")
raise "jtag_tb_c build failed " unless system("ncelab
jtag_tb:jtag_tb_behavior -access +r+w")
end

task :build_jtag_driver do
puts "build jtag_driver"
raise "build_jtag_driver failed" unless system("ncvhdl -linedebug
jtag_driver.vhd")
end

task :build_jtag do
puts "build jtag..."
raise "build_jtag failed" unless system("ncvhdl -linedebug jtag.vhd")
end

#end of rakefile

If I don't want to run certain tasks if the file the task is to work on
already is up-to-date (like how make works) how do I tell Rake to not
execute a particular task if the files being worked on are up-to-date? Is
there some built-in way of doing this (by listing the dependent files) or
do you have to do that yourself?

Also, notice the 'raise "blah" system("command")' that I'm doing above. I
want the whole thing to just die if one of the dependencies couldn't be
built (as in make) - is there some builtin method for doing this as well?

Are these things just handled 'ideomatically' in Rake now (as opposed
to their being built-in methods for them)?

Phil
 
J

Jim Weirich

Phil said:
If I don't want to run certain tasks if the file the task is to work on
already is up-to-date (like how make works) how do I tell Rake to not
execute a particular task if the files being worked on are up-to-date?

Normal tasks don't look at timestamps. If the goal of a task is to
create a file, then use a "file" task rather than a "task" task. File
tasks will not trigger if the file named by the task is up to date with
its dependents (which should also be file tasks ... a file task is
always out of date if it depends on a regular task ... think about it).

So a simple file task declaration could look like:

file "copy_of_a.txt" => ["a.txt"] do
cp "a.txt", "copy_of_a.txt"
end

Translation: The copy depends on the original. If the original changes,
then copy the original into the copy.
Also, notice the 'raise "blah" system("command")' that I'm doing above.

As long as your external programs exit with status 0 for normal and
non-zero for errors, then rake will automatically abort. The explicit
tests and raises aren't needed
Here's my rakefile:

And here's my translation. I didn't understand everything you were
doing, so I made some of the following up. But you should be able to
translated it into something appropriate.

I assume that ncvhdl is some compiler-like script and the .vhd file is
the input. I'm assuming that the output file will be a .vhdo file.

I don't know what ncdlab does, so I just made it a normal task. It will
run every time this way.

Here's the file --------------------------------------------------------

#!/usr/bin/env ruby

# This adds a :clean and :clobber target to your Rakefile.
# We also add all intermediate .vhdo files to the clobber target.
require 'rake/clean'
CLOBBER.include("*.vhdo")

# Lets make a list of all the .vhd source files in the directory.

VHD_FILES = FileList['*.vhd']

# And now use that to make a list of all the .vhdo file we
# want to generate.

VHDO_FILES = VHD_FILES.sub(/$/, 'o')

# No change to this task

task :default => [ :sim_jtag_tb ] do
puts "done..."
end

# I use "sh" instead of system. "sh" understands
# when to echo commands in Rake.

task :sim_jtag_tb => [ :build_jtag_tb ] do
puts "simulate it..."
sh %{ncsim -gui jtag_tb:jtag_tb_behavior}
end

# I don't know what ncdlab does, but I'm assuming it needs
# all the .vhdo files to be present before it can run, so
# we make a dependency. Fortunately, we already calculated
# the list of .vhdo files. (Note: If I know what kind of output
# file was produced in this step, I would make this a file task
# with the name of the output file.)

task :build_jtag_tb => VHDO_FILES do
puts "build jtag_tb"
sh %{ncdlab jtag_tb:jtag_tb_behavior -access +r+w}
end

# Here follows the three files that are processed by ncvhdl.
# The jtag_tb_c was bundled with :build_jtag_tb task before,
# but it looks to me like it could be broken out. (I could
# be wrong.) Notice the "output file depends on input file"
# pattern.

file "jtag_tb_c.vhdo" => ["jtag_tb_c.vhd"] do
puts "build jtag_tb_c"
sh %{ncvhdl -linedebug jtag_tb_c.vhd}
end

file "jtag_driver.vhdo" => ["jtag_driver.vhd"] do
puts "build jtag_driver"
sh %{ncvhdl -linedebug jtag_driver.vhd}
end

file "jtag.vhdo" => ["jtag.vhd"] do
puts "build jtag..."
sh %{ncvhdl -linedebug jtag.vhd}
end

End of Rakefile-------------------------------------------------

There is a lot of duplication in those last three file tasks. You could
iterate over VHD_FILES and create the file tasks in a loop. A simpler
way is to write a rule that describes how to turn .vhd files into .vhdo
files, e.g.

rule ".vhdo" => [".vhd"] do |t|
puts "build #{t.source}"
sh %{ncvhdl -linedebug #{t.source}}
end

Use that single rule in place of the final three file tasks. Here is
the output from the mockup I did...

----------------------------------------------------
$ rake
(in /home/jim/pgm/misc/philtomson)
build jtag.vhd
ncvhdl -linedebug jtag.vhd
Creating jtag.vhdo
build jtag_driver.vhd
ncvhdl -linedebug jtag_driver.vhd
Creating jtag_driver.vhdo
build jtag_tb_c.vhd
ncvhdl -linedebug jtag_tb_c.vhd
Creating jtag_tb_c.vhdo
build jtag_tb
ncdlab jtag_tb:jtag_tb_behavior -access +r+w
simulate it...
ncsim -gui jtag_tb:jtag_tb_behavior
done...
$
$
$ rake clobber
(in /home/jim/pgm/misc/philtomson)
rm -r jtag.vhdo
rm -r jtag_driver.vhdo
rm -r jtag_tb_c.vhdo
 
P

Phil Tomson

Phil said:
If I don't want to run certain tasks if the file the task is to work on
already is up-to-date (like how make works) how do I tell Rake to not
execute a particular task if the files being worked on are up-to-date?

Normal tasks don't look at timestamps. If the goal of a task is to
create a file, then use a "file" task rather than a "task" task. File
tasks will not trigger if the file named by the task is up to date with
its dependents (which should also be file tasks ... a file task is
always out of date if it depends on a regular task ... think about it).

So a simple file task declaration could look like:

file "copy_of_a.txt" => ["a.txt"] do
cp "a.txt", "copy_of_a.txt"
end

Translation: The copy depends on the original. If the original changes,
then copy the original into the copy.
Also, notice the 'raise "blah" system("command")' that I'm doing above.

As long as your external programs exit with status 0 for normal and
non-zero for errors, then rake will automatically abort. The explicit
tests and raises aren't needed
Here's my rakefile:

And here's my translation. I didn't understand everything you were
doing, so I made some of the following up. But you should be able to
translated it into something appropriate.

I assume that ncvhdl is some compiler-like script and the .vhd file is
the input. I'm assuming that the output file will be a .vhdo file.

I don't know what ncdlab does, so I just made it a normal task. It will
run every time this way.

Jim,

Thanks, this helps explain a lot about Rake.

You guessed correctly that ncvhdl is a compiler. ncelab is sort of like a
linker. Unfortuneatly each .vhd file doesn't compile to a
corresponding .vhdo file (object file) - that would be nice. All of the
comilation units get put into a package file in a different directory - the
same package file, so each .vhd file gets compiled and added to the
project's .pkg file which makes it hard to figure out if you really need to
recompile a particular .vhd file (not Rake's problem, though, this is a
problem with the compiler/linker tool and it would present a problem for
make as well).


Phil

Here's the file --------------------------------------------------------

#!/usr/bin/env ruby

# This adds a :clean and :clobber target to your Rakefile.
# We also add all intermediate .vhdo files to the clobber target.
require 'rake/clean'
CLOBBER.include("*.vhdo")

# Lets make a list of all the .vhd source files in the directory.

VHD_FILES = FileList['*.vhd']

# And now use that to make a list of all the .vhdo file we
# want to generate.

VHDO_FILES = VHD_FILES.sub(/$/, 'o')

# No change to this task

task :default => [ :sim_jtag_tb ] do
puts "done..."
end

# I use "sh" instead of system. "sh" understands
# when to echo commands in Rake.

task :sim_jtag_tb => [ :build_jtag_tb ] do
puts "simulate it..."
sh %{ncsim -gui jtag_tb:jtag_tb_behavior}
end

# I don't know what ncdlab does, but I'm assuming it needs
# all the .vhdo files to be present before it can run, so
# we make a dependency. Fortunately, we already calculated
# the list of .vhdo files. (Note: If I know what kind of output
# file was produced in this step, I would make this a file task
# with the name of the output file.)

task :build_jtag_tb => VHDO_FILES do
puts "build jtag_tb"
sh %{ncdlab jtag_tb:jtag_tb_behavior -access +r+w}
end

# Here follows the three files that are processed by ncvhdl.
# The jtag_tb_c was bundled with :build_jtag_tb task before,
# but it looks to me like it could be broken out. (I could
# be wrong.) Notice the "output file depends on input file"
# pattern.

file "jtag_tb_c.vhdo" => ["jtag_tb_c.vhd"] do
puts "build jtag_tb_c"
sh %{ncvhdl -linedebug jtag_tb_c.vhd}
end

file "jtag_driver.vhdo" => ["jtag_driver.vhd"] do
puts "build jtag_driver"
sh %{ncvhdl -linedebug jtag_driver.vhd}
end

file "jtag.vhdo" => ["jtag.vhd"] do
puts "build jtag..."
sh %{ncvhdl -linedebug jtag.vhd}
end

End of Rakefile-------------------------------------------------

There is a lot of duplication in those last three file tasks. You could
iterate over VHD_FILES and create the file tasks in a loop. A simpler
way is to write a rule that describes how to turn .vhd files into .vhdo
files, e.g.

rule ".vhdo" => [".vhd"] do |t|
puts "build #{t.source}"
sh %{ncvhdl -linedebug #{t.source}}
end

Use that single rule in place of the final three file tasks. Here is
the output from the mockup I did...

----------------------------------------------------
$ rake
(in /home/jim/pgm/misc/philtomson)
build jtag.vhd
ncvhdl -linedebug jtag.vhd
Creating jtag.vhdo
build jtag_driver.vhd
ncvhdl -linedebug jtag_driver.vhd
Creating jtag_driver.vhdo
build jtag_tb_c.vhd
ncvhdl -linedebug jtag_tb_c.vhd
Creating jtag_tb_c.vhdo
build jtag_tb
ncdlab jtag_tb:jtag_tb_behavior -access +r+w
simulate it...
ncsim -gui jtag_tb:jtag_tb_behavior
done...
$
$
$ rake clobber
(in /home/jim/pgm/misc/philtomson)
rm -r jtag.vhdo
rm -r jtag_driver.vhdo
rm -r jtag_tb_c.vhdo
 
J

Jim Weirich

Phil said:
Jim,

Thanks, this helps explain a lot about Rake.

You guessed correctly that ncvhdl is a compiler. ncelab is sort of like a
linker. Unfortuneatly each .vhd file doesn't compile to a
corresponding .vhdo file (object file) - that would be nice. All of the
comilation units get put into a package file in a different directory - the
same package file, so each .vhd file gets compiled and added to the
project's .pkg file which makes it hard to figure out if you really need to
recompile a particular .vhd file (not Rake's problem, though, this is a
problem with the compiler/linker tool and it would present a problem for
make as well).

You could embed ncvhdl into a script that produces a .vhdo file whose
only purpose is to provide a time stamp for rake to key off of. A
little kludgey, but if compile times are long it might be worth it.

Here's another idea. Is there any way to get the time that a particular
file was added package file? Perhaps the package file has internally
embedded dates and time? If so, and you can write some ruby code to
pull that information out, then you could extend the FileTask object by
overriding the timestamp method. That would be a really cool use of
rake that went beyond the capabilities of make.
 
P

Phil Tomson

You could embed ncvhdl into a script that produces a .vhdo file whose
only purpose is to provide a time stamp for rake to key off of. A
little kludgey, but if compile times are long it might be worth it.

That's probably a reasonable way to do it.
Here's another idea. Is there any way to get the time that a particular
file was added package file? Perhaps the package file has internally
embedded dates and time? If so, and you can write some ruby code to
pull that information out, then you could extend the FileTask object by
overriding the timestamp method. That would be a really cool use of
rake that went beyond the capabilities of make.

That would be cool, but the .pak file is binary. I tried to do some
searching in it, but didn't find any of the strings that I looked for nor
anything else that was intelligible.

Probably creating .vhdo files as you suggested would be the way to go.

Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top