# Rake - How to use separate source and build folders

**URL:** <https://www.ruby-forum.com/t/rake-how-to-use-separate-source-and-build-folders/71722>\
**Category:** Ruby\
**Created:** [October 11, 2006, 2:35am UTC](https://www.ruby-forum.com/t/rake-how-to-use-separate-source-and-build-folders/71722 "2006-10-11T02:35:26Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![barrysfarm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/a698b9/32.png) [@barrysfarm](https://www.ruby-forum.com/u/barrysfarm)\
**Post date:** [October 11, 2006, 2:35am UTC](https://www.ruby-forum.com/t/rake-how-to-use-separate-source-and-build-folders/71722/1 "2006-10-11T02:35:26Z")

</div>

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](http://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’]

---

<div class="post-metadata">

**Author:** ![barrysfarm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/a698b9/32.png) [@barrysfarm](https://www.ruby-forum.com/u/barrysfarm)\
**Post date:** [October 11, 2006, 7:46pm UTC](https://www.ruby-forum.com/t/rake-how-to-use-separate-source-and-build-folders/71722/2 "2006-10-11T19:46:08Z")

</div>

On 10/10/06, Barry A. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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 😉

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](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
