Building C++ with Rake

I'm familiarizing myself with Rake (and learning a spot of Ruby while
doing it) by making a build environment for a C++ project I'm doing.
I've run into a few issues though...

First off; here's the code I have so far:

require 'rake/clean'

PROJ_NAME = "testproj"
BUILD_DIR = ENV['BUILD_DIR']
OBJ_DIR = File.join(BUILD_DIR, PROJ_NAME,
File.expand_path('.').pathmap("%f"), 'objects')
SRC_FILES = FileList['src/**/*.c*']
OBJ_FILES = FileList[File.join(OBJ_DIR + '**/*.o')]

CLEAN.include(OBJ_DIR)

directory OBJ_DIR

def compileTask inclDirs, flags
  includes = inclDirs.collect { |dir| '-I' + dir + ' ' }
  compFlags = flags.collect { |flag| flag + ' ' }

  SRC_FILES.each do |srcFile|
    objFile = File.join(OBJ_DIR, srcFile.pathmap("%f").ext('o'))

    file objFile => [srcFile] do
      sh "g++ #{includes} #{compFlags} -c #{srcFile} -o #{objFile}"
    end
  end
end

def linkTask depLibDirs, depLibs, flags, target
  libDirs = depLibDirs.collect { |dir| '-L' + dir + ' ' }
  libs = depLibs.collect { |lib| '-l' + (lib[/lib(.+)\./, 1]) + ' ' }
  linkFlags = flags.collect { |flag| flag + ' ' }

  if (File.extname(target) == '.so') then
    linkFlags = linkFlags + ['-shared' + ' ']
  else
    linkFlags = linkFlags + ['-c' + ' ']
  end

  targetFile = File.join(BUILD_DIR, target)

  file targetFile => OBJ_FILES do
    objFiles = OBJ_FILES.collect { |objFile| objFile + ' ' }
    sh "g++ #{libDirs} #{libs} #{linkFlags} #{objFiles} -o
#{targetFile}"
  end
end

#----This here below I would like to have in a separate file

task :default => [:link]

task :compile => [OBJ_DIR] do
  inclDirs = ['/tmp/testdir1', '/tmp/testdir2']
  flags = ['-g', '-v']

  compileTask(inclDirs, flags)
end

task :link => [:compile] do
  target = 'libTest.so'
  depLibDirs = ['/usr/lib']
  depLibs = []
  flags = ['-fpic']

  linkTask(depLibDirs, depLibs, flags, target)
end

And my issues:

1: The file task thingy doesn't work as I thought it would, but I'm
probably using it wrong. I hope it's evident from the context what I'm
trying to do though.

2: I have lots of ugly "insert space between the arguments in my
arrays". How do I do it in a nicer way?

3: I would like to separate the "defined" tasks from the "regular"
ones so that the part furthest down is content of each "satellite"
rakefile which then includes the top part as a kind of library. But
when I tried doing it by simply putting the top part in a file and
then putting 'require "../../cppBuildLib.rb"' at the top of the
satellite file I got a message that file couldn't be found (or
something to that effect).

As I said before, I'm learning Rake and Ruby at the same time, so feel
free to point out any oddities or other stuff that could/should be
done differently.

2: I have lots of ugly "insert space between the arguments in my
arrays". How do I do it in a nicer way?

Just build your array and then call array.join(' ') to get a string of
the array elements separated by a space.

3: I would like to separate the "defined" tasks from the "regular"
ones so that the part furthest down is content of each "satellite"
rakefile which then includes the top part as a kind of library. But
when I tried doing it by simply putting the top part in a file and
then putting 'require "../../cppBuildLib.rb"' at the top of the
satellite file I got a message that file couldn't be found (or
something to that effect).

Yes, it's a bit hard to say where ruby thinks that the current directory
is. But as the string you give to require doesn't have to be static you
can just make it an absolute path buy prepending File.dirname(__FILE__)
(and maybe use File.join to create the path out of its pieces).

Urban

···

On Jun 3, 2007, at 23:20 , Magnus Falk wrote:

The Array.join worked beautifully, thanks for the tip.

Also, I seem to have lied about the import issue (I was recreating an
issue I had earlier before I moved it all into one file). I managed to
resolve it now and my best guess is that it was appending ".rb" to the
filename that did it.

Cheers,
Magnus