rake question

J

Joe Van Dyk

rule '.o' =3D> ['.c'] do |t|
sh "cc #{t.source} -c -o #{t.name}"
end

But, when I change the .c source file, it doesn't get compiled again.=20
Why is that?

Example:

PowerBook:~/that_stuff/test1 joe$ ls
Rakefile another_test.h test.cpp
another_test.cpp main.cpp test.h

PowerBook:~/that_stuff/test1 joe$ cat Rakefile=20
require 'rake/clean'
CLEAN.include '*.o', 'test'
CPP_SOURCE =3D FileList['*.cpp']
OBJS =3D CPP_SOURCE.ext 'o'

task :default =3D> :run
task :run =3D> "test" do
sh "./test"
end
file "test" =3D> OBJS do
sh "g++ -o test #{OBJS}"
end
rule '.o' =3D> '.cpp' do |t|
sh "g++ -c -o #{t.name} #{t.source}"
end
CPP_SOURCE.each do |cpp|
headers =3D File.read(cpp).scan(/^#include "(.+)"/)
task cpp =3D> headers
end

PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
g++ -c -o another_test.o another_test.cpp
g++ -c -o main.o main.cpp
g++ -c -o test.o test.cpp
g++ -o test another_test.o main.o test.o
/test
Whassup
what's up!


PowerBook:~/that_stuff/test1 joe$ touch main.cpp
PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
/test
Whassup
what's up!

It should've recompiled main.cpp and relinked everything, right?
 
J

Joe Van Dyk

rule '.o' =3D> ['.c'] do |t|
sh "cc #{t.source} -c -o #{t.name}"
end
=20
But, when I change the .c source file, it doesn't get compiled again.
Why is that?
=20
Example:
=20
PowerBook:~/that_stuff/test1 joe$ ls
Rakefile another_test.h test.cpp
another_test.cpp main.cpp test.h
=20
PowerBook:~/that_stuff/test1 joe$ cat Rakefile
require 'rake/clean'
CLEAN.include '*.o', 'test'
CPP_SOURCE =3D FileList['*.cpp']
OBJS =3D CPP_SOURCE.ext 'o'
=20
task :default =3D> :run
task :run =3D> "test" do
sh "./test"
end
file "test" =3D> OBJS do
sh "g++ -o test #{OBJS}"
end
rule '.o' =3D> '.cpp' do |t|
sh "g++ -c -o #{t.name} #{t.source}"
end
CPP_SOURCE.each do |cpp|
headers =3D File.read(cpp).scan(/^#include "(.+)"/)
task cpp =3D> headers
end
=20
PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
g++ -c -o another_test.o another_test.cpp
g++ -c -o main.o main.cpp
g++ -c -o test.o test.cpp
g++ -o test another_test.o main.o test.o
./test
Whassup
what's up!
=20
=20
PowerBook:~/that_stuff/test1 joe$ touch main.cpp
PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
./test
Whassup
what's up!
=20
It should've recompiled main.cpp and relinked everything, right?

When I comment out=20
CPP_SOURCE.each do |cpp|
headers =3D File.read(cpp).scan(/^#include "(.+)"/)
task cpp =3D> headers
end

Then it works as expected. So, "task cpp =3D> headers" is the culprit.=20
But I'm still not sure why it breaks everything else.
 
J

Joe Van Dyk

rule '.o' =3D> ['.c'] do |t|
sh "cc #{t.source} -c -o #{t.name}"
end

But, when I change the .c source file, it doesn't get compiled again.
Why is that?

Example:

PowerBook:~/that_stuff/test1 joe$ ls
Rakefile another_test.h test.cpp
another_test.cpp main.cpp test.h

PowerBook:~/that_stuff/test1 joe$ cat Rakefile
require 'rake/clean'
CLEAN.include '*.o', 'test'
CPP_SOURCE =3D FileList['*.cpp']
OBJS =3D CPP_SOURCE.ext 'o'

task :default =3D> :run
task :run =3D> "test" do
sh "./test"
end
file "test" =3D> OBJS do
sh "g++ -o test #{OBJS}"
end
rule '.o' =3D> '.cpp' do |t|
sh "g++ -c -o #{t.name} #{t.source}"
end
CPP_SOURCE.each do |cpp|
headers =3D File.read(cpp).scan(/^#include "(.+)"/)
task cpp =3D> headers
end

PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
g++ -c -o another_test.o another_test.cpp
g++ -c -o main.o main.cpp
g++ -c -o test.o test.cpp
g++ -o test another_test.o main.o test.o
./test
Whassup
what's up!


PowerBook:~/that_stuff/test1 joe$ touch main.cpp
PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
./test
Whassup
what's up!

It should've recompiled main.cpp and relinked everything, right?
=20
When I comment out
CPP_SOURCE.each do |cpp|
headers =3D File.read(cpp).scan(/^#include "(.+)"/)
task cpp =3D> headers
end
=20
Then it works as expected. So, "task cpp =3D> headers" is the culprit.
But I'm still not sure why it breaks everything else.

(I hope it's clear what I'm trying to do. I'm trying to scan the
included header files and if the header files have been changed, I
want to recompile all source files that include those header files. I
tried using "file cpp =3D> headers", but that didn't help either.)
 
O

Olaf Klischat

Joe Van Dyk said:
rule '.o' => ['.c'] do |t|
sh "cc #{t.source} -c -o #{t.name}"
end

But, when I change the .c source file, it doesn't get compiled again.
Why is that?

Example:

PowerBook:~/that_stuff/test1 joe$ ls
Rakefile another_test.h test.cpp
another_test.cpp main.cpp test.h

PowerBook:~/that_stuff/test1 joe$ cat Rakefile
require 'rake/clean'
CLEAN.include '*.o', 'test'
CPP_SOURCE = FileList['*.cpp']
OBJS = CPP_SOURCE.ext 'o'

task :default => :run
task :run => "test" do
sh "./test"
end
file "test" => OBJS do
sh "g++ -o test #{OBJS}"
end
rule '.o' => '.cpp' do |t|
sh "g++ -c -o #{t.name} #{t.source}"
end
CPP_SOURCE.each do |cpp|
headers = File.read(cpp).scan(/^#include "(.+)"/)
task cpp => headers
end

PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
g++ -c -o another_test.o another_test.cpp
g++ -c -o main.o main.cpp
g++ -c -o test.o test.cpp
g++ -o test another_test.o main.o test.o
./test
Whassup
what's up!


PowerBook:~/that_stuff/test1 joe$ touch main.cpp
PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
./test
Whassup
what's up!

It should've recompiled main.cpp and relinked everything, right?

When I comment out
CPP_SOURCE.each do |cpp|
headers = File.read(cpp).scan(/^#include "(.+)"/)
task cpp => headers
end

Then it works as expected. So, "task cpp => headers" is the culprit.
But I'm still not sure why it breaks everything else.

Well, AFAICS it happens to be the case that, when you have defined an
explicit task like foo.cpp, then rules matching the task name won't be
considered when computing the dependencies of the task. See Task.[] in
rake.rb for details -- given a task name, it just returns the task if
it is defined, without considering additional dependencies imposed by
rules matching the task's name.

This could be considered unfortunate behaviour or a bug :) A related
problem I had is that rules can only define a single prerequisite,
which seems like a quite arbitrary restriction to me.
 
S

Stefan Lang

Example:

PowerBook:~/that_stuff/test1 joe$ ls
Rakefile another_test.h test.cpp
another_test.cpp main.cpp test.h

PowerBook:~/that_stuff/test1 joe$ cat Rakefile
require 'rake/clean'
CLEAN.include '*.o', 'test'
CPP_SOURCE = FileList['*.cpp']
OBJS = CPP_SOURCE.ext 'o'

task :default => :run
task :run => "test" do
sh "./test"
end
file "test" => OBJS do
sh "g++ -o test #{OBJS}"
end
rule '.o' => '.cpp' do |t|
sh "g++ -c -o #{t.name} #{t.source}"
end
CPP_SOURCE.each do |cpp|
headers = File.read(cpp).scan(/^#include "(.+)"/)
task cpp => headers
end

PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
g++ -c -o another_test.o another_test.cpp
g++ -c -o main.o main.cpp
g++ -c -o test.o test.cpp
g++ -o test another_test.o main.o test.o
./test
Whassup
what's up!


PowerBook:~/that_stuff/test1 joe$ touch main.cpp
PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
./test
Whassup
what's up!

It should've recompiled main.cpp and relinked everything, right?

When I comment out
CPP_SOURCE.each do |cpp|
headers = File.read(cpp).scan(/^#include "(.+)"/)
task cpp => headers
end

Then it works as expected. So, "task cpp => headers" is the culprit.
But I'm still not sure why it breaks everything else.

Your logic should be correct. It works if i run it with Rant (with some
minor Rake->Rant translations). Don't know why it doesn't work with Rake.

I don't want to advertise but Rant can scan #includes for you:

import "c/dependencies", "autoclean"
CPP_SOURCE = sys['*.cpp']
OBJS = CPP_SOURCE.map { |f| f.sub_ext "o" }

task :run => "test" do
sys "./test"
end
gen C::Dependencies
gen Action do source "c_dependencies" end
file "test" => OBJS do
sys "g++ -o test #{OBJS.arglist}"
end
gen Rule, '.o' => '.cpp' do |t|
sys "g++ -c -o #{t.name} #{t.source}"
end
desc "Remove generated files."
gen AutoClean
 
J

Joe Van Dyk

Joe Van Dyk said:
rule '.o' =3D> ['.c'] do |t|
sh "cc #{t.source} -c -o #{t.name}"
end

But, when I change the .c source file, it doesn't get compiled again.
Why is that?

Example:

PowerBook:~/that_stuff/test1 joe$ ls
Rakefile another_test.h test.cpp
another_test.cpp main.cpp test.h

PowerBook:~/that_stuff/test1 joe$ cat Rakefile
require 'rake/clean'
CLEAN.include '*.o', 'test'
CPP_SOURCE =3D FileList['*.cpp']
OBJS =3D CPP_SOURCE.ext 'o'

task :default =3D> :run
task :run =3D> "test" do
sh "./test"
end
file "test" =3D> OBJS do
sh "g++ -o test #{OBJS}"
end
rule '.o' =3D> '.cpp' do |t|
sh "g++ -c -o #{t.name} #{t.source}"
end
CPP_SOURCE.each do |cpp|
headers =3D File.read(cpp).scan(/^#include "(.+)"/)
task cpp =3D> headers
end

PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
g++ -c -o another_test.o another_test.cpp
g++ -c -o main.o main.cpp
g++ -c -o test.o test.cpp
g++ -o test another_test.o main.o test.o
./test
Whassup
what's up!


PowerBook:~/that_stuff/test1 joe$ touch main.cpp
PowerBook:~/that_stuff/test1 joe$ rake
(in /Users/joe/that_stuff/test1)
./test
Whassup
what's up!

It should've recompiled main.cpp and relinked everything, right?

When I comment out
CPP_SOURCE.each do |cpp|
headers =3D File.read(cpp).scan(/^#include "(.+)"/)
task cpp =3D> headers
end

Then it works as expected. So, "task cpp =3D> headers" is the culprit.
But I'm still not sure why it breaks everything else.
=20
Well, AFAICS it happens to be the case that, when you have defined an
explicit task like foo.cpp, then rules matching the task name won't be
considered when computing the dependencies of the task. See Task.[] in
rake.rb for details -- given a task name, it just returns the task if
it is defined, without considering additional dependencies imposed by
rules matching the task's name.
=20
This could be considered unfortunate behaviour or a bug :) A related
problem I had is that rules can only define a single prerequisite,
which seems like a quite arbitrary restriction to me.

Hm. So, are there any work arounds, other than to rebuild the entire
thing when a .h file changes?

What I'm trying to do is become a better software developer. So, I've
got a couple C and C++ books. I want to do the examples in them. So
I'll have directories like
/
/c/
/c/problem_1_1/
/c/problem_1_2/
/c/problem_1_2/main.c
/c/problem_1_2/foo.c
/c/problem_1_2/foo.h
/c/problem_1_2/test_foo.c
/c++/


And so on. I want a Rake file that will go into the directory
structure, compile all the code, compile all the test code, and run
the tests. Then I want it to create syntax-highlighted webpages that
shows for each example the code and the output and the tests, and then
posts them to a website where I can get comments on them.

Perhaps I'll have separate build directories (so I can build and test
the code on Windows, Linux, FreeBSD, and OS X)..

So, I'm looking for help for that.

Thanks!
Joe
 
J

Joe Van Dyk

]
And I haven't looked at Rant much, would it be better for my purposes?
Rake and Rant are both general purpose build utilities, right?
=20
Yes, but Rant can automatically determine the dependencies between
C/C++ sources files (by extracting #include statements) and it has
some support for multiple directories (i.e. more than one Rantfile).
=20
Actually a good example. I came up with the following solution for Rant:
=20
% ls
c c++ Rantfile rule.rf
% ls c
problem_1_1 template.rf
% ls c++
problem_1_1 template.rf
=20
The main Rantfile in the root directory copies the c/template.rf Rantfile
into all c/problem_* directories and the c++/template.rf into all
c++/problem_* directories.
=20
If you run rant in the root directory, it will compile all tests
and run them. To compile only, run rant with "build" as only argument.
During work on one of the exercises you can change into the c(++)/problem= *
directory and run rant to only compile/run the current exercise.
=20
The example is in the attachment. The only problem is, that the last
Rant release contains a bug with regards to the Rule/subdirectory
combination. If you want, I can send you my development version offlist.

Yeah, when I run 'rant', I get:
rant: [ERROR] Name error when loading
`/home/joe/repos/joe/learning/c_cpp_exercises/c++/problem_1_1/Rantfile':
undefined method `sub_ext' for #<Rant::RacFileList:0x4026baf4=/usr/lib/ruby/gems/1.8/gems/rant-0.4.0/lib/rant/rantsys.rb:12=
2:in
`method_missing'
/home/joe/repos/joe/learning/c_cpp_exercises/c++/problem_1_1/=
Rantfile:13:in
`instance_eval'
/usr/lib/ruby/gems/1.8/gems/rant-0.4.0/lib/rant/rantlib.rb:10=
02:in
`instance_eval'
/usr/lib/ruby/gems/1.8/gems/rant-0.4.0/lib/rant/rantlib.rb:10=
02:in
`load_file'
/usr/lib/ruby/gems/1.8/gems/rant-0.4.0/lib/rant/rantlib.rb:68=
6:in
`subdirs'

And so on. Would that be fixed in the development version?
 
S

Stefan Lang

On Friday 15 July 2005 22:24, Joe Van Dyk wrote:
The example is in the attachment. The only problem is, that the last
Rant release contains a bug with regards to the Rule/subdirectory
combination. If you want, I can send you my development version offlist.

Yeah, when I run 'rant', I get:
rant: [ERROR] Name error when loading
`/home/joe/repos/joe/learning/c_cpp_exercises/c++/problem_1_1/Rantfile':
undefined method `sub_ext' for
#<Rant::RacFileList:0x4026baf4>
/usr/lib/ruby/gems/1.8/gems/rant-0.4.0/lib/rant/rantsys.rb:122:in
`method_missing'

/home/joe/repos/joe/learning/c_cpp_exercises/c++/problem_1_1/Rantfile:13:in
`instance_eval'

/usr/lib/ruby/gems/1.8/gems/rant-0.4.0/lib/rant/rantlib.rb:1002:in
`instance_eval'

/usr/lib/ruby/gems/1.8/gems/rant-0.4.0/lib/rant/rantlib.rb:1002:in
`load_file'

/usr/lib/ruby/gems/1.8/gems/rant-0.4.0/lib/rant/rantlib.rb:686:in `subdirs'

And so on. Would that be fixed in the development version?

Yes.
 

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,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top