Summary
Commake (Common Makefile) is a base template for a makefile
/justfile
that you can use in your software project. Its purpose is to simplify the process of checking or installing dependencies and running the project, without needing to remember specific commands or constantly refer to the README.
To get started with a project, simply run (or use the equivalent just
commands):
$ make init # Check if the project's dependencies (e.g., Docker) are installed
$ make install # Install project packages (e.g., `yarn install`)
$ make run # Start the project's development environment (e.g., `yarn run`)
Contents
- Introduction
- Specification
- Guidance & Examples
- Usage
- Customising Your Commake
- Contributing
- About
- Licence
- Previous Versions
Introduction
Joining new software projects can be challenging. Often, you need to go through the setup process, but it’s not always clear what requirements you need to install until you run into issues.
Jumping between software projects presents similar difficulties. After being away for a few months, you may forget how to set up the project or which commands to run. In some cases, the commands aren’t included in the README, and you have to ask for help. In other cases, there is no guidance at all, and you’re left to figure it out on your own.
Commake aims to solve these problems by providing a standard template. With Commake, you can easily run the init
, install
, and run
steps to get your project set up and running quickly.
Example - A node project:
If I come back to a Node project, this is my thought process:
- Does this project use yarn or npm?
- Have I got the correct version of node installed?
- Do I need to do an install?
- Do I need to set environment variables?
- How do I serve this? npm run start, npm run serve, npm run dev?
All of this can be solved by using a common makefile across all your projects. So you don’t need to consult the README, remember, or figure it out.
Specification
This is the empty makefile
. Just is slightly different see justfile.
# Commake (v0.2.0) - https://niallbunting.com/commake/
.PHONY: all help init install build run lint test e2e plan deploy int versioncheck
.ONESHELL:
all: lint test run #help Full check
help:
@echo "-- HELP --"
@grep '#[h]elp' makefile
# Use this to check if they have the correct version
# To use update the if statement and the message.
versioncheck:
@if [ 0 -gt 0 ]; then
echo "Wrong version of: <DEP>" &&
exit 1;
fi
init: #help Run through dependencies and check
@echo Not Implemented
install: versioncheck #help Install packages
@echo Not Implemented
build: #help Build the project files
@echo Not Implemented
run: #help Run locally
@echo Not Implemented
lint: #help Run linting
@echo Not Implemented
test: #help Run the unit tests
@echo Not Implemented
int: #help Run the int tests
@echo Not Implemented
e2e: #help Run the e2e tests
@echo Not Implemented
plan: #help Plan to run any infra changes
@echo Not Implemented
deploy: #help Run any infra changes
@echo Not Implemented
# Custom Commands - Put your custom commands below
Guidance
The goal isn’t for these steps to be overly complex—often, they’re just one line. See the examples section.
You don’t need to handle every possible scenario in the script. People may be using different environments or have different setups, and managing those variations can be complicated. That added complexity takes time to address, so it’s better to keep the Commake simple and defer to the developer when necessary.
You can always improve the steps later. The most important thing is to get the steps into the file so that it can serve as a checklist to start with.
Here’s an example of an init
step that checks if Yarn is installed and whether a key is set. If Yarn isn’t found, the script will fail. The second step simply requires the developer to press Enter.
init: #help Run through dependencies and check
yarn --version
@echo Have you set the key in the .env file? && read input
Examples
- Golang (v0.0.1)
- Github Pages (v0.1.0)
- Node (v0.0.1)
Usage
Requirements
You will need make
or just
installed. Make
is often installed by default.
Make Usage
To show all recipes:
$ make help
Otherwise to run a command use make <target>
. For example:
$ make run
or
$ make # To run the all target (lint, test, run)
Just Usage
To show all recipes:
$ just -l
Otherwise to run a command use just <target>
. For example:
$ just run
or
$ just # To run the all target (lint, test, run)
Customising your Commake
Here are some common make steps/commands to help you get started. More in-depth make specific content can be found here.
Note: All makefiles
are tab seperated, they won’t work with spaces.
User interaction
This is useful when you want to pause and wait for the user to continue the script. For example waiting for them to run a command.
@echo "Press ENTER to continue (ctrl+c to cancel)" && @read line
This will check that they press y/Y to continue.
@echo Press Y/y to continue
@read answer; if [ "$answer" != "${answer#[Yy]}" ] ;then echo yes; else echo no; fi
If you want to do something more complex you can use a case statement.
read -p "Do that? [y,n]" doit
case $$doit in
y|Y) echo yes ;;
n|N) echo no ;;
*) echo dont know ;;
esac
Ignore Errors
If you have a command that may fail you can ignore any failures and continue by adding a -
.
-rm somefilethatdoesnotexist
@echo I still get run
Run mupltiple things at once
If you need to run mulitple services at the same time you can do this.
(trap 'kill 0' SIGINT; (command 1) & (command 2))
Silencing commands
By default make
prints out the command it’s about to run. Sometimes you may want to silence this. This is done by adding an at symbol before the command.
Since we run everything as a single line (see more). We only need this on the first line and that’s the only line that counts.
@echo "Dont print me"
Step Dependencies
You might want to run other targets as prerequisites of your command. This is done by adding it after the targets colon. For example before running the project you need to build it.
You can see here that the install
target requires versioncheck
to be run beforehand.
install: versioncheck #help Install packages
@echo Not Implemented
Make arguments
To pass arguments run make
in the following style:
$ make run env=prod
You can then access this like:
run: #help Run locally
@echo $(env)
python test.py $(env)
Variables
Variables from bash are accessed via a double dollar sign.
myvar="test"
echo $$myvar
.PHONY and .ONESHELL
This only applies to the make
version.
Here are some default options that make our life a little easier.
- .PHONY - This means that this isn’t actually a file and is just a command. Without this it will check if a file with the name of the target exists and if it does won’t run the command.
- .ONESHELL - This is more natural for a beginners perspective. It stops each line being run as a different shell.
Contributing
The makefile
and this document are a work in progress. For example not much though has been put into the windows world. I would love to hear your feeback, please open an issue on GitHub.
About
This was created originally by Niall Bunting.