Getting Rake's PackageTask to depend on generated files

September 17, 2008 📬 Get My Weekly Newsletter

Been playing with Rake lately and decided to use it to package up the PHP Client Library for the Gliffy integration API. Didn't seem to make sense to use ant for something that amounts to creating a tarball. make would be appropriate here, too, but I figured it would be cool to use Rake and there's not really much harm in doing so. A large annoyance is Rake::PackageTask. This is a seemingly handy task that creates tars, zips, etc. and is pretty useful. It's not a task in and of itself, but it creates the :package task:
Rake::PackageTask.new("gliffy-php-client",GLIFFY_VERSION) do |p|
    p.need_tar = true
    p.need_zip = true
    p.package_files = SRC_FILES + EXAMPLE_FILES + DOC_FILES
end
Unfortunately, this doesn't do what it seems to do. DOC_FILES is the list of documentation files output by phpDocumentor and are not checked into version control. The syntax of the PackageTask makes it appear that the code in the block will run when the :package task executes, however this is not the case. This code is initialization code. So, I tried:
# DOC_DIR is the dir generated by phpdoc, a task elsewhere

# uses this to kick off phpdoc

task :package => DOC_DIR
The result is that the tarball and zip files are created and then the documentation is generated. The reason is that PackageTask.new creates a set of tasks and the actual creation of the tarball/zip file is done via a file task, upon which :package is dependent. So, the real dependency I created was:
task :package => "gliffy-php-client.zip" "gliffy-php-client.tgz" DOC_DIR
Examining the source code, a task named for the directory created by :package is created. This task is dependent on the package_files set up in the constructor. So this is the task I need to use:
# Have to keep a reference to the PackageTask object

package_task = Rake::PackageTask.new("gliffy-php-client",GLIFFY_VERSION) do |p|
    p.need_tar = true
    p.need_zip = true
    # Executed BEFORE any other tasks; DOC_FILES don't exist  yet

    p.package_files = SRC_FILES + EXAMPLE_FILES
end

file package_task.package_dir_path => DOC_DIR

file DOC_DIR => SRC_FILES + EXAMPLE_FILES do |t|
    system("phpdoc #{PHP_DOC_ARGS}");
    doc_files = FileList.new(DOC_DIR + "/**/**");
    # Have to add these files to the package_task file list

    package_task.package_files = package_task.package_files + doc_files
end
This is definitely a hack, because I'm depending on the internal implementation of the PackageTask. It really needs a facility for including generated files. In make, I could just send the directory DOC_DIR to tar and it would pick up everything. In Ant, I'd probably have to spawn another ant, since ant sets all property vaules at startup time.