1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
---
title: make
subtitle: best practices
layout: nosidebar
links:
- {rel: stylesheet, href: 'assets/css/guides.css'}
features:
- note: This should go on top of every Makefile.
sections:
- do:
- |
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
- note: Quote command arguments and use the `escape` function on variables and shell output.
sections:
- do:
- |
var := Includes ' quote
test:
printf '%s\n' '$(call escape,$(var))'
dont:
- |
var := Includes space
test:
printf '%s\n' $(var)
- |
var := Includes ' quote
test:
printf '%s\n' '$(var)'
- do:
- |
cwd := $(shell pwd)
test:
printf 'In directory %s\n' '$(call escape,$(cwd))'
dont:
- |
cwd := $(shell pwd)
test:
printf 'In directory %s\n' $(cwd)
- |
cwd := $(shell pwd)
test:
printf 'In directory %s\n' '$(cwd)'
- note: Use the `noexpand` function on environment variables or variables that can be overridden on the command line.
sections:
- do:
- |
has_default ?= Default value
$(eval $(call noexpand,has_default))
test:
echo '$(call escape,$(has_default))'
dont:
- |
has_default ?= Default value
test:
echo '$(call escape,$(has_default))'
- |
has_default ?= Default value
export has_default
test:
echo "$$has_default"
- do:
- |
$(eval $(call noexpand,ENV_VAR))
test:
echo '$(call escape,$(ENV_VAR))'
dont:
- |
test:
echo '$(call escape,$(ENV_VAR))'
---
I've made a [detailed blog post] about how all of this works.
{: .alert .alert-info }
[detailed blog post]: {% post_url 2020-05-20-makefile-escaping %}
{% for feature in page.features %}
{{ feature.note | markdownify }}
{% for section in feature.sections %}
<div class="row">
{% if section.do %}
{% if section.dont %}{% assign width = "6" %}{% else %}{% assign width = "12" %}{% endif %}
<div class="col-md-{{ width }}">
{% for guide in section.do %}
<div class="pre_container pre_do">
<pre>{{ guide }}</pre>
<div class="pre_mark"><span class="glyphicon glyphicon-ok"></span></div>
</div>
{% endfor %}
</div>
{% endif %}
{% if section.dont %}
{% if section.do %}{% assign width = "6" %}{% else %}{% assign width = "12" %}{% endif %}
<div class="col-md-{{ width }}">
{% for guide in section.dont %}
<div class="pre_container pre_dont">
<pre>{{ guide }}</pre>
<div class="pre_mark"><span class="glyphicon glyphicon-remove"></span></div>
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
<hr/>
{% endfor %}
|