{ |one, step, back| } 70 to 79 of 177 articles WikiSyndicate: full/short

Getting Ready for OSCON 2005   02 Jul 05
[ print link all ]

Preparations have been made, presentations have been written, and tickets have been ordered.

Talks for OSCON 2005

As mentioned here earlier, I’m doing a talk on Dependency Injection at OSCON this year. I’ve given the talk twice now for practice (thanks to both the Cincinnati XP Users Group and the Cincinnati Java Users Group for being my guinea pigs). Both practice runs went fairly well. I rewrote about half the talk between the first and second trial runs and am much happier with the result. The hardest part is knowing what not to say, otherwise I could talk for hours (OSCON presentations are 45 minutes long).

What I haven’t mentioned is that I’ll be giving a second talk there as well. It seems there was cancellation in the Ruby track and they had another opening, so the “10 Things Every Java Programmer Should Know About Ruby” is going to OSCON as well. This should be good, the “10 Things” talk is a fun one to give.

However, I did a practice run on the “10 Things” talk at the Cincinnati Programmers Guild last week and the timing was way off. I ended up talking for nearly an hour and 45 minutes. I’m going to have to to some serious cutting and trimming on that talk to get it into the 45 minute window, actually make that 35 minutes because I would like to leave 10 minutes for questions.

If you are in the Columbus Ohio area and would like to hear yet another practice run, I’ll be at the Columbus Ruby Brigade on July 19th. It will probably be the dependency injection talk. Time and location hasn’t been set quite yet, but I’ll announce more when I know more.

Cincinnatians at OSCON

John Wilger has announced he will be at OSCON, and Chris Nelson (Mr. Trails) will be there speaking about his Trails project (see this java.net article for a preview to Chris’s talk). Both John and Chris live within a few miles of my house, so I officially declare Finneytown to be the OSCON-off-cite center of the conference. From elsewhere in Cincinnati, a friend from the Cincinnati Linux Users Group has mentioned to me that he is also going. Anyone else planning on going?


Rails Day 2005   05 Jun 05
[ print link all ]

All I can say is Wow!

Rails Day, the Aftermath

(If you don’t know what rails day is, look here: Rails Day Blog. It is a 24 hour contest to implement a web application in Rails.)

Obviously I can say more than wow. I don’t have a lot of time, so just a few quick points here.

  • Don’t try to setup your brand new Mac-mini for Rails Day if you’ve never used it for developement and are not that familiar with Macs in the first place. Not that Macs are a poor development machine, far from it! It’s just a poor decision to “try out a Mac” the morning of Rails Day. I wasted way too much time trying to get it configured. I finally switched back to my trusty laptop.
  • Favorite quote of the day: I heard this from the other Rails Day team in the room with us:

Person 1: I think we should use transactional testing.

Person 2: I agree. Just a second … I want to watch you set it up. (He then turns back to his machine to finish a commit. He returns in a few seconds). Ok, I’m ready.

Person 1: Oh, I’m done already.

Person 2: Damn! That’s what I hate about Rails. You blink and you miss something.

  • Ha! We way overplanned our application. John started at midnight and implemented the DB schema we talked though in our planning meeting. When we started connecting things up, we discovered that is was way more complicated than what we could accomplish in one day, so we ripped out the extra stuff and concentrated on the features that we were working on at the moment. Eventually we might need the complexity, but it was only getting on our way. YAGNI!
  • Thanks to Fusion Alliance for procuring the Room. It was perfect for our needs (well, except for a distinct lack of power outlets ... we had to bring in a few extra power strips).
  • Thanks to Lisa Kaminski (SARK) for the fruit basket and the Pizza.
  • Although we didn’t get everything done, we did get to put in some AJAX like features. That’s the first time I have played with AJAX and Rails does a really nice job of making it easy.
  • Here’s our stats:
