Most of us have heard of Drush by this time. It's a cool command line tool to make it easier to set up and update Drupal. A really handy addition to Drush is Drush Make, a tool that makes it easy to identify all the files needed to create a new Drupal site and automatically retrieve and download them. Most Drupal sites have at least a few files that come from non-Drupal locations -- like javascript or flash libraries that need to be downloaded separately and moved to some specific location within your Drupal installation. Drush Make makes it easy to pull these files together.
All the examples I had seen for Drush Make used Drupal core, but I recently wanted to create a new site using PressFlow, an alternative to the regular Drupal core code that has lots of performance enhancements. The PressFlow files are not hosted on Drupal.org, they need to be retrieved from the PressFlow site. The site will also be using ApacheSolr and jQuery UI, both of which require grabbing code from external locations. I wanted to create a system to pull these files together automatically using Drush Make, but it took a bit of digging to figure out how to do it.
The first step is obviously to install Drush and Drush Make. There are lots of places that show you how to do that, so I won't go into that in this article. Once they are installed, we need to create a makefile. The makefile contains all the information Drush Make will need to identify what files are needed, where and how to retrieve them, and where to put them on my Drupal installation.
A makefile is a plain text file with a name like 'example.make'. The first line of the file should indicate which Drupal version this make file is creating, in this case 6.x. The next line should indicate where to get the core Drupal files. For a normal drupal installation, this would look like the following:
core = 6.x
projects[] = "drupal"
In this case, I want to use PressFlow instead of Drupal core. I finally got a clue about how to do that from an article on groups.drupal.org. So to create a PressFlow installation, I will instead start my make file like this:
core = 6.x
projects[pressflow][type] = "core"
projects[pressflow][download][type] = "get"
projects[pressflow][download][url] = "http://files.pressflow.org/pressflow-6-current.tar.gz"
This site will be using some high performance tools, so I want to include the Drupal Varnish, Memcache, and ApacheSolr modules. To better organize my site, which will eventually have a lot of custom code, I want them all to be in a 'contrib' subdirectory under 'sites/all/modules'. Adding the modules is easy enough:
projects[memcache][subdir] = "contrib"
projects[varnish][subdir] = "contrib"
projects[apachesolr][subdir] = "contrib"
I could specify other information about those files. The above code will automatically retrieve the latest official release for each of those modules, and will download and extract the files into that directory. I could instead specify a specific release.
projects[memcache][subdir] = "contrib"
projects[memcache][version] = "1.4"
Or I could ask for a cvs checkout instead:
projects[memcache][download][module] = "module"
projects[memcache][download][type] = "cvs"
projects[memcache][revision] = "DRUPAL-6--1-4"
In the case of ApacheSolr, I also need to find and download an external library and move it into the apachesolr directory as a subdirectory called 'SolrPhpClient'. Drush Make can do this too. These external files all get put into an array called 'libraries'. By default, anything in 'libraries' will go into a directory at '/sites/all/libraries', but I can instruct it to put the file into a different location.
libraries[SolrPhpClient][download][type] = "get"
libraries[SolrPhpClient][download][url] = "http://solr-php-client.googlecode.com/files/SolrPhpClient.r22.2009-11-09.tgz"
libraries[SolrPhpClient][directory_name] = "SolrPhpClient"
libraries[SolrPhpClient][destination] = "modules/contrib/apachesolr"
There are lots of things I could use as file sources. For instance, I could pick up some files from a feature server:
projects[tao][location] = http://code.developmentseed.org/fserver
projects[rubik][location] = http://code.developmentseed.org/fserver
Putting this all together, I created a makefile for a large D6 site that will use PressFlow and other performance enhancements, and included some modules that create functionality similar to what is provided by Drupal 7, either modules that were added to core in Drupal 7 or backports of some Drupal 7 features:
; DRUPAL VERSION
core = 6.x
; CORE MODULES
projects[pressflow][type] = "core"
projects[pressflow][download][type] = "get"
projects[pressflow][download][url] = "http://files.pressflow.org/pressflow-6-current.tar.gz"
; DEVELOPMENT
projects[devel][subdir] = "contrib"
projects[backup_migrate][subdir] = "contrib"
; PERFORMANCE
projects[memcache][subdir] = "contrib"
projects[varnish][subdir] = "contrib"
; UTILITY
projects[apachesolr][subdir] = "contrib"
projects[libraries][subdir] = "contrib"
projects[jquery_ui][subdir] = "contrib"
projects[modalframe][subdir] = "contrib"
; UI
projects[admin][subdir] = "contrib"
projects[admin][version] = "2.0-beta3"
projects[vertical_tabs][subdir] = "contrib"
projects[wysiwyg][subdir] = "contrib"
; KEY MODULES
projects[cck][subdir] = "contrib"
projects[views][subdir] = "contrib"
projects[token][subdir] = "contrib"
projects[pathauto][subdir] = "contrib"
; FILE/IMAGE HANDLING
projects[filefield][subdir] = "contrib"
projects[imagefield][subdir] = "contrib"
projects[imagecache][subdir] = "contrib"
projects[imageapi][subdir] = "contrib"
projects[transliteration][subdir] = "contrib"
; THEMES
projects[tao][location] = http://code.developmentseed.org/fserver
projects[rubik][location] = http://code.developmentseed.org/fserver
; OTHER FILES
; ApacheSolr
libraries[SolrPhpClient][download][type] = "get"
libraries[SolrPhpClient][download][url] = "http://solr-php-client.googlecode.com/files/SolrPhpClient.r22.2009-11-09.tgz"
libraries[SolrPhpClient][directory_name] = "SolrPhpClient"
libraries[SolrPhpClient][destination] = "modules/contrib/apachesolr"
; jQuery UI
libraries[jquery_ui][download][type] = "get"
libraries[jquery_ui][download][url] = "http://jquery-ui.googlecode.com/files/jquery.ui-1.6.zip"
libraries[jquery_ui][directory_name] = "jquery.ui"
libraries[jquery_ui][destination] = "modules/contrib/jquery_ui"
; TinyMCE
libraries[tinymce][download][type] = "get"
libraries[tinymce][download][url] = "http://downloads.sourceforge.net/project/tinymce/TinyMCE/3.2.7/tinymce_3_2_7.zip"
libraries[tinymce][directory_name] = "tinymce"
Once the file is created I could drop it on my server and execute it as follows, where DESTINATION is my Drupal root directory. The DESTINATION folder cannot already exist, Drush Make insists on creating it if you call it this way:
drush make example.make DESTINATION
Another way to execute the code is to create the directory and put the makefile in it, then cd to the directory and run drush make from there, as:
drush make example.make
Then just sit back and watch the messages scroll past as Drush Make goes out to retrieve all the files in the list, extracts them where necessary, and then moves them to the right place in your Drupal directory.
Important note! I found that some of the things I wanted to do with external files did not work correctly when I tried to do them on my Mac. Eventually I realized that this was due to a Drush Make bug that has been fixed in the very latest development version of Drush Make. In earlier versions the Drupal files were downloaded with no problem but some of the external files were not.
That's the scoop. I hope this information will save everyone else a bit of time. Now go forth and build some sites!
Update! Ben Buckman discovered a better url to use for retrieving the PressFlow code, one that doesn't have to be changed every time there's a new version. He posted a question on the PressFlow site and David Strauss told him to use 'http://files.pressflow.org/pressflow-6-current.tar.gz' instead of the url originally used in this article, 'http://launchpad.net/pressflow/6.x/6.16.77/+download/pressflow-6.16.77.tar.gz'. Great find Ben!