Skip to main content

Makefile builds great again

This is a story of why we have migrated from Phing to Make.

by nick.schuch /

Lets preface this by saying that Phing is a great tool, we just weren't using it in the right way.

After using Phing for 2 years, it’s now easy to see that Phing is competing with projects like:

  • Drush - http://www.drush.org/en/master
  • Drupal Console - https://drupalconsole.com
  • Symfony Console - http://symfony.com/doc/master//components/console.html

All the above tools being native (PHP) command line applications that have the ability to bootstrap Drupal and do interesting things. We never took this approach because we already had these tools and we were just wrapping them in Phing.

To make (pun intended) matters worse, we were also starting to reinvent the wheel with Robo and wrapped our scripts in Object Oriented PHP. While this gave us test coverage for our steps, our build steps aren’t anything more than declarations of the CLI steps a developer should use to build the project. The logic should be reside in simple first class CLI applications.

Here are some of the reasons we finally decided to migrate over to a Makefile workflow.

Composer workflow

Phing was not ideal when it came time for us to adopt a composer based workflow.

Phing was always our entry point into a project, and now with "composer install" handling a lot of our application dependencies, we found the lines blurring.

Multiple languages

We have also adopted additional languages as part of our projects:

  • Application Developers = PHP
  • Frontend developers = Nodejs
  • Operations = Golang

There are no benefits to wrapping a Nodejs or Golang package with Phing (unless your really really love Phing).

So we simply rely on each project being able to be built via the command:

make

Simple definition files

I mentioned above that we were using Phing wrong, here is an example of how we were doing that.

We wrapped every exec call in this (ouch!):


<target name="cache-clear"        description="Clear Drupal cache.">  <exec command="${drush.cmd} cc all"        logoutput="true" /></target>

Instead of using native Phing objects (PHP code) to bootstrap the application and clear the cache, we were writing glorified bash scripts wrapped by XML! This made our build steps overly verbose, and very hard to read, modify and share.

After migrating to a Makefile we have found ourselves with cleaner definition files:

This is just a small portion of our Makfiles.

#!/usr/bin/make -f

PHPCS_STANDARD=vendor/drupal/coder/coder_sniffer/Drupal/ruleset.xml
PHPCS_EXTENSIONS='php,module,inc,install,test,profile,theme'
PHPCS_INGORE='*/libraries*/,*/contrib/*,*/*.features.*,*/*.field_group.inc,*/*.layout.*,*/*.pages_default.*,*/*.panels_default.*,*/*strongarm.inc,*/*.views_default.inc'
PHPCS_DIRS=app/sites/all/modules/custom app/sites/all/themes/custom

build: deps lint

deps:
        composer install --prefer-dist --no-progress
        npm install

lint:
        bin/phpcs --report=full \
                  --standard=$(PHPCS_STANDARD) \
                  --extensions=$(PHPCS_EXTENSIONS) \
                  --ignore=$(PHPCS_IGNORE) \
                  $(PHPCS_DIRS)

Don't get me wrong, you can write very messy Makefiles, but the Makefile has given put us in the right direction.

More contribution

Internally we have a "scaffold" project which we use for bootstrapping new Drupal projects, this comes preloaded with a generic workflow (Makefile) and dependency graph (composer.json and packages.json).

Since migrating to a Makefile approach we have seen a huge growth in collaboration on the Makefile in this "scaffold" project, something I haven't seen during our Phing build system approach.

Conclusion

This is a great example of where "old and boring" technology really shines. The Makefile has given us a sturdy base for future projects regardless of the language or how we wish to build them.

We aren’t the only ones from the PHP community who think this is a great approach, see the latest blog post from Fabien Potencier http://fabien.potencier.org/symfony4-best-practices.html.

Are you using make or any other build tools? Let me know in the comments.