+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Helpers              |     9 |     8 |       0 |       0 |   0 |     0 |
| Controllers          |   148 |   126 |       4 |      21 |   5 |     4 |
| APIs                 |     0 |     0 |       0 |       0 |   0 |     0 |
| Components           |     0 |     0 |       0 |       0 |   0 |     0 |
|   Functionals        |   189 |   148 |       6 |      26 |   4 |     3 |
| Models               |   170 |   133 |       4 |      26 |   6 |     3 |
|   Units              |   175 |   142 |       3 |      28 |   9 |     3 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                |   691 |   557 |      17 |     101 |   5 |     3 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 267     Test LOC: 290     Code to Test Ratio: 1:1.1
  • Note to self: Next year have practice run to smooth out the kinks.
  • Teams in Cincinati:
    • Team 1 (JEWEL … personal food log)
      • Jim Weirich
      • John Wilger
      • Rob Biedenharn
    • Team 2 (Photo album/organizer)
      • Scott Barron
      • Doug Alcorn
      • Mark Windholtz
  • Mark brought in a couple bottles of Ruby Sake, which we used to celebrate the end of the run.

Had a great time … I suspect the other teams did too.


I'm Going to OSCON 2005   24 May 05
[ print link all ]

It looks like I am going to O’Reilly’s Open Source Conference this year.

Dependency Injection at OSCON 2005

My proposal for a talk at OSCON 2005 on Dependency Injection and Dynamic Languages has been accepted. The acceptance notification came quite a bit later than I expected so when it finally came I was pleasantly surprised. Speaker registration opened last week and I’m all signed up and ready to go.

Well … almost ready. There’s the small detail of finishing the presentation and getting the materials to O’Reilly in a timely fashion. (details, details …)

The talk is going to be an extension of the blog entry I made last fall on Dependency Injection In Ruby, but will go further and deeper into the subject. I think it will be a lot of fun.

If you can make it to the conference, come on by and introduce yourself. I’d love to meet you.


War at the Movie Theater   20 May 05
[ print link all ]

Yes, I saw Star Wars, Episode III. But that’s not the war I’m talking about.

Episode III

My daughter and I went to the midnight showing of “Revenge of the Sith”. (Quick review: Yes, worth seeing; no, Lucas still can’t write a love scene.) But this blog is not about the movie, it’s about the event.

Imagine this picture… You are in a room full of Star Wars geeks, many of whom are dressed in elaborate costumes with expensive (as in over $200) light sabers. You have been waiting for hours for the show to start, and have suffered through the trailers. The obligatory “Please turn off all cell phones” and “Remember our concession stand” message are now playing and the movie event of the year is just seconds away from starting.

Pause now with this picture in your mind and think about how the Star Wars movies always start. I know you’ve seen them. The big STAR WARS logo flashes on screen, the brass fanfare sounds and the words “In a galaxy far, far away” start scrolling on the screen.

Also remember that if you are at the midnight showing, then you are there not only for the movie (which you will probably see several times over the next few weeks), but for the experience, the event! The final movie is showing and you just want to drink in the experience and feel the mood.

And then seconds before the movie starts… the projector skips a beat and the frame gets out of synchronization with the projector. The top half of the screen is now showing at the bottom, and the bottom of the screen is at the top. The logo was split across the screen so that it read:

   WARS
  -----
  STARS

The room was in an uproar! Chants of “FIX IT” and “RESTART” echoed throughout the theater. The crowd reacted as if the projector malfunction was ruining the whole experience. Someone in the back of the room stood up and blocked the projection beam so that the picture could not be seen … and the crowd cheered because they did not want to see a flawed first performance (why shutting one’s eyes was not sufficient was never clear to me).

The theater staff was not exactly helpful. At first someone came out and said that they would get it fixed shortly and would restart the film. And they did get it fixed within a few minutes, but didn’t restart it. It didn’t matter, the crowd was so upset that they kept chanting “RESTART” after the picture was fixed. Finally the staff came out and said that weren’t able to restart it (never sure just why), and that the problem was in all the theaters (Really? In all 20 theaters in the movieplex? In what way are the theaters linked so that the same problem happens in all them at the same time?)

