Le 28/4/2005, "Jim Weirich" <jim / weirichhouse.org> a ñÄrit: >On Wednesday 27 April 2005 07:38 pm, Mark Probert wrote: >> 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 >----------------------------------------------------------------- This subfolder-sourcing seems like a common usage pattern, perhaps worthy of some sort of an abstraction? Is there any sort of a 'common Rake task idioms' collection anywhere? >-- Jim Weirich E -- template<typename duck> void quack(duck& d) { d.quack(); }