Makefiles provide an easy way to group multiple terminal commands into a single command using
make <command>. This gives a brief overview with just enough information to write your first Makefile.
Apparently Make was originally developed to build executable programs, but I have seen an number of examples of people using Make to manage Python workflows. In this example, let's say we have a Python script in several repositories that we use to update files in each respective repository. From the command line, we can easily
cd into each and
python build.py to run the update script and then commit the changes. Using a Makefile, however, we can automate all of that into a single command:
make publish. Let's take a look at how to do this.
Writing a Makefile
To start, our entire Makefile is below (and available for download here):.
PY?=python3 help: @echo ' ' @echo 'Makefile to update websites on MAG GitHub pages ' @echo ' ' @echo 'Usage: ' @echo ' make data MILE_file_copy and update_utilization ' @echo ' make html regenerate the websites ' @echo ' make publish regenerate websites, then publish to GitHub ' @echo ' ' data: python ../MILE_Data/MILE_file_copy.py cd ../Aircraft-Data/Utilization/Scripts; python update_utilization.py html: data cd ../CommercialData/scripts; python build.py cd ../MarketView/scripts; python build.py cd ../FleetView/scripts; python build.py publish: html @echo ' ' cd ../CommercialData; git pull origin master cd ../CommercialData; git add -A cd ../CommercialData; git commit -m "auto-regenerate from make" cd ../CommercialData; git push origin master @echo ' ' cd ../MarketView; git pull origin master cd ../MarketView; git add -A cd ../MarketView; git commit -m "auto-regenerate from make" cd ../MarketView; git push origin master @echo ' ' cd ../FleetView; git pull origin master cd ../FleetView; git add -A cd ../FleetView; git commit -m "auto-regenerate from make" cd ../FleetView; git push origin master
Let's break this down to understand how to construct a Makefile. A Makefile has this basic structure (see the complete Make documentation, particularly section 2.1):
target … : prerequisites … recipe … …
targetis name of the make command we are constructing. In our Makefile,
data: ...means we can enter the command
make datafrom the command line.
prerequisitesare targets to call before calling our
recipe. In our Makefile, when we call
make htmlwill be automatically be executed first because it is a prerequisite.
recipeis the group of commands our make command performs. Each line is a command, but commands can be given on the same line separated by
;. When we call
make datain our Makefile, the first command run is executing
python ../MILE_Data/MILE_file_copy.py, and so on until all commands are completed.
We can now define Make commands, group tasks we want to perform, and define prerequisites as necessary. As with anything there is much more to learn about Makefiles, but this is enough to get you started.
A Note on Directories
cwd of Python when run from a Makefile will by default be the directory that contains the Makefile. This may be an issue if you are running Python scripts that assume a
cwd where they are located. To address this, you can enter the appropriate directory and execute the script on the same line in the Makefile, for example:
cd ../MarketView/scripts; python build.py
Back to our example, the previous process required us to:
cdinto each repo
python build.pyupdate files
- commit the changes
- repeat or each
Using this Makefile, the process now is simply:
cdin to the directory containing
Whenever you find yourself doing the same rote task often it may be a good time to ask yourself if some simple automation is appropriate. For anything you perform at the command line, Makefiles can be a lightweight automation solution.