Finally it was obvious that they weren’t restarting it, and the crowd settled down and we could begin to watch the show. At that point, we were in the middle of a space battle (I’m not quite sure who was fighting who), and there were little drilling droids on Obi wan’s fighter. Oh well, it was Star Wars and we settled in to enjoy it.

An aside: You got to believe that a significant portion of that midnight showing crowd was planning on multiple viewings of the movie. Lets say two-thirds were planning on seeing it more than once. With 20 sold out theaters with 200 to 300 people per theater makes (around) 5000 people there that night. Now if two-thirds of 5000 were going to pay to see the movie twice, but now have a free pass, that right around $30,000 that was lost that night. Wow. That’s an expensive mistake.

Oh, and I have one other piece of advice to those going to midnight Star Wars showings. If you are going to go in costume, go all out and do it right. If you show up with a Darth Vadar helmet that looks like it came from a K-Mart Halloween costume rack, and the Darth Vadar standing next to you looks as if he just stepped off the movie set ... well, you look pretty silly.

Just go see the movie and enjoy it.


Rake Tutorial -- Another C Example   28 Apr 05
[ print link all ]

Mark Probert on the Ruby-Talk mailing lists asks: “I am not sure how to create a set of Rake rules to do the following. Can anyone prove assistance?”

I had planned for the next Rake tutorial to go into using prepackaged task libraries, but Mark’s question highlights an interesting problem (and resolution) with rules. I posted an answer to Mark on the list, but why waste a perfectly good explaination when I can recycle it here.

The Problem

