Hi ..
I am not sure how to create a set of Rake rules to do the following. Can
anyone prove assistance?
I think the following Rakefile will do what you want. I added extensive
comments to the file rather than do commentary in this message. Let me know
if you have problems.
-- Rakefile ----------------------------------------------------------------
require 'rake/clean'
# Create some constants for later reference.
PROG = "foo"
LIBNAME = PROG
LIBFILE = "lib#{LIBNAME}.a"
# For SRC, we just find all files in the project ending in '.c'. This
# will work with nested source directories too (like might be found in
# a Java project).
SRC = FileList['**/*.c']
# Generate the OBJ list by striping off the directory portion of the
# source file name and flattening the names into a single level obj
# directory. This assumes that all the base file names are unique,
# but that is given by the problem statement. (Note that the +ext+
# function is available in Rake 0.5.3 or later).
OBJDIR = 'obj'
OBJ = SRC.collect { |fn| File.join(OBJDIR, File.basename(fn).ext('o')) }
# Define our clean and clobber targets.
CLEAN.include(OBJ, OBJDIR, LIBFILE)
CLOBBER.include(PROG)
# The default task builds, then runs the program
task :default => [:build, :run]
# The build task just depends upon the program being present.
task :build => [PROG]
# The run task requires the program to be present, and then runs that
# program.
task :run => [PROG] do
sh "./#{PROG}"
end
# The program depends only on the library file.
file PROG => [LIBFILE] do
sh "cc -o #{PROG} -L . -l#{LIBNAME}"
end
# The library file depends only on the list of objects we constructed
# at the top of the file.
file LIBFILE => OBJ do
sh "ar cr #{LIBFILE} #{OBJ}"
sh "ranlib #{LIBFILE}"
end
# The directory directive defines the directory OBJDIR as a task that
# can be used in a prerequisites list in a task declaration.
directory OBJDIR
# Ok, this is the tricky part. This rule generates .o files from a
# source file described by a lambda function. Finding the source file
# is tricky because the object file does not indicate /which/ source
# directory contains the matching .c file. We punt by writing a
# special function to locate the source. (Originally I did this
# inline in the lambda, but I think it reads better split out into a
# separate functions).
#
# Note that we invoke the OBJDIR task directly in this rule. Because
# it is a rule, there is no opportunity to list OBJDIR as a
# dependency. By invoking it directly, we will build that directory
# if it is needed (but only if it is needed).
rule '.o' => lambda{ |objfile| find_source(objfile) } do |t|
Task[OBJDIR].invoke
sh "cc -c -o #{t.name} #{t.source}"
end
# It turns out that finding the source file is not that difficult. We
# just search the list of source files for a match on the basename of
# the object file. Obviously this might have a performance problem
# with a _large_ list of source files. In that case, I would build a
# hash at the top of the Rakefile and use that hash here when looking
# up the source.
def find_source(objfile)
base = File.basename(objfile, '.o')
SRC.find { |s| File.basename(s, '.c') == base }
end
-----------------------------------------------------------------