Rake - How to use separate source and build folders

Hello Rubyists,

I am new to rake and attempting to use it to build a small C++ project.
I made some changes to one of the example rake files from
rake.rubyforge.org and I want to have a separate source and build folder
named ‘src’ and ‘build’. I use the FileList to specify my cpp files,
then I modify that list with the ‘ext’ and ‘sub’ methods. I would expect
this to work, however I get this:

“Don’t know how to build task ‘build/CGfxOpenGL.o’” which points to this
line: “Rake::Task[‘link’].invoke” in the build task.

If I change these 2 lines:

exts = SRC.ext(‘o’)
OBJ = exts.sub(“#{SRC_DIR}”, “#{BUILD_DIR}”)

to just

OBJ = SRC.ext(‘o’)

it WORKS FINE except all my object files are in my src folder WHICH I
DON’T WANT.

How can I remedy this? I thought that since the ‘build/CGfxOpenGL.o’
does not exist that the rule ‘.o’ would execute which is what does the
compile.

many many thanks!

-Barry

require ‘rake/clean’

SRC_DIR = ‘src’
BUILD_DIR = ‘build’

SRC = FileList[“#{SRC_DIR}/*.cpp”]
exts = SRC.ext(‘o’)
OBJ = exts.sub(“#{SRC_DIR}”, “#{BUILD_DIR}”)

task :echo do
puts “Usage:\n”
puts " clean\n"
puts " build\n"
end

clean

CLEAN.include(“#{BUILD_DIR}/*.o”)

task :default => [“echo”]

task :init do
FileUtils.mkdir “#{BUILD_DIR}” if !FileTest.exists?(“#{BUILD_DIR}”)
end

compile

rule ‘.o’ => ‘.cpp’ do |t|
sh “g++ -Wall -Weffc++ -O2 -c -o #{t.name} #{t.source}”
end

link

file “link” => OBJ do
puts “myobject: #{OBJ}\n”;
sh “g++ -Wall -L/usr/local/lib -lglut -lGL -lGLU -o
#{BUILD_DIR}/Balance #{OBJ}”
end

build it!

task :build => [:init] do
Rake::Task[‘link’].invoke
end

File dependencies go here …

file ‘CGfxOpenGL.o’ => [‘CGfxOpenGL.cpp’,
‘CGfxOpenGL.h’]

file ‘winmain.o’ => [‘winmain.cpp’]

On 10/10/06, Barry A. [email protected] wrote:

line: “Rake::Task[‘link’].invoke” in the build task.
it WORKS FINE except all my object files are in my src folder WHICH I
DON’T WANT.

How can I remedy this? I thought that since the ‘build/CGfxOpenGL.o’
does not exist that the rule ‘.o’ would execute which is what does the
compile.

many many thanks!

Well, I stole this from Jim W.'s blog so if it does not work, blame
him :wink:

You want to modify your “rule ‘.o’ => …” line so that it maps to a
lambda function …

def find_source( objfile )
SRC.find { |s| File.basename(s, ‘.cpp’) == File.basename(objfile,
‘.o’) }
end

rule ‘.o’ => lambda {|objfile| find_source(objfile)} do |t|
sh “g++ -Wall -Weffc++ -O2 -c -o #{t.name} #{t.source}”
end

Jim’s full writeup can be found here
http://jimweirich.umlcoop.net/index.cgi/Tech/Rake/Tutorial

The only thing to watch out for with this rule is that all your source
code files must be uniquely named. All directory information is
stripped off by the call to File.basename in the find_source method.

Blessings,
TwP