function bundle( pkgs, dest, opts, clbk ) {
	var total;
	var ppath;
	var dpath;
	var pkg;
	var i;

	total = pkgs.length;
	i = -1;

	return next();

	/**
	* Generates the next bundle.
	*
	* @private
	*/
	function next() {
		i += 1;

		pkg = pkgs[ i ];
		ppath = pkg.substring( opts.dir.length+1 ); // +1 to account for path separator
		dpath = path.join( dest, ppath );

		debug( 'Creating output directory: %s', dpath );
		mkdirp( dpath, onDir );
	}

	/**
	* Callback invoked upon creating an output directory.
	*
	* @private
	* @param {Error} [error] - error object
	* @returns {void}
	*/
	function onDir( error ) {
		var bopts;
		if ( error ) {
			debug( 'Encountered an error when creating output directory. Package: %s (%d of %d). Directory: %s. Error: %s', pkg, i+1, total, dpath, error.message );
			return clbk( error );
		}
		debug( 'Successfully created output directory.' );

		debug( 'Generating package bundle %d of %d: %s', i+1, total, pkg );
		bopts = {
			'pattern': opts.files_pattern,
			'bundle': opts.bundle,
			'html': opts.html,
			'mount': opts.mount + ppath,
			'title': opts.title
		};
		build( pkg, dpath, bopts, onBundle );
	}

	/**
	* Callback invoked upon generating a bundle.
	*
	* @private
	* @param {(Error|null)} error - error object
	* @param {boolean} bool - boolean indicating whether a bundle was created
	* @returns {void}
	*/
	function onBundle( error, bool ) {
		if ( error ) {
			debug( 'Encountered an error when generating a bundle. Package: %s (%d of %d). Destination: %s. Error: %s', pkg, i+1, total, dpath, error.message );
			return clbk( error );
		}
		if ( bool ) {
			debug( 'Successfully generated a bundle.' );
		} else {
			debug( 'No bundle generated.' );
		}
		done();
	}

	/**
	* Callback invoked upon generating bundles.
	*
	* @private
	* @returns {void}
	*/
	function done() {
		var j = i + 1;
		if ( j < total ) {
			debug( 'Generated %d of %d bundles.', j, total );
			return next();
		}
		debug( 'Successfully generated all bundles.' );
		return clbk();
	}
}
Generates benchmark bundles for a list of packages.

@private
@param {(EmptyArray|StringArray)} pkgs - package list
@param {string} dest - output directory
@param {Object} opts - options
@param {string} opts.bundle - bundle filename
@param {string} opts.dir - root directory
@param {string} opts.html - HTML filename
@param {string} opts.mount - base URL mount
@param {Object} opts.files_pattern - glob pattern
@param {string} opts.title - HTML title
@param {Callback} clbk - callback to invoke upon completion
@returns {void}