Mark has two separate source directories (he calls them src_a and src_b, but I suspect they are more creatively named in real life. Both directories contain .c files. However, the kicker is that all the object files are to be placed in a single directory (named obj) no matter which source directory contained the original C code.

The rule we introduced in the last tutorial isn’t powerful enough to move the .o file into the obj directory. We need to tweek it just a bit.

The .o File Rule

Here is the rule in question.

rule '.o' => '.c' do |t|
  sh "cc -c -o #{t.name} #{t.source}" 
end

To recap, the rule specifies how to create a .o file from a similarly named .c file. But as noted above, the .c are in a different location. We can fix this by giving the rule a general purpose function that transforms the object file name into the correct source file name.

Finding the Source File.

But how do we find the source file? Assuming we have a constant named SRC that contains a list of all our source files, this simple find command will do the trick (assume objfile is the name of the object file):

SRC.find { |s| File.basename(s, '.c') == File.basename(objfile, '.o') }

Wrapping this in a method (named find_source) gives us a nice way to find the source file.

Tweeking the Rule

We can now write the rule like this…

rule '.o' => lambda { |objfile| find_source(objfile) } do |t|
  sh "cc -c -o #{t.name} #{t.source}" 
end

The Whole Rakefile

Just a couple notes about the Rakefile

  1. Note that we invoke the OBJDIR task directly in the rule. Because it is a rule, there is no opportunity to list OBJDIR as an explicit dependency. By invoking it directly inside the rule, we will build that directory if it is needed (but only if it is needed).
  2. If searching the SRC list has performance problems (because SRC is very long), then an alternative is to create a mapping of object names to source names at the top of the file. Then finding the source name is a simple hash lookup.

Rakefile

require 'rake/clean'

PROG = "foo" 
LIBNAME = PROG
LIBFILE = "lib#{LIBNAME}.a" 

SRC = FileList['**/*.c']

OBJDIR = 'obj'
OBJ = SRC.collect { |fn| File.join(OBJDIR, File.basename(fn).ext('o')) }

CLEAN.include(OBJ, OBJDIR, LIBFILE)
CLOBBER.include(PROG)

task :default => [:build, :run]

task :build => [PROG]

task :run => [PROG] do
  sh "./#{PROG}" 
end

file PROG => [LIBFILE] do
  sh "cc -o #{PROG} -L . -l#{LIBNAME}" 
end

file LIBFILE => OBJ do
  sh "ar cr #{LIBFILE} #{OBJ}" 
  sh "ranlib #{LIBFILE}" 
end

directory OBJDIR

rule '.o' => lambda{ |objfile| find_source(objfile) } do |t|
  Task[OBJDIR].invoke
  sh "cc -c -o #{t.name} #{t.source}" 
end

def find_source(objfile)
  base = File.basename(objfile, '.o')
  SRC.find { |s| File.basename(s, '.c') == base }
end

Alternatives

On possible alternative is to replace the rule with a loop that explicitly creates tasks to compile each .c file. It might look something like this:

SRC.each do |srcfile|
  objfile = File.join(OBJDIR, File.basename(srcfile).ext('o'))
  file objfile => [srcfile, OBJDIR] do
    sh "cc -c -o #{objfile} #{srcfile}" 
  end
end

What I like about this solution is the ability to put the OBJDIR dependency directly in the task definition.


Kali Code for Dense Stellar Systems   23 Apr 05
[ print link all ]

Ruby and celestial mechanics… two great tastes that taste great together.

I saw this mentioned on the Ruby-Talk mailing list. The Kali Code for Dense Stellar Systems by Piet Hut and Jun Makino is a conversation between two astrophysists as they build a computer simulation of the N-Body problem. And they are using Ruby to write the simulation. It is a great introduction to the Ruby language in addition to being a fun problem to solve.

My first job out of college was at Cape Canaveral working on deep space trajectory programs. It has been many years since I flexed my math muscles in celestial mechanices, so it was kinda fun to see that stuff again. I’ve only read through the second chapter, but I’m eagerly looking forward to the rest.

If you are looking to learn Ruby and aren’t frightened by a bit of math (well, perhaps more than a bit), you might enjoy this.


Rake Tutorial -- Handling Common Actions   05 Apr 05
[ print link all ]

Rake is a tool for controlling builds. In this part of the Rake tutorial, we see how to organize the Rake actions to apply to many similar tasks.

In the RakeTutorialIntroduction, we talked about the basics of specifying dependencies and associating actions to build the files. We ended up with a nice Rakefile that built our simple C program, but with some duplication in the build rules.

But First, Some Extra Rake Targets

But before we get into all that, lets add some convience targets to our Rakefile. First of all, it would be nice to have a default target that is invoked when we don’t give any explicit task names to rake. The default target looks like this:

   task :default => ["hello"]

Until now, the only kind of task we have seen in Rake are file tasks. File tasks are knowledgable about time stamps on files. A file task will not execute its action unless the file it represents doesn’t exist, or is older than any of its prerequisites.

A non-file task (or just plain “task”) does not represent the creation of a file. Since there is no timestamp for comparison, non-file tasks always execute their actions (if they have any). Since the default task does not represent a file named “default”, we use a regular non-file task for this purpose. Non-file tasks just use the task keyword (instead of the file keyword).

Here are a couple of other really useful tasks that I almost always include in a Rakefile.

clean:

Remove temporary files created during the build process.

clobber:

Remove all files generated during the build process.

clean tidies up the directories and removes any files that generated as part of the build process, but are not the final goal of the build process. For example, the .o files used to link up the final executable hello program would fall in this category. After the executable program is built, the .o files are no longer needed and will be removed by saying “rake clean”.

clobber is like clean, but even more aggressive. “rake clobber” will remove all files that are not part of the original package. It should return a project to the “just checked out of CVS” state. So it removes the final executable program as well as the files removed by clean.

In fact, these tasks are so common, Rake comes with a predefined library that implements clean and clobber.

But every project is different, how do we specify which files are to be cleaned and clobbered on a per project basis?

The answer is File lists.

File Lists to the Rescue

A file list is simply a list of file names. Since a lot of what Rake does involves files and lists of those files, a file list has some special features to make manipulating file names rather easy.

Suppose you want a list of all the C files in your project. You could add this to your rake file:

  SRC = FileList['*.c']

This will collect all the files ending in ”.c” in the top level directory of your project. File lists understand glob patterns (i.e. things like "*.c") and will find all the matching files.

By the way, no matter where you invoke it, rake always executes in the directory where the Rakefile is found. This keeps your path names consistent without depending on the current directory the user interactive shell.

The clean and clobber tasks use file lists to manage the files to remove. So if we want to clean up all the .o files in a project we could try …

  CLEAN = FileList['*.o']

(CLEAN is the file list associated with the clean task. I’ll let you guess the name of the file list associated with clobber).

The Rakefile So Far …

With the addtion of a few extra tasks, our Rakefile now looks like this. Notice the require ‘rake/clean’ line used to enable the clean and clobber tasks.

  require 'rake/clean'

  CLEAN.include('*.o')
  CLOBBER.include('hello')

  task :default => ["hello"]

  file 'main.o' => ["main.c", "greet.h"] do
    sh "cc -c -o main.o main.c" 
  end

  file 'greet.o' => ['greet.c'] do
    sh "cc -c -o greet.o greet.c" 
  end

  file "hello" => ["main.o", "greet.o"] do
    sh "cc -o hello main.o greet.o" 
  end

Ok, now its time to address the redundant compile commands.

Dynamically Building Tasks

The command to compile the main.c and greet.c files is identical, except for the name of the files involved. The simpliest and most direct way to address the problem is to define the compile task in a loop. Perhaps something like this …

  SRC = FileList['*.c']
  SRC.each do |fn|
    obj = fn.sub(/\.[^.]*$/, '.o')
    file obj  do
      sh "cc -c -o #{obj} #{fn}" 
    end
  end

Just a couple things to note about the above code.

  • The dependencies are not specified. This is a common where we specify the dependents at one place and the actions in another. Rake is smart enough to combine the dependencies with the actions.
  • Although the task was named after the .o (which is, after all, what we want to generate), the file list is defined in terms of the .c files. Why?

The simple reason is that file lists search for file names that exist in the file system. We have no guarantee that the .o files even exist at this point (indeed, the will not after invoking the clean task). The .c are source and will always be there.

Rake Can Automatically Generate Tasks

Defining tasks in a loop is pretty cool, but is really not needed in a number of simple cases. Rake can automatically generate file based tasks according to some simple pattern matching rules.

For example, we can capture the above logic in a single rule … no need to find all the source files and iterate through them.

  rule '.o' => '.c' do |t|
    sh "cc -c -o #{t.name} #{t.source}" 
  end

The above rule says that if you want to generate a file ending in .o, then you if you have a file with the same base name, but ending in .c, then you can generate the .o from the .c.

t.name is the name of the task, and in file based tasks will be the name of the file we are trying to generate. t.source is the name of the source file, i.e. the one that matches the second have of the rule pattern. t.source is only valid in the body of a rule.

Rules are actually much more flexible than you are led to believe here. But that’s an advanced topic that we will save for another day.

Final Rakefile

Here is our final resule. Notice how we use the SRC and OBJ file lists to manage our lists of scource files and object files.

  require 'rake/clean'

  CLEAN.include('*.o')
  CLOBBER.include('hello')

  task :default => ["hello"]

  SRC = FileList['*.c']
  OBJ = SRC.ext('o')

  rule '.o' => '.c' do |t|
    sh "cc -c -o #{t.name} #{t.source}" 
  end

  file "hello" => OBJ do
    sh "cc -o hello #{OBJ}" 
  end

  # File dependencies go here ...
  file 'main.o' => ['main.c', 'greet.h']
  file 'greet.o' => ['greet.c']

Up Next

In our next tutorial, we will look at using Rake to handle some tasks other than compiling C code.


Rake Tutorial -- Getting Started   03 Apr 05
[ print link all ]
Received via EMail:
I have just started using the excellent Rake tool (thanks, Jim!) and I am at a bit of a loss on how to proceed. I am attempting to create unit test for some C++ code I am creating, […]
Several people recently have made similar comments, they really like rake, but have had trouble getting started. Although the Rake documentation is fairly complete, it really does assume you are familiar with other build tools such as ant and make. It is not really material for the newbie.

To adderess this lack, I’m going to post several Rake tutorial articles that will take you through some of the basics. Eventually, I’ll organize the articles into a document somewhere.

Here’s the first one!

The Problem

We will start with a very simple build problem, the type of problem that make (and now rake) were desiged to deal with.

Suppose I am a C programmer and I have a simple C program consisting of the following files.

main.c

  #include "greet.h"
  int main() {
      greet ("World");
      return 0;
  }

greet.h

  extern void greet(const char * who);

greet.c

  #include <stdio.h>
  void greet (const char * who) {
      printf ("Hello, %s\n", who);
  }

(Yes, it really is the old standard "Hello, World" program. I did say we were starting with the basics!)

To compile and run this collection of files, a simple shell script like the following is adequate.

build.sh

  cc -c -o main.o main.c
  cc -c -o greet.o greet.c
  cc -o hello main.o greet.o
For those not familiar with compiling C code, the cc command is the C compiler. It generates an output file (specified by the -o flag) from the source files listed on the command line.

Running it gives us the following results …

  $ build.sh
  $ ./hello
  Hello, World

Building C Programs

Compiling C programs is really a two step process. First you compile all the source code file into object files. Then you take all the object files and link them together to make the executable.

The following figure illustrates the progression from source files to object files to executable program.

Our program is so small that there is little benefit in doing more than the three line build script above. However, as projects grow, there are more and more source files and object files to manage. Recompiling everything for a simple one line change in a single source file gets old quickly. It is much more efficient to just recompile the few files that change and then relink.

But how do we know what to recompile? Keeping track of that would be quite error prone if we tried to do that by hand. Here is where Rake become useful.

File Dependencies

First, lets take a look at when files need to be recompiled. Consider the main.o. Obviously if the main.c file changes, then we need to rebuild main.o. But are the other files that can trigger a recompile of main.o?

Actually, yes. Looking at the source of main.c, we see that it includes the header file greet.h. That means any changes in greet.h could possibly effect the main.o file as well.

We say that main.o has a dependency on the files main.c and greet.h. We can capture this dependency in Rake with the following line:

  file "main.o" => ["main.c", "greet.h"]

The rake dependency declaration is just regular Ruby code. We take advantage of the fact that we can construct hash arguments on the fly, and that Ruby doesn’t require parenthesis around the method arguement to create a file task declaration that reads very naturally to the humans reading the rake file. But its still just Ruby code.

Likewise, we can declare the dependencies for creating the "greet.o" file as well.

  file "greet.o" => ["greet.c"]

greet.c does include stdio.h, but since that is a system header file and not subject to change (often), we can leave it out of the dependency list.

Finally we can declare the dependencies for the executable program hello. It just depends on the two object files.

  file "hello" => ["main.o", "greet.o"]

Notice that we only have to declare the direct dependencies of hello. Yes, hello depends on main.o which in turn depends on main.c. But the .c files are not directly used in building hello, so they can safely be omitted from the list.

Building the Files

We have carefully specified how the files are related. Now we need to say what Rake would have to do to build the files when needed.

This part is pretty simple. The three line build script that we started with contains all the commands needed to build the program. We just need to put those actions with the right set of dependencies. Use a Ruby do / end block to capture actions …

The result looks like this:

Rakefile

  file 'main.o' => ["main.c", "greet.h"] do
    sh "cc -c -o main.o main.c"
  end

  file 'greet.o' => ['greet.c'] do
    sh "cc -c -o greet.o greet.c"
  end

  file "hello" => ["main.o", "greet.o"] do
    sh "cc -o hello main.o greet.o"
  end

Trying it out

So, let’s see if it works!

  $ rake hello
  (in /home/jim/pgm/rake/intro)
  cc -c -o main.o main.c
  cc -c -o greet.o greet.c
  cc -o hello main.o greet.o

The command line rake hello instructs rake to look through its list of tasks and find one called "hello". It then checks hello’s dependencies and builds them if required. Finally, when everything is ready it builds hello by executing the C compiler command.

Rake dutifully reports what it is doing as it goes along. We can see that each compiler invocation is done in the correct order, building the main program at the end. So, does the program work? Let’s find out.

  $ ./hello
  Hello, World

Success!

But what happens when we change a file. Lets change the greet function in greet.c to print "Hi" instead of hello.

  $ xemacs greet.c
  $ rake hello
  (in /home/jim/pgm/rake/intro)
  cc -c -o greet.o greet.c
  cc -o hello main.o greet.o
  $
  $ ./hello
  Hi, World

Notice that it recompiles greet.c making a new greet.o. And then it needs to relink hello with the new greet.o. Then it is done. There is no need to recompile main.c since it never changed.

What do you think will happend if we run Rake again?

  $ rake hello
  (in /home/jim/pgm/rake/intro)
  $

That’s right … nothing. Everything is up to date with its dependencies, so there is no work for Rake to do.

Ok, sure. Rake is a bit of overkill for only two source files and a header. But imagine a large project with hundreds of files and dependencies. All of a sudden, a tool like Rake becomes very attractive.

Summary

What have we learned? Building a Rakefile involves identifying dependencies and the actions required to create the target files. Then declaring the dependencies and actions are as simple as writing them down in standard Ruby code. Rake then handles the details of building

What’s Up Next

We notice that even our small example has a bit of duplication in it. We have specify how to compile both C file separately, even though the only difference is the files that are used. The next installment will look at fixing that problem as well as introduce non-file based tasks, rules and file lists.

Until then … Code Red, Code Ruby.


Rake 0.5.0 Released   26 Mar 05
[ print link all ]
It has been a long time in coming, but we finally have a new version of Rake available.

Changes

  • Fixed bug where missing intermediate file dependencies could cause an abort with —trace or —dry-run. (Brian Chandler)
  • Recursive rules are now supported (Tilman Sauerbeck).
  • Added tar.gz and tar.bz2 support to package task (Tilman Sauerbeck).
  • Added warning option for the Test Task (requested by Eric Hodel).
  • The jamis rdoc template is only used if it exists.
  • Added fix for Ruby 1.8.2 test/unit and rails problem.
  • Added contributed rake man file. (Jani Monoses)
  • Fixed documentation that was lacking the Rake module name (Tilman Sauerbeck).

What is Rake

Rake is a build tool similar to the make program in many ways. But instead of cryptic make recipes, Rake uses standard Ruby code to declare tasks and dependencies. You have the full power of a modern scripting language built right into your build tool.

Availability

The easiest way to get and install rake is via RubyGems …

  gem install rake    (you may need root/admin privileges)

Otherwise, you can get it from the more traditional places:

Home Page:rake.rubyforge.org/
Download:rubyforge.org/project/showfiles.php?group_id=50

Thanks

Lots of people provided input to this release. Thanks to Tilman Sauerbeck for numerous patches, documentation fixes and suggestions. And for also pushing me to get this release out. Also, thanks to Brian Chandler for the finding and fixing —trace/dry-run fix. That was an obscure bug. Also to Eric Hodel for some good suggestions.

— Jim Weirich


Web Programming with Continuations   25 Mar 05
[ print link all ]
An easy introduction to a mind bending technique.

Playing with continuations is great fun, but thinking deeply about them does tend to stretch the brain cells. If you always wanted to understand continuations better, but found them a bit hard to comprehend, Mikael Brockman has written a wonderful little introduction on the topic (via Tim Bray).

If you are interested in real world uses of continuations, see SeaSide and Borges.


 

Formatted: 17-May-08 14:33
Feedback: jim@weirichhouse.org