From matthieu.riou at gmail.com Tue May 1 10:46:37 2007 From: matthieu.riou at gmail.com (Matthieu Riou) Date: Tue, 1 May 2007 07:46:37 -0700 Subject: [Raven-devel] rake-less prototype In-Reply-To: References: Message-ID: Hi Matthew, I've been musing about this more declarative approach for a few days. I think you might want to take a look at Buildr (http://buildr.rubyforge.org). I've been mildly involved in it as it's been designed by one of my coworkers (Assaf Arkin) and have been using it a bit at work. To get a feeling of how a build script looks like, there's an extensive example here: http://svn.apache.org/repos/asf/incubator/ode/trunk/Rakefile The approach is definitely more declarative than what Raven has been so far. I've been thinking of Raven as the Ant version of a Rake-based build system for Java as Buildr is closer to Maven (without the issues). Let me know what you think. Cheers, Matthieu On 4/27/07, Matthew Foemmel wrote: > > Hi all, > > I came up with a little hack the other day, and I'd like to get > people's feedback on it. I've been growing a bit frustrated trying to > get build channels and multi-project stuff all working cleanly with > Rake (which has required a fair bit of monkey-patching) so out of > curiousity I decided to see what I could come up with given a "clean > slate" i.e. without using any Rake code. I'm not suggesting Raven > should switch to this model, but I kind of like the way it turned > out, and would be interested in hearing if anyone thinks there are > ideas here worth pursuing. I've attached a file with some sample code > - it doesn't rely on any existing code (it doesn't do much, in fact) > so you should be able to just download and run it with vanilla ruby. > > Here's an example of what a build script looks like with the prototype: > > MainCompile = Javac.new { > @classpath << "foo.jar" > } > > TestCompile = Javac.new(MainCompile, JUnit::Classpath) { > @srcdir = "target/test/java" > } > > Test = JUnit::Run.new(TestCompile) > > The main differences between the prototype and the current raven2 > code are: > > * Unlike Rake, there is no conceptual difference between a task > *instance* and a task *class* - you can call "new" on any task to > create an extension of that task > * Tasks are objects that the build script must keep track of (usually > by storing them in constants e.g. "MainCompile" above) unlike Rake > where they are kept in a hashtable and looked up by name > * The @ symbol can be used to define build attributes (I've been > calling these build "channels" before, but given the new syntax i > think "attribute" is more appropriate) > > Build attributes are handled as follows: > > * A task can extend any other task (by calling "new" on it) in which > case build attributes are automatically passed from the child to the > parent > * A task can depend on other tasks, in which case the build > attributes for the latter are merged together and passed into the > former (the same way that Raven works now) > > Here's a quick walkthough: > > > === Creating Tasks === > > The obligatory hello world script looks like this: > > Hello = Task.new { > log_info "Hello, World!" > } > > Here we're just creating a new Task object with a single log > statement. Calling "build Hello" would print out "Hello, World!" > obviously. > > > === Extending Tasks === > > Now, let's say we wanted to make this task more generic, so that you > could optionally pass in the name of the person we want to greet. We > could do this like so: > > Hello = Task.new { > @name ||= "World" > log_info "Hello, #{@name}!" > } > > In this case, calling "build Hello" would do the same thing as in the > previous example (since we set the default value for "@name" to be > "World" in the Hello task). However, we can now also define a task to > greet "Homer": > > GreetHomer = Hello.new { > @name = "Homer" > } > > Here we're extending the Hello task, by calling "new" on it and > passing in a block. (Hello isn't a class, it just happens to have a > method called "new"). So calling "new" on the Task class returns a > new Task object, on which you can call "new" again, and so on. So > from the user's point of view there's no real difference between a > task class and a task instance. They're all just tasks. > > When the GreetHomer task is executed, its block is run (where we set > the value of @name to be "Homer") then its parent block is run (where > we print out the greeting). The build attribute "@name" is > automatically passed from the child to the parent through a bit of > metaprogramming magic. In a sense this is like inheritance, except we > don't need to specify which method we're overloading, and we don't > need to explicitly call "super". > > > === Dependencies === > > Dependencies can be declared by passing other tasks as arguments to > the "new" method. For example, let's say we wanted to set up our > classpath, then call Javac: > > Classpath = Task.new { @classpath = ["foo.jar"] } > > Compile = Javac.new(Classpath) > > Build attributes are passed up the same way they are currently in > Raven (i.e. the @classpath attribute defined in MainClasspath will be > visible in MainCompile). > > Note that I had to scrap the "=>" notation that rake uses to > declaring dependencies, since the name of the task is no longer > passed into the task constructor. > > > === Anonymous Tasks === > > Sometimes you want to group tasks together, but don't necessarily > want to define a separate top-level task w/associated dependencies > for each one. The "call" command lets you run tasks from within other > tasks. For example, say we want to compile some files and copy some > resources over in a single build target: > > Compile = Task.new { > call Javac.new { > @srcdir = "src/main/java" > @destdir = "target/main" > } > call Copy.new { > @srcdir = "src/main/resources"; > @destdir = "target/main" > @include = "**/*.properties" > } > } > > > === Modules === > > The use of capitalize names for tasks may seems strange, but I've > done that so that they can be treated as module constants, and > therefore be referred to from other modules. This takes the place of > Rake namespaces. For example: > > module Jdk > Javac = Task.new { > ... > } > Jar = Task.new { > ... > } > Javadoc = Task.new { > ... > } > end > > module MyApp > > # Here we use the fully qualified name > MainCompile = Jdk::Javac { > ... > } > > # Here we include the module and use the short name > include Jdk > TestCompile = Jdk::Javac(MainCompile) { > ... > } > > end > > > === Gems === > > The nice thing about using modules instead of Rake namespaces is that > we can now bundle up sets of tasks (and their associated files) and > distribute them as gems. For example, we could wrap all the JDK tasks > up in a gem and use it like this: > > require_gem 'jdk' > > MainCompile = Jdk::Javac { > @srcdir = "mysrc" > } > > For tools like JUnit (or XDoclet, or Antlr, etc) we might want to > provide two tasks: one to set up the classpath, and one for the > actual tool itself. This would be fairly easy: > > module JUnit > Classpath = Task.new { > @classpath = "junit.jar" > } > > Run = Task.new { > # execute the junit tests > ... > } > end > > Then if you wanted to use JUnit from your build script you could do > something like this: > > require_gem 'junit' > > CompileTests = Javac.new(JUnit::Classpath) { > ... > } > > RunTests = JUnit::Run.new { > ... > } > > > === Code === > > I've attached some sample code showing how this might work - let me > know what you think... > > > > Cheers, > Foemmel > _______________________________________________ > Raven-devel mailing list > Raven-devel at rubyforge.org > http://rubyforge.org/mailman/listinfo/raven-devel > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/raven-devel/attachments/20070501/95a8ad4f/attachment-0001.html From nobody at rubyforge.org Sat May 12 16:11:30 2007 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sat, 12 May 2007 16:11:30 -0400 (EDT) Subject: [Raven-devel] [192] branches/v1.x/lib/raven: Fixing a few path issues (/ vs \) Message-ID: <20070512201131.0B5145240ADB@rubyforge.org> An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/raven-devel/attachments/20070512/c575350e/attachment.html From nobody at rubyforge.org Sat May 12 17:27:30 2007 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sat, 12 May 2007 17:27:30 -0400 (EDT) Subject: [Raven-devel] [193] branches/v1.x/lib/raven: Updating for latest gem versions Message-ID: <20070512212730.E5B475240AC5@rubyforge.org> An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/raven-devel/attachments/20070512/8be4df5a/attachment.html From nobody at rubyforge.org Sun May 13 00:16:23 2007 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 13 May 2007 00:16:23 -0400 (EDT) Subject: [Raven-devel] [194] branches/v1.x/lib/raven: Fixed a few glitches for windows, support for different rubygems versions. Message-ID: <20070513041623.4231F5240B44@rubyforge.org> An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/raven-devel/attachments/20070513/0facaf24/attachment.html From nobody at rubyforge.org Sun May 13 00:20:45 2007 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 13 May 2007 00:20:45 -0400 (EDT) Subject: [Raven-devel] [195] branches/v1.x/rakefile: Increasing minor version number for minor release. Message-ID: <20070513042045.2B4035240B44@rubyforge.org> An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/raven-devel/attachments/20070513/e5f78ebd/attachment.html From nobody at rubyforge.org Sun May 13 00:28:15 2007 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 13 May 2007 00:28:15 -0400 (EDT) Subject: [Raven-devel] [196] branches/v1.x/site: Updating latest release number on site. Message-ID: <20070513042815.A931B5240B48@rubyforge.org> An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/raven-devel/attachments/20070513/6472d4e3/attachment-0001.html