Make is the original UNIX build tool. It existed a long time before gulp, or grunt. Loved by some, loathed by others it is at least worth being aware of how
make works, what the strengths are and where it falls short.
Make is available on UNIX-like systems. That means OSX, BSD and Linux. It exposes any system command meaning that you can run system commands and execute arbitrary scripts. There is no doubt that tools like gulp and grunt are inpsired by or at least a reaction to
make you create a Makefile and then run
make [what to run] from the terminal. In the following examples it is assumed
make build will be run from the terminal.
A common build task is to concatenate various files into a single file. In the tradition of UNIX single line commands this is easy.
build: mkdirs concat-css mkdirs: @mkdir -p ./build/css concat-css: @cat ./src/stylesheets/*\.css > ./build/css/application.css
That’s it - five lines of code.
UNIX tools already exist to make directories and combine files and they are fast because more often than not the underlying tools are C based.
We can extend the previous example to minify the CSS using the cssmin node module to minify the css too.
build: mkdirs concat-css min-css mkdirs: @mkdir -p ./build/css concat-css: @cat ./src/stylesheets/*\.css > ./build/css/application.css.tmp min-css: @./node_modules/cssmin/bin/cssmin ./src/css/application.css.tmp > ./build/css/application.css && rm ./build/css/application.css.tmp
UNIX has many tools for copying files around the filesystem. One of those tools is rsync. It lets you synchronise folders on your own filesystem or even over the network.
build: copy-files copy-files: @rsync -aq ./src/ ./build
If you want to exclude files or folders you can do it like this
build: copy-files copy-files: @rsync -aq --exclude='_*' ./src/ ./build
This will exclude any folder names prefixed with _.
build: uglifyjs uglifyjs: @./node_modules/uglify-js/bin/uglifyjs ./build/js/main.js.tmp > ./build/js/main.js && rm ./build/js/main.js.tmp
It is fast. In all tests I’ve run locally using system commands via a Makefile is always faster than using a build framework.
It is simple. If you can complete a task in five lines of code there is less to go wrong and it is easier to understand.
Probably the biggest weakness is that Make is not cross platform. So if you have a windows developer in your team they will have to jump through some hoops to get it working. Make can also become unmaintainable as it is just one big file. Of course you can break tasks down to individual bash scripts that get called in the Makefile.
Managing dependencies is a manual process. For node modules you can use npm to make sure a particular version is available but for UNIX tools you are on your own. Some UNIX tools vary between platforms both in terms of where they are located and what they allow you to do. GNU sed is different from BSD sed for example.
For a super lightweight build system you can also just craft your own bash scripts and ignore Make altogether.
There is a tendency within any programming community to want to do everything in the community’s language. But sometimes the problem has already been solved by men with beards in the 1970’s. If you can park the hipster hacker mentality there are tools that have been around for a long time that are stable and fast that already solve your problem. The main thing is to keep it small and distinct. If you know a little UNIX maybe you should try
make or a small bash script as your build tool.
Have an update or suggestion for this article? You can edit it here and send me a pull request.
Using HashiCorp Vault with LDAP
How to use HashiCorp Vault to setup an LDAP backed secret store with read-only access for users in groups and read-write access for specific users
Linux and Unix xargs command tutorial with examples
Tutorial on using xargs, a UNIX and Linux command for building and executing command lines from standard input. Examples of cutting by character, byte position, cutting based on delimiter and how to modify the output delimiter.
Copy a file in Go
How to copy a file in Go. The ioutil package does not offer a shorthand way of copying a file. Instead the os package should be used.