aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--_notes/makefile.md64
-rw-r--r--_posts/2020-05-20-makefile-escaping.md3
2 files changed, 67 insertions, 0 deletions
diff --git a/_notes/makefile.md b/_notes/makefile.md
new file mode 100644
index 0000000..777e04d
--- /dev/null
+++ b/_notes/makefile.md
@@ -0,0 +1,64 @@
+---
+title: GNU Make
+---
+Best practices for my Makefiles (sorry for the botched highlighting).
+
+```make
+# Put this in the top of the Makefile:
+
+MAKEFLAGS += --no-builtin-rules --no-builtin-variables --warn-undefined-variables
+unexport MAKEFLAGS
+.DEFAULT_GOAL := all
+.DELETE_ON_ERROR:
+.SUFFIXES:
+SHELL := bash
+.SHELLFLAGS := -eu -o pipefail -c
+
+escape = $(subst ','\'',$(1))
+
+define noexpand
+ifeq ($$(origin $(1)),environment)
+ $(1) := $$(value $(1))
+endif
+ifeq ($$(origin $(1)),environment override)
+ $(1) := $$(value $(1))
+endif
+ifeq ($$(origin $(1)),command line)
+ override $(1) := $$(value $(1))
+endif
+endef
+
+# OK, now some examples of how to use it:
+
+.PHONY: all
+all: test-escape test-noexpand
+
+# Always put command arguments in single quotes.
+# Escape variables and shell output using the escape function.
+
+var_with_quote := Includes ' quote
+
+.PHONY: test-escape
+test-escape:
+ printf '%s\n' '$(call escape,$(var_with_quote))'
+ printf '%s\n' '$(call escape,$(shell echo "Includes ' quote"))'
+
+# The above recipe will print "Includes ' quote" twice.
+
+# If you define variables using ?= or use environment variables in your
+# Makefile, use noexpand on them (to safeguard against ${accidental}
+# references).
+
+var_with_default ?= Accidental reference?
+$(eval $(call noexpand,var_with_default))
+
+$(eval $(call noexpand,env_var))
+
+.PHONY: test-noexpand
+test-noexpand:
+ printf '%s\n' '$(call escape,$(var_with_default))'
+ printf '%s\n' '$(call escape,$(env_var))'
+
+# The above recipe will print "Accidental ${reference}" twice if you run using
+# env_var='Accidental ${reference}' make var_with_default='Accidental ${reference}'
+```
diff --git a/_posts/2020-05-20-makefile-escaping.md b/_posts/2020-05-20-makefile-escaping.md
index d16e3b5..bf29657 100644
--- a/_posts/2020-05-20-makefile-escaping.md
+++ b/_posts/2020-05-20-makefile-escaping.md
@@ -35,6 +35,9 @@ variable, but the same rules should apply for all similar `sh`-like shells.
TL;DR
-----
+Visit [this page]({{ site.baseurl }}{% link _notes/makefile.md %}) for an all-in-one Makefile.
+{: .alert .alert-info }
+
* Put the prologue above at the top of your Makefile.
* Quote command arguments in Makefiles using single quotes `'`.
* Don't use `'` and `$` in stuff like file paths/environment variable values,