@hybridlabor-api/aos 4.8.0 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/agents.md +1 -1
- package/.agents/nodes.json +1 -1
- package/.agents/vendor-manifest.json +23 -1
- package/.claude/agents/godmode-media-eventtech.md +1 -1
- package/.claude/hooks/conventional-commits.mjs +125 -0
- package/.claude/hooks/env-file-protection.mjs +105 -0
- package/.claude/hooks/go-gate.mjs +101 -81
- package/.claude/settings.json +13 -0
- package/.opencode/agents/godmode-media-eventtech.md +1 -1
- package/.opencode/plugins/bdb-aos.js +31 -4
- package/README.de.md +1 -1
- package/README.md +1 -1
- package/README.pt.md +1 -1
- package/THIRD_PARTY_NOTICES.md +88 -0
- package/docs/skills_table.md +1 -1
- package/installer.js +174 -46
- package/package.json +6 -2
- package/packages/aos-cli/README.md +80 -0
- package/packages/aos-cli/bin/aos-cli.mjs +134 -0
- package/packages/aos-cli/core-skills.json +12 -0
- package/packages/aos-cli/extensions/aos.ts +321 -0
- package/packages/aos-cli/package-lock.json +1923 -0
- package/packages/aos-cli/package.json +29 -0
- package/packages/aos-cli/scripts/check-theme.mjs +63 -0
- package/packages/aos-cli/themes/aos.json +97 -0
- package/scripts/build-plugin-manifest.mjs +131 -0
- package/scripts/validate-skills.mjs +81 -6
- package/skills/basic/ao-orchestrator/SKILL.md +116 -0
- package/skills/global_config/agenttrail/SKILL.md +6 -1
- package/skills/global_config/ask-tim/SKILL.md +4 -4
- package/skills/global_config/bash-script-generator/SKILL.md +201 -0
- package/skills/global_config/bash-script-generator/assets/templates/standard-template.sh +96 -0
- package/skills/global_config/bash-script-generator/docs/bash-scripting-guide.md +729 -0
- package/skills/global_config/bash-script-generator/docs/generation-best-practices.md +193 -0
- package/skills/global_config/bash-script-generator/docs/script-patterns.md +566 -0
- package/skills/global_config/bash-script-generator/docs/text-processing-guide.md +437 -0
- package/skills/global_config/bash-script-generator/examples/log-analyzer.sh +92 -0
- package/skills/global_config/bash-script-generator/scripts/generate_script_template.sh +123 -0
- package/skills/global_config/bash-script-generator/scripts/run_ci_checks.sh +172 -0
- package/skills/global_config/bash-script-generator/scripts/test_generator.sh +413 -0
- package/skills/global_config/bash-script-validator/SKILL.md +249 -0
- package/skills/global_config/bash-script-validator/docs/awk-reference.md +449 -0
- package/skills/global_config/bash-script-validator/docs/bash-reference.md +468 -0
- package/skills/global_config/bash-script-validator/docs/common-mistakes.md +623 -0
- package/skills/global_config/bash-script-validator/docs/grep-reference.md +395 -0
- package/skills/global_config/bash-script-validator/docs/regex-reference.md +391 -0
- package/skills/global_config/bash-script-validator/docs/sed-reference.md +454 -0
- package/skills/global_config/bash-script-validator/docs/shell-reference.md +463 -0
- package/skills/global_config/bash-script-validator/docs/shellcheck-reference.md +399 -0
- package/skills/global_config/bash-script-validator/examples/bad-bash.sh +55 -0
- package/skills/global_config/bash-script-validator/examples/bad-shell.sh +54 -0
- package/skills/global_config/bash-script-validator/examples/good-bash.sh +71 -0
- package/skills/global_config/bash-script-validator/examples/good-shell.sh +69 -0
- package/skills/global_config/bash-script-validator/scripts/run_ci_checks.sh +23 -0
- package/skills/global_config/bash-script-validator/scripts/shellcheck_wrapper.sh +174 -0
- package/skills/global_config/bash-script-validator/scripts/test_validate.sh +446 -0
- package/skills/global_config/bash-script-validator/scripts/validate.sh +512 -0
- package/skills/global_config/ci-pipeline/SKILL.md +135 -0
- package/skills/global_config/dispatching-parallel-agents/SKILL.md +170 -0
- package/skills/global_config/dockerfile-generator/SKILL.md +1038 -0
- package/skills/global_config/dockerfile-generator/examples/example.dockerignore +95 -0
- package/skills/global_config/dockerfile-generator/examples/golang-distroless.Dockerfile +34 -0
- package/skills/global_config/dockerfile-generator/examples/java-springboot.Dockerfile +45 -0
- package/skills/global_config/dockerfile-generator/examples/nextjs-production.Dockerfile +49 -0
- package/skills/global_config/dockerfile-generator/examples/nodejs-multistage.Dockerfile +55 -0
- package/skills/global_config/dockerfile-generator/examples/python-fastapi.Dockerfile +48 -0
- package/skills/global_config/dockerfile-generator/references/language_specific_guides.md +510 -0
- package/skills/global_config/dockerfile-generator/references/multistage_builds.md +570 -0
- package/skills/global_config/dockerfile-generator/references/optimization_patterns.md +492 -0
- package/skills/global_config/dockerfile-generator/references/security_best_practices.md +375 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_dockerignore.sh +199 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_golang.sh +172 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_java.sh +185 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_nodejs.sh +279 -0
- package/skills/global_config/dockerfile-generator/scripts/generate_python.sh +218 -0
- package/skills/global_config/dockerfile-generator/scripts/test_generator.sh +210 -0
- package/skills/global_config/dockerfile-validator/SKILL.md +300 -0
- package/skills/global_config/dockerfile-validator/examples/.dockerignore.example +34 -0
- package/skills/global_config/dockerfile-validator/examples/bad-example.Dockerfile +37 -0
- package/skills/global_config/dockerfile-validator/examples/golang-distroless.Dockerfile +50 -0
- package/skills/global_config/dockerfile-validator/examples/good-example.Dockerfile +52 -0
- package/skills/global_config/dockerfile-validator/examples/python-optimized.Dockerfile +53 -0
- package/skills/global_config/dockerfile-validator/examples/security-issues.Dockerfile +42 -0
- package/skills/global_config/dockerfile-validator/references/docker_best_practices.md +348 -0
- package/skills/global_config/dockerfile-validator/references/optimization_guide.md +473 -0
- package/skills/global_config/dockerfile-validator/references/security_checklist.md +208 -0
- package/skills/global_config/dockerfile-validator/scripts/dockerfile-validate.sh +699 -0
- package/skills/global_config/dockerfile-validator/scripts/test_validate.sh +35 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn-lock-read.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/copy-before-yarn.Dockerfile +6 -0
- package/skills/global_config/dockerfile-validator/tests/fixtures/from-platform-nonroot.Dockerfile +7 -0
- package/skills/global_config/dockerfile-validator/tests/test_regression.sh +164 -0
- package/skills/global_config/finishing-a-development-branch/SKILL.md +228 -0
- package/skills/global_config/github-actions-generator/SKILL.md +353 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/composite/action.yml +82 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/Dockerfile +25 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/action.yml +42 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/docker/entrypoint.sh +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/action.yml +33 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/index.js +50 -0
- package/skills/global_config/github-actions-generator/assets/templates/action/javascript/package.json +27 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/basic_workflow.yml +242 -0
- package/skills/global_config/github-actions-generator/assets/templates/workflow/reusable_workflow.yml +106 -0
- package/skills/global_config/github-actions-generator/examples/README.md +147 -0
- package/skills/global_config/github-actions-generator/examples/actions/setup-node-cached/action.yml +93 -0
- package/skills/global_config/github-actions-generator/examples/caching/docker-buildkit.yml +256 -0
- package/skills/global_config/github-actions-generator/examples/security/dependency-review.yml +62 -0
- package/skills/global_config/github-actions-generator/examples/security/sbom-attestation.yml +119 -0
- package/skills/global_config/github-actions-generator/examples/triggers/chatops-commands.yml +475 -0
- package/skills/global_config/github-actions-generator/examples/triggers/repository-dispatch.yml +418 -0
- package/skills/global_config/github-actions-generator/examples/triggers/workflow-orchestration.yml +404 -0
- package/skills/global_config/github-actions-generator/examples/workflows/docker-build-push.yml +68 -0
- package/skills/global_config/github-actions-generator/examples/workflows/go-ci.yml +161 -0
- package/skills/global_config/github-actions-generator/examples/workflows/monorepo-ci.yml +340 -0
- package/skills/global_config/github-actions-generator/examples/workflows/multi-environment-deploy.yml +406 -0
- package/skills/global_config/github-actions-generator/examples/workflows/nodejs-ci.yml +122 -0
- package/skills/global_config/github-actions-generator/examples/workflows/python-ci.yml +157 -0
- package/skills/global_config/github-actions-generator/examples/workflows/scheduled-tasks.yml +376 -0
- package/skills/global_config/github-actions-generator/references/advanced-triggers.md +917 -0
- package/skills/global_config/github-actions-generator/references/best-practices.md +755 -0
- package/skills/global_config/github-actions-generator/references/common-actions.md +715 -0
- package/skills/global_config/github-actions-generator/references/custom-actions.md +320 -0
- package/skills/global_config/github-actions-generator/references/expressions-and-contexts.md +688 -0
- package/skills/global_config/github-actions-generator/references/modern-features.md +421 -0
- package/skills/global_config/github-actions-generator/scripts/test_generator.sh +344 -0
- package/skills/global_config/github-actions-templates/SKILL.md +7 -0
- package/skills/global_config/github-actions-validator/SKILL.md +576 -0
- package/skills/global_config/github-actions-validator/examples/README.md +88 -0
- package/skills/global_config/github-actions-validator/examples/outdated-versions.yml +76 -0
- package/skills/global_config/github-actions-validator/examples/valid-ci.yml +79 -0
- package/skills/global_config/github-actions-validator/examples/with-errors.yml +47 -0
- package/skills/global_config/github-actions-validator/references/act_usage.md +233 -0
- package/skills/global_config/github-actions-validator/references/action_versions.md +122 -0
- package/skills/global_config/github-actions-validator/references/actionlint_usage.md +343 -0
- package/skills/global_config/github-actions-validator/references/common_errors.md +512 -0
- package/skills/global_config/github-actions-validator/references/modern_features.md +384 -0
- package/skills/global_config/github-actions-validator/references/runners.md +317 -0
- package/skills/global_config/github-actions-validator/scripts/install_tools.sh +113 -0
- package/skills/global_config/github-actions-validator/scripts/validate_workflow.sh +910 -0
- package/skills/global_config/github-actions-validator/tests/test_validate_workflow.sh +237 -0
- package/skills/global_config/makefile-generator/SKILL.md +614 -0
- package/skills/global_config/makefile-generator/assets/templates/.gitkeep +1 -0
- package/skills/global_config/makefile-generator/docs/makefile-structure.md +530 -0
- package/skills/global_config/makefile-generator/docs/optimization-guide.md +784 -0
- package/skills/global_config/makefile-generator/docs/patterns-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/security-guide.md +361 -0
- package/skills/global_config/makefile-generator/docs/targets-guide.md +642 -0
- package/skills/global_config/makefile-generator/docs/variables-guide.md +596 -0
- package/skills/global_config/makefile-generator/scripts/add_standard_targets.sh +539 -0
- package/skills/global_config/makefile-generator/scripts/generate_makefile_template.sh +690 -0
- package/skills/global_config/makefile-generator/test/test_helper_scripts.sh +190 -0
- package/skills/global_config/makefile-validator/SKILL.md +244 -0
- package/skills/global_config/makefile-validator/docs/bake-tool.md +1000 -0
- package/skills/global_config/makefile-validator/docs/best-practices.md +858 -0
- package/skills/global_config/makefile-validator/docs/common-mistakes.md +944 -0
- package/skills/global_config/makefile-validator/examples/bad-makefile.mk +77 -0
- package/skills/global_config/makefile-validator/examples/good-makefile.mk +103 -0
- package/skills/global_config/makefile-validator/scripts/test_validate.sh +382 -0
- package/skills/global_config/makefile-validator/scripts/validate_makefile.sh +712 -0
- package/skills/global_config/{MCP_Manage → mcp-manage}/SKILL.md +3 -3
- package/skills/global_config/requesting-code-review/SKILL.md +98 -0
- package/skills/global_config/requesting-code-review/code-reviewer.md +198 -0
- package/skills/global_config/using-git-worktrees/SKILL.md +170 -0
- package/skills/global_config/verification-before-completion/SKILL.md +123 -0
- package/skills/global_config/writing-plans/SKILL.md +126 -46
- package/skills/global_config/writing-plans-legacy/SKILL.md +139 -0
|
@@ -0,0 +1,944 @@
|
|
|
1
|
+
# Common Makefile Mistakes
|
|
2
|
+
|
|
3
|
+
A comprehensive guide to common mistakes in Makefiles, their consequences, and how to fix them.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Critical Missing Declarations](#critical-missing-declarations)
|
|
8
|
+
2. [Syntax Errors](#syntax-errors)
|
|
9
|
+
3. [Indentation Issues](#indentation-issues)
|
|
10
|
+
4. [Target and Dependency Problems](#target-and-dependency-problems)
|
|
11
|
+
5. [Variable Issues](#variable-issues)
|
|
12
|
+
6. [Security Vulnerabilities](#security-vulnerabilities)
|
|
13
|
+
7. [Performance Problems](#performance-problems)
|
|
14
|
+
8. [Portability Issues](#portability-issues)
|
|
15
|
+
9. [Build Logic Errors](#build-logic-errors)
|
|
16
|
+
|
|
17
|
+
## Critical Missing Declarations
|
|
18
|
+
|
|
19
|
+
### 0. Missing .DELETE_ON_ERROR
|
|
20
|
+
|
|
21
|
+
**Problem**: Not declaring `.DELETE_ON_ERROR` (most common critical mistake)
|
|
22
|
+
|
|
23
|
+
```makefile
|
|
24
|
+
# WRONG: Missing .DELETE_ON_ERROR
|
|
25
|
+
.PHONY: all clean
|
|
26
|
+
|
|
27
|
+
all: app.bin
|
|
28
|
+
|
|
29
|
+
app.bin: app.c
|
|
30
|
+
$(CC) -o $@ $<
|
|
31
|
+
|
|
32
|
+
# If compilation fails partway through, a partial/corrupt app.bin may exist
|
|
33
|
+
# Next "make" sees the file and thinks target is up-to-date!
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Solution**: Always add `.DELETE_ON_ERROR:` at the top
|
|
37
|
+
|
|
38
|
+
```makefile
|
|
39
|
+
# CORRECT: Always include .DELETE_ON_ERROR
|
|
40
|
+
.DELETE_ON_ERROR:
|
|
41
|
+
|
|
42
|
+
.PHONY: all clean
|
|
43
|
+
|
|
44
|
+
all: app.bin
|
|
45
|
+
|
|
46
|
+
app.bin: app.c
|
|
47
|
+
$(CC) -o $@ $<
|
|
48
|
+
|
|
49
|
+
# Now if build fails, the partial file is deleted
|
|
50
|
+
# Next "make" will properly rebuild
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Impact**:
|
|
54
|
+
- Corrupt/partial files left behind after failed builds
|
|
55
|
+
- Subsequent builds silently use corrupt files
|
|
56
|
+
- Very difficult to debug ("it worked yesterday!")
|
|
57
|
+
|
|
58
|
+
**GNU Make Manual Quote**: *"This is almost always what you want make to do, but it is not historical practice; so for compatibility, you must explicitly request it."*
|
|
59
|
+
|
|
60
|
+
### 0b. Not Clearing .SUFFIXES
|
|
61
|
+
|
|
62
|
+
**Problem**: Built-in suffix rules slow down large projects
|
|
63
|
+
|
|
64
|
+
```makefile
|
|
65
|
+
# Slow: Make checks ~90 built-in suffix rules
|
|
66
|
+
%.o: %.c
|
|
67
|
+
$(CC) -c $< -o $@
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Solution**: Clear .SUFFIXES for faster builds
|
|
71
|
+
|
|
72
|
+
```makefile
|
|
73
|
+
# Fast: Disable built-in suffix rules
|
|
74
|
+
.SUFFIXES:
|
|
75
|
+
|
|
76
|
+
%.o: %.c
|
|
77
|
+
$(CC) -c $< -o $@
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Impact**: Up to 40% faster rule resolution on large projects
|
|
81
|
+
|
|
82
|
+
## Syntax Errors
|
|
83
|
+
|
|
84
|
+
### 1. Spaces Instead of Tabs
|
|
85
|
+
|
|
86
|
+
**Problem**: Using spaces for recipe indentation
|
|
87
|
+
|
|
88
|
+
```makefile
|
|
89
|
+
# WRONG: Spaces (will fail!)
|
|
90
|
+
build:
|
|
91
|
+
echo "Building..." # 4 spaces
|
|
92
|
+
go build -o app # 4 spaces
|
|
93
|
+
|
|
94
|
+
# Error: Makefile:2: *** missing separator. Stop.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Solution**: Use TAB characters
|
|
98
|
+
|
|
99
|
+
```makefile
|
|
100
|
+
# CORRECT: Tab characters
|
|
101
|
+
build:
|
|
102
|
+
echo "Building..." # TAB
|
|
103
|
+
go build -o app # TAB
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Impact**: Build fails immediately with confusing error message
|
|
107
|
+
|
|
108
|
+
**Detection**: mbake automatically detects and fixes this issue
|
|
109
|
+
|
|
110
|
+
### 2. Missing Colon After Target
|
|
111
|
+
|
|
112
|
+
**Problem**: Forgetting colon in target definition
|
|
113
|
+
|
|
114
|
+
```makefile
|
|
115
|
+
# WRONG
|
|
116
|
+
build $(SOURCES)
|
|
117
|
+
$(CC) -o app $^
|
|
118
|
+
|
|
119
|
+
# Error: Makefile:1: *** missing separator. Stop.
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Solution**: Always include colon
|
|
123
|
+
|
|
124
|
+
```makefile
|
|
125
|
+
# CORRECT
|
|
126
|
+
build: $(SOURCES)
|
|
127
|
+
$(CC) -o app $^
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 3. Incorrect Line Continuation
|
|
131
|
+
|
|
132
|
+
**Problem**: Missing backslash or space after backslash
|
|
133
|
+
|
|
134
|
+
```makefile
|
|
135
|
+
# WRONG: Missing backslash
|
|
136
|
+
SOURCES = main.c
|
|
137
|
+
utils.c
|
|
138
|
+
config.c
|
|
139
|
+
|
|
140
|
+
# WRONG: Space after backslash
|
|
141
|
+
SOURCES = main.c \
|
|
142
|
+
utils.c \
|
|
143
|
+
config.c
|
|
144
|
+
|
|
145
|
+
# Error: Unexpected token or incorrect variable value
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Solution**: Proper line continuation
|
|
149
|
+
|
|
150
|
+
```makefile
|
|
151
|
+
# CORRECT
|
|
152
|
+
SOURCES = main.c \
|
|
153
|
+
utils.c \
|
|
154
|
+
config.c
|
|
155
|
+
|
|
156
|
+
# Or use wildcards
|
|
157
|
+
SOURCES := $(wildcard src/*.c)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 4. Mismatched Quotes
|
|
161
|
+
|
|
162
|
+
**Problem**: Unmatched or incorrect quotes
|
|
163
|
+
|
|
164
|
+
```makefile
|
|
165
|
+
# WRONG
|
|
166
|
+
message:
|
|
167
|
+
echo "Building project $(PROJECT)'
|
|
168
|
+
|
|
169
|
+
# Error: Syntax error or unexpected behavior
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Solution**: Match quotes properly
|
|
173
|
+
|
|
174
|
+
```makefile
|
|
175
|
+
# CORRECT
|
|
176
|
+
message:
|
|
177
|
+
echo "Building project $(PROJECT)"
|
|
178
|
+
|
|
179
|
+
# Or use single quotes
|
|
180
|
+
message:
|
|
181
|
+
echo 'Building project $(PROJECT)'
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Indentation Issues
|
|
185
|
+
|
|
186
|
+
### 5. Mixed Tabs and Spaces
|
|
187
|
+
|
|
188
|
+
**Problem**: Mixing tabs and spaces in recipes
|
|
189
|
+
|
|
190
|
+
```makefile
|
|
191
|
+
# WRONG: First line has tab, second has spaces
|
|
192
|
+
build:
|
|
193
|
+
@echo "Starting..."
|
|
194
|
+
go build -o app # Spaces!
|
|
195
|
+
|
|
196
|
+
# Error: Makefile:3: *** missing separator. Stop.
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Solution**: Use tabs consistently
|
|
200
|
+
|
|
201
|
+
```makefile
|
|
202
|
+
# CORRECT: All tabs
|
|
203
|
+
build:
|
|
204
|
+
@echo "Starting..."
|
|
205
|
+
go build -o app
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Editor Configuration**:
|
|
209
|
+
```vim
|
|
210
|
+
" Vim: .vimrc
|
|
211
|
+
autocmd FileType make setlocal noexpandtab
|
|
212
|
+
|
|
213
|
+
# VS Code: settings.json
|
|
214
|
+
"[makefile]": {
|
|
215
|
+
"editor.insertSpaces": false,
|
|
216
|
+
"editor.detectIndentation": false
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### 6. Tab Width Confusion
|
|
221
|
+
|
|
222
|
+
**Problem**: Assuming tab width instead of using actual tabs
|
|
223
|
+
|
|
224
|
+
```makefile
|
|
225
|
+
# WRONG: Looks like tab but is 8 spaces
|
|
226
|
+
build:
|
|
227
|
+
echo "Building..." # 8 spaces, not a tab!
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Solution**: Configure editor to show whitespace and use real tabs
|
|
231
|
+
|
|
232
|
+
```makefile
|
|
233
|
+
# CORRECT: Actual tab character
|
|
234
|
+
build:
|
|
235
|
+
echo "Building..." # TAB (shows as single character)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Target and Dependency Problems
|
|
239
|
+
|
|
240
|
+
### 7. Missing .PHONY Declarations
|
|
241
|
+
|
|
242
|
+
**Problem**: Not declaring non-file targets as phony
|
|
243
|
+
|
|
244
|
+
```makefile
|
|
245
|
+
# WRONG: Missing .PHONY
|
|
246
|
+
clean:
|
|
247
|
+
rm -rf build
|
|
248
|
+
|
|
249
|
+
test:
|
|
250
|
+
go test ./...
|
|
251
|
+
|
|
252
|
+
# If files named 'clean' or 'test' exist, targets won't run!
|
|
253
|
+
# $ touch clean # Create a file named 'clean'
|
|
254
|
+
# $ make clean
|
|
255
|
+
# make: 'clean' is up to date.
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Solution**: Always declare non-file targets
|
|
259
|
+
|
|
260
|
+
```makefile
|
|
261
|
+
# CORRECT: Declare .PHONY targets
|
|
262
|
+
.PHONY: clean test all install
|
|
263
|
+
|
|
264
|
+
clean:
|
|
265
|
+
rm -rf build
|
|
266
|
+
|
|
267
|
+
test:
|
|
268
|
+
go test ./...
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Impact**:
|
|
272
|
+
- 35%+ of developers face issues due to missing .PHONY
|
|
273
|
+
- Targets may not run if files with same names exist
|
|
274
|
+
- Performance degradation (implicit rule search)
|
|
275
|
+
|
|
276
|
+
### 8. Incorrect Dependency Specification
|
|
277
|
+
|
|
278
|
+
**Problem**: Missing or incomplete dependencies
|
|
279
|
+
|
|
280
|
+
```makefile
|
|
281
|
+
# WRONG: Missing header dependencies
|
|
282
|
+
app: main.o utils.o
|
|
283
|
+
$(CC) -o $@ $^
|
|
284
|
+
|
|
285
|
+
%.o: %.c
|
|
286
|
+
$(CC) $(CFLAGS) -c $<
|
|
287
|
+
|
|
288
|
+
# If headers change, .o files won't rebuild!
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Solution**: Include all dependencies
|
|
292
|
+
|
|
293
|
+
```makefile
|
|
294
|
+
# CORRECT: Include header dependencies
|
|
295
|
+
app: main.o utils.o
|
|
296
|
+
$(CC) -o $@ $^
|
|
297
|
+
|
|
298
|
+
main.o: main.c main.h common.h
|
|
299
|
+
$(CC) $(CFLAGS) -c main.c
|
|
300
|
+
|
|
301
|
+
utils.o: utils.c utils.h common.h
|
|
302
|
+
$(CC) $(CFLAGS) -c utils.c
|
|
303
|
+
|
|
304
|
+
# BETTER: Auto-generate dependencies
|
|
305
|
+
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
|
|
306
|
+
%.o: %.c
|
|
307
|
+
$(CC) $(DEPFLAGS) $(CFLAGS) -c $<
|
|
308
|
+
|
|
309
|
+
-include $(DEPS)
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Impact**: Over 60% reduction in unnecessary recompilation with proper dependencies
|
|
313
|
+
|
|
314
|
+
### 9. Circular Dependencies
|
|
315
|
+
|
|
316
|
+
**Problem**: Targets depending on each other
|
|
317
|
+
|
|
318
|
+
```makefile
|
|
319
|
+
# WRONG: Circular dependency
|
|
320
|
+
A: B
|
|
321
|
+
@echo "Target A"
|
|
322
|
+
|
|
323
|
+
B: A
|
|
324
|
+
@echo "Target B"
|
|
325
|
+
|
|
326
|
+
# Error: Makefile:1: *** Circular A <- B dependency dropped.
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Solution**: Break the cycle
|
|
330
|
+
|
|
331
|
+
```makefile
|
|
332
|
+
# CORRECT: Proper dependency chain
|
|
333
|
+
A: B
|
|
334
|
+
@echo "Target A depends on B"
|
|
335
|
+
|
|
336
|
+
B: C
|
|
337
|
+
@echo "Target B depends on C"
|
|
338
|
+
|
|
339
|
+
C:
|
|
340
|
+
@echo "Target C has no dependencies"
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### 10. Phony Target as Prerequisite of Real Target
|
|
344
|
+
|
|
345
|
+
**Problem**: Using phony target as dependency of file target
|
|
346
|
+
|
|
347
|
+
```makefile
|
|
348
|
+
# WRONG: Phony prerequisite causes always-rebuild
|
|
349
|
+
.PHONY: generate
|
|
350
|
+
|
|
351
|
+
app.o: app.c generate
|
|
352
|
+
$(CC) -c app.c -o app.o
|
|
353
|
+
|
|
354
|
+
generate:
|
|
355
|
+
./gen-config.sh
|
|
356
|
+
|
|
357
|
+
# app.o rebuilds EVERY time because 'generate' is always out of date
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**Solution**: Use real file dependencies
|
|
361
|
+
|
|
362
|
+
```makefile
|
|
363
|
+
# CORRECT: Depend on actual generated file
|
|
364
|
+
app.o: app.c config.h
|
|
365
|
+
$(CC) -c app.c -o app.o
|
|
366
|
+
|
|
367
|
+
config.h:
|
|
368
|
+
./gen-config.sh
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Variable Issues
|
|
372
|
+
|
|
373
|
+
### 11. Using = Instead of :=
|
|
374
|
+
|
|
375
|
+
**Problem**: Recursive expansion causing performance issues
|
|
376
|
+
|
|
377
|
+
```makefile
|
|
378
|
+
# WRONG: Recursive expansion (re-evaluated every time)
|
|
379
|
+
BUILD_TIME = $(shell date +%Y%m%d-%H%M%S)
|
|
380
|
+
GIT_HASH = $(shell git rev-parse HEAD)
|
|
381
|
+
|
|
382
|
+
target1:
|
|
383
|
+
echo $(BUILD_TIME) # Shell called here
|
|
384
|
+
|
|
385
|
+
target2:
|
|
386
|
+
echo $(BUILD_TIME) # Shell called AGAIN with different time!
|
|
387
|
+
echo $(GIT_HASH) # Shell called here
|
|
388
|
+
|
|
389
|
+
target3:
|
|
390
|
+
echo $(GIT_HASH) # Shell called AGAIN!
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Solution**: Use := for immediate expansion
|
|
394
|
+
|
|
395
|
+
```makefile
|
|
396
|
+
# CORRECT: Immediate expansion (evaluated once)
|
|
397
|
+
BUILD_TIME := $(shell date +%Y%m%d-%H%M%S)
|
|
398
|
+
GIT_HASH := $(shell git rev-parse HEAD)
|
|
399
|
+
|
|
400
|
+
target1:
|
|
401
|
+
echo $(BUILD_TIME) # Uses cached value
|
|
402
|
+
|
|
403
|
+
target2:
|
|
404
|
+
echo $(BUILD_TIME) # Same cached value
|
|
405
|
+
echo $(GIT_HASH) # Cached value
|
|
406
|
+
|
|
407
|
+
target3:
|
|
408
|
+
echo $(GIT_HASH) # Same cached value
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**Impact**: Can cause significant slowdown and inconsistent builds
|
|
412
|
+
|
|
413
|
+
### 12. Undefined Variables
|
|
414
|
+
|
|
415
|
+
**Problem**: Using variables without defaults
|
|
416
|
+
|
|
417
|
+
```makefile
|
|
418
|
+
# WRONG: No default value
|
|
419
|
+
install:
|
|
420
|
+
cp app $(PREFIX)/bin/
|
|
421
|
+
|
|
422
|
+
# If PREFIX is not set, installs to /bin/ (wrong!) or fails
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**Solution**: Always provide defaults
|
|
426
|
+
|
|
427
|
+
```makefile
|
|
428
|
+
# CORRECT: Provide sensible defaults
|
|
429
|
+
PREFIX ?= /usr/local
|
|
430
|
+
BINDIR ?= $(PREFIX)/bin
|
|
431
|
+
|
|
432
|
+
install:
|
|
433
|
+
mkdir -p $(DESTDIR)$(BINDIR)
|
|
434
|
+
cp app $(DESTDIR)$(BINDIR)/
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 13. Incorrect Variable Expansion
|
|
438
|
+
|
|
439
|
+
**Problem**: Using wrong expansion syntax
|
|
440
|
+
|
|
441
|
+
```makefile
|
|
442
|
+
# WRONG: Shell variable vs Make variable confusion
|
|
443
|
+
build:
|
|
444
|
+
for file in *.c; do \
|
|
445
|
+
echo "Compiling $file"; \
|
|
446
|
+
$(CC) -c $file; \
|
|
447
|
+
done
|
|
448
|
+
|
|
449
|
+
# $file expands as Make variable (empty!), not shell variable
|
|
450
|
+
# Output: Compiling (nothing)
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**Solution**: Escape shell variables
|
|
454
|
+
|
|
455
|
+
```makefile
|
|
456
|
+
# CORRECT: Escape $ for shell variables
|
|
457
|
+
build:
|
|
458
|
+
for file in *.c; do \
|
|
459
|
+
echo "Compiling $$file"; \
|
|
460
|
+
$(CC) -c $$file; \
|
|
461
|
+
done
|
|
462
|
+
|
|
463
|
+
# Output: Compiling main.c, Compiling utils.c, etc.
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### 14. Variable Naming Conflicts
|
|
467
|
+
|
|
468
|
+
**Problem**: Overriding special Make variables
|
|
469
|
+
|
|
470
|
+
```makefile
|
|
471
|
+
# WRONG: Overriding built-in variable
|
|
472
|
+
MAKEFLAGS = -j4 # This overrides Make's internal flags!
|
|
473
|
+
|
|
474
|
+
# AVOID: Using reserved names
|
|
475
|
+
MAKE = my-build-tool # Breaks recursive make
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
**Solution**: Use unique names
|
|
479
|
+
|
|
480
|
+
```makefile
|
|
481
|
+
# CORRECT: Use custom names for your variables
|
|
482
|
+
BUILD_FLAGS := -j4
|
|
483
|
+
MY_BUILD_TOOL := custom-builder
|
|
484
|
+
|
|
485
|
+
build:
|
|
486
|
+
$(MAKE) -f sub.mk $(BUILD_FLAGS)
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Security Vulnerabilities
|
|
490
|
+
|
|
491
|
+
### 15. Hardcoded Credentials
|
|
492
|
+
|
|
493
|
+
**Problem**: Secrets in Makefile
|
|
494
|
+
|
|
495
|
+
```makefile
|
|
496
|
+
# WRONG: Hardcoded secrets
|
|
497
|
+
API_KEY = sk-1234567890abcdef
|
|
498
|
+
DB_PASSWORD = super_secret_123
|
|
499
|
+
|
|
500
|
+
deploy:
|
|
501
|
+
curl -H "Authorization: Bearer $(API_KEY)" https://api.example.com/
|
|
502
|
+
psql -U admin -p $(DB_PASSWORD) -c "SELECT version();"
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
**Solution**: Use environment variables
|
|
506
|
+
|
|
507
|
+
```makefile
|
|
508
|
+
# CORRECT: Load from environment
|
|
509
|
+
deploy:
|
|
510
|
+
@if [ -z "$$API_KEY" ]; then \
|
|
511
|
+
echo "Error: API_KEY not set"; \
|
|
512
|
+
exit 1; \
|
|
513
|
+
fi
|
|
514
|
+
curl -H "Authorization: Bearer $$API_KEY" https://api.example.com/
|
|
515
|
+
|
|
516
|
+
# Or use a .env file (not committed)
|
|
517
|
+
include .env
|
|
518
|
+
export
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Impact**: Credentials exposed in version control, logs, and process listings
|
|
522
|
+
|
|
523
|
+
### 16. Unsafe Variable Expansion
|
|
524
|
+
|
|
525
|
+
**Problem**: Unvalidated variables in dangerous commands
|
|
526
|
+
|
|
527
|
+
```makefile
|
|
528
|
+
# WRONG: Unsafe rm command
|
|
529
|
+
BUILD_DIR = $(USER_INPUT)
|
|
530
|
+
|
|
531
|
+
clean:
|
|
532
|
+
rm -rf $(BUILD_DIR)/*
|
|
533
|
+
|
|
534
|
+
# If BUILD_DIR is empty or "/", this is catastrophic!
|
|
535
|
+
# $ make clean BUILD_DIR=/
|
|
536
|
+
# rm -rf /* # Disaster!
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
**Solution**: Validate before dangerous operations
|
|
540
|
+
|
|
541
|
+
```makefile
|
|
542
|
+
# CORRECT: Validate variables
|
|
543
|
+
BUILD_DIR := build # Default value
|
|
544
|
+
|
|
545
|
+
clean:
|
|
546
|
+
@if [ -z "$(BUILD_DIR)" ] || [ "$(BUILD_DIR)" = "/" ]; then \
|
|
547
|
+
echo "Error: Invalid BUILD_DIR=$(BUILD_DIR)"; \
|
|
548
|
+
exit 1; \
|
|
549
|
+
fi
|
|
550
|
+
@if [ -d "$(BUILD_DIR)" ]; then \
|
|
551
|
+
rm -rf $(BUILD_DIR)/*; \
|
|
552
|
+
fi
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### 17. Command Injection
|
|
556
|
+
|
|
557
|
+
**Problem**: Unsanitized input in shell commands
|
|
558
|
+
|
|
559
|
+
```makefile
|
|
560
|
+
# WRONG: User input directly in command
|
|
561
|
+
deploy:
|
|
562
|
+
ssh user@$(SERVER) "cd /app && git pull origin $(BRANCH)"
|
|
563
|
+
|
|
564
|
+
# Malicious input: BRANCH="; rm -rf /"
|
|
565
|
+
# Executes: git pull origin ; rm -rf /
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
**Solution**: Validate and quote input
|
|
569
|
+
|
|
570
|
+
```makefile
|
|
571
|
+
# CORRECT: Validate input
|
|
572
|
+
ALLOWED_BRANCHES := main develop staging
|
|
573
|
+
BRANCH ?= main
|
|
574
|
+
|
|
575
|
+
deploy:
|
|
576
|
+
@if ! echo "$(ALLOWED_BRANCHES)" | grep -wq "$(BRANCH)"; then \
|
|
577
|
+
echo "Error: Invalid branch $(BRANCH)"; \
|
|
578
|
+
exit 1; \
|
|
579
|
+
fi
|
|
580
|
+
ssh user@$(SERVER) "cd /app && git pull origin '$(BRANCH)'"
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### 18. Logging Sensitive Information
|
|
584
|
+
|
|
585
|
+
**Problem**: Echoing secrets in build output
|
|
586
|
+
|
|
587
|
+
```makefile
|
|
588
|
+
# WRONG: Secrets visible in logs
|
|
589
|
+
deploy:
|
|
590
|
+
echo "Deploying with token: $(API_TOKEN)"
|
|
591
|
+
curl -H "Authorization: Bearer $(API_TOKEN)" https://api.example.com/
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
**Solution**: Suppress sensitive output
|
|
595
|
+
|
|
596
|
+
```makefile
|
|
597
|
+
# CORRECT: Hide sensitive information
|
|
598
|
+
deploy:
|
|
599
|
+
@echo "Deploying to production..."
|
|
600
|
+
@curl -s -H "Authorization: Bearer $$API_TOKEN" https://api.example.com/
|
|
601
|
+
@echo "Deployment complete"
|
|
602
|
+
|
|
603
|
+
# Or mask partial value
|
|
604
|
+
@echo "Using token: $${API_TOKEN:0:8}..."
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
## Performance Problems
|
|
608
|
+
|
|
609
|
+
### 19. Inefficient Wildcards
|
|
610
|
+
|
|
611
|
+
**Problem**: Repeated wildcard evaluation
|
|
612
|
+
|
|
613
|
+
```makefile
|
|
614
|
+
# WRONG: wildcard called every time
|
|
615
|
+
build:
|
|
616
|
+
$(CC) -o app $(wildcard src/*.c)
|
|
617
|
+
|
|
618
|
+
test:
|
|
619
|
+
for file in $(wildcard tests/*.sh); do bash $$file; done
|
|
620
|
+
|
|
621
|
+
# wildcard searches filesystem every time these targets run
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
**Solution**: Evaluate once with :=
|
|
625
|
+
|
|
626
|
+
```makefile
|
|
627
|
+
# CORRECT: Evaluate wildcard once
|
|
628
|
+
SOURCES := $(wildcard src/*.c)
|
|
629
|
+
TESTS := $(wildcard tests/*.sh)
|
|
630
|
+
|
|
631
|
+
build:
|
|
632
|
+
$(CC) -o app $(SOURCES)
|
|
633
|
+
|
|
634
|
+
test:
|
|
635
|
+
for file in $(TESTS); do bash $$file; done
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
**Impact**: Significant speedup for large projects (40%+ in some cases)
|
|
639
|
+
|
|
640
|
+
### 20. Missing Incremental Build Support
|
|
641
|
+
|
|
642
|
+
**Problem**: Always rebuilding everything
|
|
643
|
+
|
|
644
|
+
```makefile
|
|
645
|
+
# WRONG: No incremental build
|
|
646
|
+
build:
|
|
647
|
+
rm -rf build
|
|
648
|
+
mkdir -p build
|
|
649
|
+
$(CC) -o build/app $(SOURCES)
|
|
650
|
+
|
|
651
|
+
# Rebuilds from scratch every time!
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
**Solution**: Proper dependency tracking
|
|
655
|
+
|
|
656
|
+
```makefile
|
|
657
|
+
# CORRECT: Incremental build
|
|
658
|
+
OBJECTS := $(patsubst src/%.c,build/%.o,$(SOURCES))
|
|
659
|
+
|
|
660
|
+
build: build/app
|
|
661
|
+
|
|
662
|
+
build/app: $(OBJECTS)
|
|
663
|
+
$(CC) -o $@ $^
|
|
664
|
+
|
|
665
|
+
build/%.o: src/%.c
|
|
666
|
+
@mkdir -p $(dir $@)
|
|
667
|
+
$(CC) $(CFLAGS) -c $< -o $@
|
|
668
|
+
|
|
669
|
+
# Only rebuilds changed files
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
**Impact**: Can reduce build times by up to 60% with proper dependencies
|
|
673
|
+
|
|
674
|
+
### 21. Not Using Pattern Rules
|
|
675
|
+
|
|
676
|
+
**Problem**: Duplicated rules for similar targets
|
|
677
|
+
|
|
678
|
+
```makefile
|
|
679
|
+
# WRONG: Repetitive rules
|
|
680
|
+
main.o: main.c
|
|
681
|
+
$(CC) $(CFLAGS) -c main.c -o main.o
|
|
682
|
+
|
|
683
|
+
utils.o: utils.c
|
|
684
|
+
$(CC) $(CFLAGS) -c utils.c -o utils.o
|
|
685
|
+
|
|
686
|
+
config.o: config.c
|
|
687
|
+
$(CC) $(CFLAGS) -c config.c -o config.o
|
|
688
|
+
|
|
689
|
+
# Lots of duplication!
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
**Solution**: Use pattern rules
|
|
693
|
+
|
|
694
|
+
```makefile
|
|
695
|
+
# CORRECT: Single pattern rule
|
|
696
|
+
%.o: %.c
|
|
697
|
+
$(CC) $(CFLAGS) -c $< -o $@
|
|
698
|
+
|
|
699
|
+
# Or with directories
|
|
700
|
+
build/%.o: src/%.c
|
|
701
|
+
@mkdir -p $(dir $@)
|
|
702
|
+
$(CC) $(CFLAGS) -c $< -o $@
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
## Portability Issues
|
|
706
|
+
|
|
707
|
+
### 22. Assuming GNU Make
|
|
708
|
+
|
|
709
|
+
**Problem**: Using GNU Make-specific features
|
|
710
|
+
|
|
711
|
+
```makefile
|
|
712
|
+
# WRONG: GNU Make specific
|
|
713
|
+
SOURCES := $(shell find src -name '*.c')
|
|
714
|
+
|
|
715
|
+
build: $(SOURCES:.c=.o)
|
|
716
|
+
$(CC) -o app $^
|
|
717
|
+
|
|
718
|
+
# Fails with BSD make or other Make implementations
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
**Solution**: Use portable constructs
|
|
722
|
+
|
|
723
|
+
```makefile
|
|
724
|
+
# CORRECT: More portable (though still uses shell)
|
|
725
|
+
SOURCES != find src -name '*.c' || find src -name '*.c'
|
|
726
|
+
|
|
727
|
+
# Or manually list sources for maximum portability
|
|
728
|
+
SOURCES = src/main.c src/utils.c src/config.c
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
### 23. Hard-Coded Tools
|
|
732
|
+
|
|
733
|
+
**Problem**: Assuming specific tool paths
|
|
734
|
+
|
|
735
|
+
```makefile
|
|
736
|
+
# WRONG: Hard-coded tool paths
|
|
737
|
+
CC = /usr/bin/gcc
|
|
738
|
+
PYTHON = /usr/bin/python3
|
|
739
|
+
|
|
740
|
+
build:
|
|
741
|
+
$(CC) -o app $(SOURCES)
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
**Solution**: Use which or allow override
|
|
745
|
+
|
|
746
|
+
```makefile
|
|
747
|
+
# CORRECT: Allow override with defaults
|
|
748
|
+
CC ?= gcc
|
|
749
|
+
PYTHON ?= python3
|
|
750
|
+
INSTALL ?= install
|
|
751
|
+
|
|
752
|
+
# Or detect at runtime
|
|
753
|
+
CC := $(shell command -v gcc || command -v clang)
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
### 24. Platform-Specific Commands
|
|
757
|
+
|
|
758
|
+
**Problem**: Using OS-specific commands
|
|
759
|
+
|
|
760
|
+
```makefile
|
|
761
|
+
# WRONG: Linux-specific
|
|
762
|
+
clean:
|
|
763
|
+
rm -rf build
|
|
764
|
+
|
|
765
|
+
copy:
|
|
766
|
+
cp -r src/* dest/
|
|
767
|
+
|
|
768
|
+
# Fails on Windows
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
**Solution**: Detect platform or use portable commands
|
|
772
|
+
|
|
773
|
+
```makefile
|
|
774
|
+
# CORRECT: Platform detection
|
|
775
|
+
UNAME_S := $(shell uname -s 2>/dev/null || echo Windows)
|
|
776
|
+
|
|
777
|
+
ifeq ($(UNAME_S),Windows)
|
|
778
|
+
RM := del /Q /S
|
|
779
|
+
MKDIR := mkdir
|
|
780
|
+
else
|
|
781
|
+
RM := rm -rf
|
|
782
|
+
MKDIR := mkdir -p
|
|
783
|
+
endif
|
|
784
|
+
|
|
785
|
+
clean:
|
|
786
|
+
$(RM) build
|
|
787
|
+
|
|
788
|
+
# Or use Go/Python for cross-platform scripts
|
|
789
|
+
clean:
|
|
790
|
+
@go run scripts/clean.go
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
## Build Logic Errors
|
|
794
|
+
|
|
795
|
+
### 25. Silent Failures
|
|
796
|
+
|
|
797
|
+
**Problem**: Not checking command exit codes
|
|
798
|
+
|
|
799
|
+
```makefile
|
|
800
|
+
# WRONG: Ignoring failures
|
|
801
|
+
test:
|
|
802
|
+
go test ./pkg1
|
|
803
|
+
go test ./pkg2
|
|
804
|
+
go test ./pkg3
|
|
805
|
+
@echo "All tests passed!"
|
|
806
|
+
|
|
807
|
+
# If pkg1 fails, Make continues to pkg2, pkg3, and prints "passed"
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
**Solution**: Use set -e or check exit codes
|
|
811
|
+
|
|
812
|
+
```makefile
|
|
813
|
+
# CORRECT: Stop on first failure
|
|
814
|
+
test:
|
|
815
|
+
@set -e; \
|
|
816
|
+
go test ./pkg1; \
|
|
817
|
+
go test ./pkg2; \
|
|
818
|
+
go test ./pkg3; \
|
|
819
|
+
echo "All tests passed!"
|
|
820
|
+
|
|
821
|
+
# Or check explicitly
|
|
822
|
+
test:
|
|
823
|
+
@go test ./pkg1 || exit 1
|
|
824
|
+
@go test ./pkg2 || exit 1
|
|
825
|
+
@go test ./pkg3 || exit 1
|
|
826
|
+
@echo "All tests passed!"
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
### 26. Race Conditions in Parallel Builds
|
|
830
|
+
|
|
831
|
+
**Problem**: Unsafe parallel execution
|
|
832
|
+
|
|
833
|
+
```makefile
|
|
834
|
+
# WRONG: Race condition with parallel builds
|
|
835
|
+
all: build-frontend build-backend
|
|
836
|
+
|
|
837
|
+
build-frontend:
|
|
838
|
+
npm install # Both may write to node_modules!
|
|
839
|
+
npm run build
|
|
840
|
+
|
|
841
|
+
build-backend:
|
|
842
|
+
npm install # Race condition!
|
|
843
|
+
go build
|
|
844
|
+
|
|
845
|
+
# With make -j2, both run npm install simultaneously
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
**Solution**: Use order dependencies or .NOTPARALLEL
|
|
849
|
+
|
|
850
|
+
```makefile
|
|
851
|
+
# CORRECT: Sequential dependencies
|
|
852
|
+
all: build-frontend build-backend
|
|
853
|
+
|
|
854
|
+
build-frontend: node_modules
|
|
855
|
+
npm run build
|
|
856
|
+
|
|
857
|
+
build-backend: node_modules
|
|
858
|
+
go build
|
|
859
|
+
|
|
860
|
+
node_modules: package.json
|
|
861
|
+
npm install
|
|
862
|
+
@touch node_modules # Update timestamp
|
|
863
|
+
|
|
864
|
+
# Or use .NOTPARALLEL for specific target
|
|
865
|
+
.NOTPARALLEL: install
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
### 27. Assuming Build Order
|
|
869
|
+
|
|
870
|
+
**Problem**: Relying on target order without dependencies
|
|
871
|
+
|
|
872
|
+
```makefile
|
|
873
|
+
# WRONG: Assuming build is run before test
|
|
874
|
+
all: build test deploy
|
|
875
|
+
|
|
876
|
+
build:
|
|
877
|
+
go build -o app
|
|
878
|
+
|
|
879
|
+
test:
|
|
880
|
+
./scripts/test.sh # Assumes app exists!
|
|
881
|
+
|
|
882
|
+
deploy:
|
|
883
|
+
./scripts/deploy.sh # Assumes tests passed!
|
|
884
|
+
|
|
885
|
+
# Direct "make test" or "make deploy" fails!
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
**Solution**: Explicit dependencies
|
|
889
|
+
|
|
890
|
+
```makefile
|
|
891
|
+
# CORRECT: Explicit dependencies
|
|
892
|
+
all: deploy
|
|
893
|
+
|
|
894
|
+
build:
|
|
895
|
+
go build -o app
|
|
896
|
+
|
|
897
|
+
test: build
|
|
898
|
+
./scripts/test.sh
|
|
899
|
+
|
|
900
|
+
deploy: test
|
|
901
|
+
./scripts/deploy.sh
|
|
902
|
+
|
|
903
|
+
# Now "make deploy" automatically runs build → test → deploy
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
## Quick Fix Checklist
|
|
907
|
+
|
|
908
|
+
When you encounter Makefile issues, check:
|
|
909
|
+
|
|
910
|
+
- [ ] **Is .DELETE_ON_ERROR: declared at top?** (Critical!)
|
|
911
|
+
- [ ] Are you using TAB characters (not spaces) for recipes?
|
|
912
|
+
- [ ] Are all non-file targets declared as .PHONY?
|
|
913
|
+
- [ ] Is .SUFFIXES: declared to disable built-in rules?
|
|
914
|
+
- [ ] Are dependencies complete and correct?
|
|
915
|
+
- [ ] Are variables using := instead of = for expensive operations?
|
|
916
|
+
- [ ] Are shell variables escaped with $$?
|
|
917
|
+
- [ ] Are dangerous operations (rm, sudo) validated?
|
|
918
|
+
- [ ] Are secrets loaded from environment, not hardcoded?
|
|
919
|
+
- [ ] Are wildcard results cached with :=?
|
|
920
|
+
- [ ] Is error handling present in critical recipes?
|
|
921
|
+
- [ ] Are tools and paths configurable (CC ?= gcc)?
|
|
922
|
+
- [ ] Is parallel build safety considered?
|
|
923
|
+
- [ ] Are pattern rules used instead of duplicate rules?
|
|
924
|
+
|
|
925
|
+
## Impact Statistics
|
|
926
|
+
|
|
927
|
+
According to research from build system studies (2024-2025):
|
|
928
|
+
|
|
929
|
+
- **35%** of developers face issues with outdated targets due to improper dependencies
|
|
930
|
+
- **40%** experience inaccurate profiling due to incorrect compiler flag usage
|
|
931
|
+
- **60%** reduction in unnecessary recompilation possible with proper dependency tracking
|
|
932
|
+
- **40%** faster incremental builds achievable with optimized Makefile patterns
|
|
933
|
+
|
|
934
|
+
## Additional Resources
|
|
935
|
+
|
|
936
|
+
- [GNU Make Manual - Common Mistakes](https://www.gnu.org/software/make/manual/)
|
|
937
|
+
- [Makefile Tutorial - Pitfalls](https://makefiletutorial.com/)
|
|
938
|
+
- [mbake - Automatic Formatting](https://github.com/EbodShojaei/bake)
|
|
939
|
+
|
|
940
|
+
## Sources
|
|
941
|
+
|
|
942
|
+
- [Common Mistakes in Makefile Incremental Builds](https://moldstud.com/articles/p-common-mistakes-in-makefile-incremental-builds-and-how-to-fix-them)
|
|
943
|
+
- [Makefile Madness: Common Pitfalls](https://moldstud.com/articles/p-makefile-madness-common-pitfalls-and-how-to-avoid-them)
|
|
944
|
+
- [Makefile Best Practices](https://danyspin97.org/blog/makefiles-best-practices/)
|