functions for use in build steps
function(assemble, next) {

      grunt.verbose.writeln('Validating options');

      if (utils.endsWithDot(assemble.options.ext)) {
        grunt.warn('Invalid ext "' + assemble.options.ext + '". ext cannot end with a period.');
        done(false);
      }

      // find an engine to use
      assemble.options.engine = assemble.options.engine || 'handlebars';
      grunt.verbose.ok('>> Current engine:'.yellow, assemble.options.engine);

      assemble.engine.load(assemble.options.engine);

      var initializeEngine = function(engine, options) { engine.init(options, { grunt: grunt, assemble: assemble }); };
      assemble.options.initializeEngine = assemble.options.initializeEngine || initializeEngine;

      var registerFunctions = function(engine) { engine.registerFunctions(); };
      assemble.options.registerFunctions = assemble.options.registerFunctions || registerFunctions;

      var registerPartial = function(engine, filename, content) { engine.registerPartial(filename, content); };
      assemble.options.registerPartial = assemble.options.registerPartial || registerPartial;

      assemble.partials = file.expand(assemble.options.partials);

      if (_.isArray(assemble.options.dataFiles) && assemble.options.dataFiles.length > 0) {
        assemble.dataFiles = file.expand(assemble.options.dataFiles);
        //assemble.options.data = {};
      }

      // Expand layout into layoutFiles if a glob pattern is specified
      if (assemble.options.layouts) {
        assemble.layoutFiles = file.expand({filter: 'isFile'}, assemble.options.layouts);
      }

      if (assemble.layoutFiles && assemble.layoutFiles.length !== 0) {
        grunt.verbose.writeln('Found layout files:'.yellow, assemble.layoutFiles);
      } else {
        assemble.layoutFiles = null;
      }

      assemble.options.initializeEngine(assemble.engine, assemble.options);
      assemble.options.registerFunctions(assemble.engine);

      next(assemble);
    }