Generic Python Project Makefile
Configuration Management Working Group
October 25, 2016
Makefile for Python Web Development & Related Projects
Who
-
Alex Clark
- Python Web Developer (for hire, forever)
- Pillow (Python Imaging Library fork) author
- Partner/President & Executive Director (ACLARK.NET, LLC/DC Python)
- Systems Administrator (NIH)
- (former) Network Engineer (BBN)
- Would-be Computer Science PhD candidate
- "Hacker" (I <3 UNIX & command line)
(Not a GNU Make expert)
What
-
Makefile for Python Web Development & related projects.
-
Django (startapp, startproject, etc.)
-
Python packaging (flake8, yapf, etc.)
-
Heroku (debug, push, etc.)
-
Where
- https://github.com/aclark4life/project-makefile
When
- Initial commit: January 12, 2016
- https://github.com/aclark4life/project-makefile/commit/01a85c746d4a06058fcb4749e85186325449f34b
- Originally "django-project"
Why
-
Laziness e.g.
-
$ make world
-
-
Familiarity e.g.
-
$ ./configure; make; make install
-
-
Simplicity e.g.
-
$ cp ~/Developer/project-makefile <DIR>
-
Car Analogy
If <YOUR_FAV_CM_SOFT> is a sports car…
____----------- _____ \~~~~~~~~~~/~_--~~~------~~~~~ \ `---`\ _-~ | \ _-~ <_ | \[] / ___ ~~--[""] | ________-------'_ > /~` \ |-. `\~~.~~~~~ _ ~ - _ ~| ||\% | | ~ ._ ~ _ ~ ._ `_//|_% \ | ~ . ~-_ /\ `--__ | _-____ /\ ~-_ \/. ~--_ / ,/ -~-_ \ \/ _______---~/ ~~-/._< \ \`~~~~~~~~~~~~~ ##--~/ \ ) |`------##---~~~~-~ ) ) ~-_/_/ ~~ ~~
E.g. Ansible, Chef, Puppet
This Makefile is…
A Volkswagen Beetle
(the old one)
_________ This _.--""'-----, `"--.._ Makefile .-'' _/_ ; .'"----,`-, .' :___: ; : ;;`.`. . _.- _.- .' : :: `.. __;..----------------' :: ___ :: ;; .--"". ' ___.....`:=(___)-' :--'`. .' .' .--''__ : ==: ; .--/ / .'.'' ``-, : : '`-. ."', : / .'-`\\ .--.\ : : , _\ ; ; | ; /:' ;; /__ \\: : : /_\\ |\_/ | | / \__// /"--\\ \: : : ;|`\| : " /\__/\____// """ / \\ : : : :|'|| ["""""""""--------........._ / || ; __.:--' :|//| "------....______ ].'| // |--"""'__...-'`\ \// `| GNUMAKE |__;_...--'": : \ // |---""" \__\_/ """""""""' \ \ \_.// / `---' \ \_ _' `--`---' dp
Context is Key
Possible Alternatives, Dependent on Context
- Ansible, Chef, Puppet
- Buildout
-
[buildout] extends = http://your-project
-
- Shell
-
alias do="echo do stuff"
-
- Fabric
-
def do_stuff(): print("do stuff")
-
- Grunt
- Rake
Questions
Ask anytime
Overview of GNU Make
- "The make utility automatically determines which pieces of a large program need to be recompiled, and issues commands to recompile them…Our examples show C programs, since they are most common, but you can use make with any programming language whose compiler can be run with a shell command. Indeed, make is not limited to programs. You can use it to describe any task where some files must be updated automatically from others whenever the others change." (https://www.gnu.org/software/make/manual/html_node/Overview.html#Overview)
Overview of GNU Make
- "Certain standard ways of remaking target files are used very often. For example, one customary way to make an object file is from a C source file using the C compiler, cc." (https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html#Implicit-Rules)
GNUMakefile
Makefile
makefile
all: average counter list roach average: gcc average.c -o average counter: gcc counter.c -o counter list: gcc list.c -o list roach: gcc roach.c -o roach trapezoid: gcc trapezoid.c -o trapezoid clean: rm average counter list roach
A Makefile
Just
Type
$ make
all: average counter list roach average: gcc average.c -o average counter: gcc counter.c -o counter list: gcc list.c -o list roach: gcc roach.c -o roach trapezoid: gcc trapezoid.c -o trapezoid clean: rm average counter list roach
Without Implicit Rule Usage
objects = average.o all: average counter list roach average: $(objects) gcc -o average $(objects) counter: gcc counter.c -o counter list: gcc list.c -o list roach: gcc roach.c -o roach trapezoid: gcc trapezoid.c -o trapezoid clean: rm average counter list roach
With Implicit Rule Usage
See what I did there?
Replaced explicit file (.c) compilation with implicit object (.o) compilation.
Implicit Behavior is Awesome!
(Except in Python)
Terminology
"Makefile Moment #0"
- "A variable is a name defined in a makefile to represent a string of text, called the variable’s value. These values are substituted by explicit request into targets, prerequisites, recipes, and other parts of the makefile. (In some other versions of make, variables are called macros.) (https://www.gnu.org/software/make/manual/html_node/Using-Variables.html)
Installation
-
mkdir <YOUR-PROJECT>
-
cd <YOUR-PROJECT>
-
curl -O https://raw.githubusercontent.com\ /aclark4life/project-makefile/master/Makefile
Usage
$ make help Usage: make [TARGET] Available targets: - ablog-build - ablog-init - ablog-serve …
Terminology
"Makefile Moment #1"
-
A target is usually the name of a file that is generated by a program; examples of targets are executable or object files. A target can also be the name of an action to carry out, such as ‘clean’ (see Phony Targets). (https://www.gnu.org/software/make/manual/make.html#Rule-Introduction)
Example #1
$ make help
Target
help: @echo "Usage:…
help: @echo "Usage: make [TARGET]\nAvailable targets:\n" @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F:\ '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}'\ | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs | tr ' ' '\n' | awk\ '{print " - "$$0}' | less # http://stackoverflow.com/a/26339924 @echo "\n"
Terminology
"Makefile Moment #2"
- "The goals are the targets that make should strive ultimately to update. Other targets are updated as well if they appear as prerequisites of goals, or prerequisites of prerequisites of goals, etc.
By default, the goal is the first target in the makefile (not counting targets that start with a period). Therefore, makefiles are usually written so that the first target is for compiling the entire program or programs they describe… You can manage the selection of the default goal from within your makefile using the .DEFAULT_GOAL variable " (https://www.gnu.org/software/make/manual/html_node/Goals.html)
targets : prerequisites recipe …
(https://www.gnu.org/software/make/manual/html_node/Rule-Syntax.html#Rule-Syntax)
Terminology
Makefile Moment #3
Example #2
$ make
Target
.DEFAULT_GOAL=git-commit-auto-push
…
git-commit-auto-push: git-commit-auto git-push
# Git MESSAGE="Update" … commit-auto: git-commit-auto # Alias commit-edit: git-commit-edit # Alias git-commit: git-commit-auto # Alias git-commit-auto-push: git-commit-auto git-push … git-commit-auto: git commit -a -m $(MESSAGE) git-commit-edit: git commit -a git-push: git push
Example #3
$ make ablog-init
Target
ablog-init:
bin/ablog start
A Bit
About…
Python
Python
- virtualenv
- pip
- requirements.txt
- source bin/activate
- bin/python
Example #4
$ make ablog
Target
ablog: ablog-clean \ ablog-install\ ablog-init \ ablog-build \ ablog-serve
Example #5
$ make django
Target
django: django-clean \ django-install\ django-init \ django-migrate\ django-su\ django-serve
Terminology
"Makefile Moment #4"
- "A rule appears in the makefile and says when and how to remake certain files, called the rule’s targets (most often only one per rule). It lists the other files that are the prerequisites of the target, and the recipe to use to create or update the target." (https://www.gnu.org/software/make/manual/make.html#Rules)
Example #6
$ make sphinx
Target
sphinx: sphinx-clean \ sphinx-install \ sphinx-init \ sphinx-build \ sphinx-serve
A Bit
About…
JavaScript
JavaScript
- NPM
- webpack
- Grunt
Example #7
$ make grunt
Target
grunt: grunt-init \ grunt-serve
Terminology "Makefile Moment #5"
- Ignore errors in a recipe with "-"
- -ls one
- -ls two
- ls three
Example #8
$ make npm
Target
npm: npm-init \ npm-install
A Bit
About…
Apps/Utils
Apps/Utils
- ABlog
- Plone
- Sphinx
- Vagrant
Example #9
$ make plone
Target
plone: plone-install \ plone-init\ plone-serve
Example #10
$ make vagrant
Target
vagrant: vagrant-init
Example #12
$ make django
Target
django: django-clean\ django-install\ django-init \ django-migrate\ django-su \ django-serve
$ make lint
lint: python-lint python-lint: python-flake\ python-yapf\ python-wc
Pros
- Easy to install and use
- Unified usage of various technologies
Cons
- Arguably wrong tool for the job
- Static PROJECT/APP definition
Todo
- Support customization
- Include other makefiles
- Redefine targets
- Support additional programming languages, apps, utils, etc.
Recap
- GNU Make
- Targets, Recipes, Rules, Prerequisites
- Python
- pip, virtualenv, requirements.txt
- JavaScript
- Grunt, Node Package Manager (NPM)
- Apps & Utils
- ABlog, Plone, Sphinx, Vagrant
The End
- https://github.com/aclark4life/project-makefile
- http://slides.com/aclark/project-makefile
Credits/Thanks
- Jeff @ CMWG, attendees, reviewers
- https://github.com/hakimel/reveal.js
- https://slides.com
- http://www.ascii-code.com/ascii-art/vehicles/cars.php
Project Makefile
By Jeffrey A Clark
Project Makefile
- 3,419