@hybridlabor-api/aos 4.7.2 → 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 +309 -101
- 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,784 @@
|
|
|
1
|
+
# Makefile Optimization Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide covers techniques for optimizing Makefile performance, including parallel builds, dependency tracking, incremental builds, caching strategies, and performance profiling.
|
|
6
|
+
|
|
7
|
+
## Parallel Builds
|
|
8
|
+
|
|
9
|
+
### Enabling Parallel Execution
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Run with 4 parallel jobs
|
|
13
|
+
make -j4
|
|
14
|
+
|
|
15
|
+
# Use all CPU cores
|
|
16
|
+
make -j$(nproc)
|
|
17
|
+
|
|
18
|
+
# Unlimited parallel jobs (careful!)
|
|
19
|
+
make -j
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Making Makefiles Parallel-Safe
|
|
23
|
+
|
|
24
|
+
**Problem: Shared resources**
|
|
25
|
+
|
|
26
|
+
```makefile
|
|
27
|
+
# WRONG: Multiple rules write to same file
|
|
28
|
+
target1:
|
|
29
|
+
echo "data1" >> shared.log
|
|
30
|
+
|
|
31
|
+
target2:
|
|
32
|
+
echo "data2" >> shared.log
|
|
33
|
+
|
|
34
|
+
# With -j2, file corruption likely!
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Solution: Proper dependencies**
|
|
38
|
+
|
|
39
|
+
```makefile
|
|
40
|
+
# RIGHT: Serialize access with dependencies
|
|
41
|
+
target2: target1
|
|
42
|
+
|
|
43
|
+
# Or use separate files
|
|
44
|
+
target1:
|
|
45
|
+
echo "data1" > target1.log
|
|
46
|
+
|
|
47
|
+
target2:
|
|
48
|
+
echo "data2" > target2.log
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Controlling Parallelism
|
|
52
|
+
|
|
53
|
+
```makefile
|
|
54
|
+
# Disable parallel builds for this Makefile
|
|
55
|
+
.NOTPARALLEL:
|
|
56
|
+
|
|
57
|
+
# Disable parallelism for specific targets
|
|
58
|
+
.NOTPARALLEL: install clean
|
|
59
|
+
|
|
60
|
+
# Serialize specific targets
|
|
61
|
+
install: build
|
|
62
|
+
# Install runs after build completes
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### GNU Make 4.4+ Parallel Control Features
|
|
66
|
+
|
|
67
|
+
GNU Make 4.4 (released October 2022) introduced new features for fine-grained parallel control. These are becoming part of the upcoming POSIX standard.
|
|
68
|
+
|
|
69
|
+
#### .WAIT Special Target
|
|
70
|
+
|
|
71
|
+
The `.WAIT` target provides explicit ordering without creating artificial dependencies:
|
|
72
|
+
|
|
73
|
+
```makefile
|
|
74
|
+
# .WAIT ensures prerequisites to its left complete
|
|
75
|
+
# before starting prerequisites to its right
|
|
76
|
+
all: compile .WAIT link .WAIT package
|
|
77
|
+
|
|
78
|
+
# Equivalent behavior without .WAIT would require:
|
|
79
|
+
# link: compile
|
|
80
|
+
# package: link
|
|
81
|
+
# But .WAIT is cleaner when targets are independent conceptually
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Use Cases for .WAIT:**
|
|
85
|
+
|
|
86
|
+
```makefile
|
|
87
|
+
# Build phases with explicit ordering
|
|
88
|
+
build: setup .WAIT compile .WAIT test .WAIT package
|
|
89
|
+
@echo "Build complete"
|
|
90
|
+
|
|
91
|
+
# Parallel within phases, serial between phases
|
|
92
|
+
ci: lint fmt .WAIT test.unit test.integration .WAIT build
|
|
93
|
+
# lint and fmt run in parallel
|
|
94
|
+
# then unit and integration tests run in parallel
|
|
95
|
+
# finally build runs
|
|
96
|
+
|
|
97
|
+
# Database migrations before tests
|
|
98
|
+
test: migrate .WAIT run-tests
|
|
99
|
+
@echo "Tests complete"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Important Notes:**
|
|
103
|
+
- `.WAIT` only affects parallel builds (`make -j`)
|
|
104
|
+
- With sequential execution, `.WAIT` has no effect
|
|
105
|
+
- `.WAIT` doesn't create actual dependencies, just ordering
|
|
106
|
+
- Available in GNU Make 4.4+ (check with `make --version`)
|
|
107
|
+
|
|
108
|
+
#### .NOTPARALLEL with Prerequisites (Enhanced)
|
|
109
|
+
|
|
110
|
+
In Make 4.4+, `.NOTPARALLEL` can take specific targets as prerequisites:
|
|
111
|
+
|
|
112
|
+
```makefile
|
|
113
|
+
# Traditional: Disable ALL parallel execution
|
|
114
|
+
.NOTPARALLEL:
|
|
115
|
+
|
|
116
|
+
# NEW in 4.4: Serialize only specific targets
|
|
117
|
+
.NOTPARALLEL: install deploy cleanup
|
|
118
|
+
|
|
119
|
+
# This implicitly adds .WAIT between each prerequisite
|
|
120
|
+
# of the listed targets
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**When to Use .NOTPARALLEL with Prerequisites:**
|
|
124
|
+
|
|
125
|
+
```makefile
|
|
126
|
+
# Deployment must be serial (avoid race conditions)
|
|
127
|
+
.NOTPARALLEL: deploy
|
|
128
|
+
|
|
129
|
+
deploy: deploy-database deploy-backend deploy-frontend
|
|
130
|
+
@echo "Deployment complete"
|
|
131
|
+
# deploy-database -> deploy-backend -> deploy-frontend (serial)
|
|
132
|
+
|
|
133
|
+
# But compilation can still be parallel
|
|
134
|
+
build: $(OBJECTS)
|
|
135
|
+
$(CC) $^ -o $(TARGET)
|
|
136
|
+
# Object files compile in parallel (unaffected by .NOTPARALLEL: deploy)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### Version Checking for Make 4.4+ Features
|
|
140
|
+
|
|
141
|
+
Check Make version before using 4.4+ features:
|
|
142
|
+
|
|
143
|
+
```makefile
|
|
144
|
+
# Check Make version (4.4 = 4.4, need >= 4.4)
|
|
145
|
+
MAKE_VERSION_MAJOR := $(word 1,$(subst ., ,$(MAKE_VERSION)))
|
|
146
|
+
MAKE_VERSION_MINOR := $(word 2,$(subst ., ,$(MAKE_VERSION)))
|
|
147
|
+
|
|
148
|
+
# Simple version check
|
|
149
|
+
ifeq ($(shell expr $(MAKE_VERSION_MAJOR) \>= 4),1)
|
|
150
|
+
ifeq ($(shell expr $(MAKE_VERSION_MINOR) \>= 4),1)
|
|
151
|
+
HAVE_WAIT := 1
|
|
152
|
+
endif
|
|
153
|
+
endif
|
|
154
|
+
|
|
155
|
+
# Alternative: Graceful degradation
|
|
156
|
+
ifdef HAVE_WAIT
|
|
157
|
+
# Use .WAIT for modern Make
|
|
158
|
+
all: compile .WAIT link
|
|
159
|
+
else
|
|
160
|
+
# Fall back to dependencies for older Make
|
|
161
|
+
link: compile
|
|
162
|
+
all: link
|
|
163
|
+
endif
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Practical Version Check Pattern:**
|
|
167
|
+
|
|
168
|
+
```makefile
|
|
169
|
+
# At the top of your Makefile
|
|
170
|
+
MIN_MAKE_VERSION := 4.4
|
|
171
|
+
CURRENT_MAKE_VERSION := $(MAKE_VERSION)
|
|
172
|
+
|
|
173
|
+
# Check and warn if using older Make
|
|
174
|
+
ifeq ($(shell printf '%s\n' "$(MIN_MAKE_VERSION)" "$(CURRENT_MAKE_VERSION)" | sort -V | head -n1),$(MIN_MAKE_VERSION))
|
|
175
|
+
# Make version is sufficient
|
|
176
|
+
else
|
|
177
|
+
$(warning GNU Make $(MIN_MAKE_VERSION)+ recommended. You have $(CURRENT_MAKE_VERSION))
|
|
178
|
+
$(warning Some parallel control features may not work)
|
|
179
|
+
endif
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### Comparison: .WAIT vs Dependencies vs .NOTPARALLEL
|
|
183
|
+
|
|
184
|
+
| Feature | Use Case | Make Version |
|
|
185
|
+
|---------|----------|--------------|
|
|
186
|
+
| Dependencies (`b: a`) | Actual dependency relationship | All |
|
|
187
|
+
| `.WAIT` | Ordering without dependency | 4.4+ |
|
|
188
|
+
| `.NOTPARALLEL:` (global) | Disable all parallel | All |
|
|
189
|
+
| `.NOTPARALLEL: target` | Serialize specific target's prereqs | 4.4+ |
|
|
190
|
+
|
|
191
|
+
**Example Comparison:**
|
|
192
|
+
|
|
193
|
+
```makefile
|
|
194
|
+
# Using dependencies (works in all Make versions)
|
|
195
|
+
# Problem: Creates false dependency relationship
|
|
196
|
+
link: compile
|
|
197
|
+
package: link
|
|
198
|
+
all: package
|
|
199
|
+
|
|
200
|
+
# Using .WAIT (Make 4.4+)
|
|
201
|
+
# Cleaner: Explicit ordering, no false dependencies
|
|
202
|
+
all: compile .WAIT link .WAIT package
|
|
203
|
+
|
|
204
|
+
# Using .NOTPARALLEL with targets (Make 4.4+)
|
|
205
|
+
# Best for: Targets that must never run in parallel
|
|
206
|
+
.NOTPARALLEL: deploy
|
|
207
|
+
deploy: step1 step2 step3
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Optimal Parallel Structure
|
|
211
|
+
|
|
212
|
+
```makefile
|
|
213
|
+
# Good parallel structure
|
|
214
|
+
SOURCES := src1.c src2.c src3.c src4.c
|
|
215
|
+
OBJECTS := $(SOURCES:.c=.o)
|
|
216
|
+
|
|
217
|
+
# All .o files can build in parallel
|
|
218
|
+
program: $(OBJECTS)
|
|
219
|
+
$(CC) $^ -o $@
|
|
220
|
+
|
|
221
|
+
%.o: %.c
|
|
222
|
+
$(CC) -c $< -o $@
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Parallel execution:**
|
|
226
|
+
```
|
|
227
|
+
make -j4
|
|
228
|
+
# Compiles 4 .c files simultaneously
|
|
229
|
+
# Then links when all are done
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Dependency Tracking
|
|
233
|
+
|
|
234
|
+
### Accurate Dependencies
|
|
235
|
+
|
|
236
|
+
**Problem: Incorrect dependencies**
|
|
237
|
+
|
|
238
|
+
```makefile
|
|
239
|
+
# WRONG: Missing header dependencies
|
|
240
|
+
main.o: main.c
|
|
241
|
+
$(CC) -c $< -o $@
|
|
242
|
+
|
|
243
|
+
# If common.h changes, main.o won't rebuild!
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Solution: Automatic dependency generation**
|
|
247
|
+
|
|
248
|
+
```makefile
|
|
249
|
+
# Generate dependencies during compilation
|
|
250
|
+
%.o: %.c
|
|
251
|
+
$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
|
|
252
|
+
|
|
253
|
+
# Include generated .d files
|
|
254
|
+
-include $(OBJECTS:.o=.d)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**Generated dependency file (main.d):**
|
|
258
|
+
```makefile
|
|
259
|
+
main.o: main.c common.h utils.h
|
|
260
|
+
common.h:
|
|
261
|
+
utils.h:
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Dependency Flags
|
|
265
|
+
|
|
266
|
+
```makefile
|
|
267
|
+
# -MMD: Generate dependency file (.d)
|
|
268
|
+
# -MP: Add phony targets for headers
|
|
269
|
+
# -MF file: Specify dependency file name
|
|
270
|
+
|
|
271
|
+
DEPFLAGS = -MMD -MP -MF $(@:.o=.d)
|
|
272
|
+
|
|
273
|
+
%.o: %.c
|
|
274
|
+
$(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Why -MP is Important
|
|
278
|
+
|
|
279
|
+
**Without -MP:**
|
|
280
|
+
```makefile
|
|
281
|
+
# Generated main.d:
|
|
282
|
+
main.o: main.c utils.h
|
|
283
|
+
|
|
284
|
+
# If utils.h is deleted:
|
|
285
|
+
make: *** No rule to make target 'utils.h'. Stop.
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**With -MP:**
|
|
289
|
+
```makefile
|
|
290
|
+
# Generated main.d:
|
|
291
|
+
main.o: main.c utils.h
|
|
292
|
+
utils.h:
|
|
293
|
+
|
|
294
|
+
# If utils.h is deleted, make continues
|
|
295
|
+
# (assumes you also removed #include "utils.h")
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Incremental Builds
|
|
299
|
+
|
|
300
|
+
### Timestamp-Based Builds
|
|
301
|
+
|
|
302
|
+
Make rebuilds targets when prerequisites are newer:
|
|
303
|
+
|
|
304
|
+
```makefile
|
|
305
|
+
# program rebuilt if any .o is newer
|
|
306
|
+
program: $(OBJECTS)
|
|
307
|
+
$(CC) $^ -o $@
|
|
308
|
+
|
|
309
|
+
# main.o rebuilt if main.c or headers are newer
|
|
310
|
+
main.o: main.c common.h
|
|
311
|
+
$(CC) -c main.c -o main.o
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Optimizing Dependency Chains
|
|
315
|
+
|
|
316
|
+
**Inefficient:**
|
|
317
|
+
```makefile
|
|
318
|
+
# Every source depends on config.h
|
|
319
|
+
# Changing config.h rebuilds EVERYTHING
|
|
320
|
+
main.o: main.c config.h
|
|
321
|
+
utils.o: utils.c config.h
|
|
322
|
+
helper.o: helper.c config.h
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Better: Only include where needed**
|
|
326
|
+
```makefile
|
|
327
|
+
# Only main.c actually uses config.h
|
|
328
|
+
main.o: main.c config.h
|
|
329
|
+
utils.o: utils.c
|
|
330
|
+
helper.o: helper.c
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Best: Use automatic dependencies**
|
|
334
|
+
```makefile
|
|
335
|
+
%.o: %.c
|
|
336
|
+
$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
|
|
337
|
+
|
|
338
|
+
-include $(DEPENDS)
|
|
339
|
+
# Automatically tracks which headers each file uses
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Intermediate File Management
|
|
343
|
+
|
|
344
|
+
```makefile
|
|
345
|
+
# Mark intermediate files
|
|
346
|
+
.INTERMEDIATE: $(OBJECTS)
|
|
347
|
+
# Deleted after use
|
|
348
|
+
|
|
349
|
+
# Keep important intermediate files
|
|
350
|
+
.SECONDARY: important.o
|
|
351
|
+
# Not deleted
|
|
352
|
+
|
|
353
|
+
# Never delete these files
|
|
354
|
+
.PRECIOUS: %.o %.d
|
|
355
|
+
# Protected from deletion
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Avoiding Unnecessary Rebuilds
|
|
359
|
+
|
|
360
|
+
**Problem: Timestamp updates without changes**
|
|
361
|
+
|
|
362
|
+
```makefile
|
|
363
|
+
# WRONG: Always updates config.h
|
|
364
|
+
config.h: config.h.in
|
|
365
|
+
sed 's/@VERSION@/$(VERSION)/g' $< > $@
|
|
366
|
+
# Updates timestamp even if content unchanged!
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
**Solution: Conditional update**
|
|
370
|
+
|
|
371
|
+
```makefile
|
|
372
|
+
# RIGHT: Only update if different
|
|
373
|
+
config.h: config.h.in
|
|
374
|
+
sed 's/@VERSION@/$(VERSION)/g' $< > $@.tmp
|
|
375
|
+
cmp -s $@.tmp $@ || mv $@.tmp $@
|
|
376
|
+
rm -f $@.tmp
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Build Caching
|
|
380
|
+
|
|
381
|
+
### Compiler Cache (ccache)
|
|
382
|
+
|
|
383
|
+
```makefile
|
|
384
|
+
# Use ccache for faster recompilation
|
|
385
|
+
CC := ccache gcc
|
|
386
|
+
CXX := ccache g++
|
|
387
|
+
|
|
388
|
+
# Or conditionally:
|
|
389
|
+
ifeq ($(shell command -v ccache 2>/dev/null),)
|
|
390
|
+
CC ?= gcc
|
|
391
|
+
else
|
|
392
|
+
CC ?= ccache gcc
|
|
393
|
+
endif
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**Benefits:**
|
|
397
|
+
- Caches compilation results
|
|
398
|
+
- Speeds up clean rebuilds
|
|
399
|
+
- Useful for CI/CD and switching branches
|
|
400
|
+
|
|
401
|
+
### Distcc for Distributed Compilation
|
|
402
|
+
|
|
403
|
+
```makefile
|
|
404
|
+
# Distributed compilation across network
|
|
405
|
+
CC := distcc gcc
|
|
406
|
+
CXX := distcc g++
|
|
407
|
+
|
|
408
|
+
# Set number of jobs based on available hosts
|
|
409
|
+
DISTCC_HOSTS := localhost/2 build1/4 build2/4
|
|
410
|
+
JOBS := 10
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Build Directory Caching
|
|
414
|
+
|
|
415
|
+
```makefile
|
|
416
|
+
# Keep build artifacts between clean builds
|
|
417
|
+
.PHONY: clean distclean
|
|
418
|
+
|
|
419
|
+
clean:
|
|
420
|
+
$(RM) $(TARGET)
|
|
421
|
+
# Keep .o and .d files for faster rebuild
|
|
422
|
+
|
|
423
|
+
distclean: clean
|
|
424
|
+
$(RM) -r $(BUILDDIR)
|
|
425
|
+
# Complete clean
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## Performance Optimization Techniques
|
|
429
|
+
|
|
430
|
+
### 1. Use := Instead of =
|
|
431
|
+
|
|
432
|
+
```makefile
|
|
433
|
+
# SLOW: Recursive expansion (evaluated every use)
|
|
434
|
+
SOURCES = $(wildcard src/*.c)
|
|
435
|
+
OBJECTS = $(SOURCES:.c=.o)
|
|
436
|
+
# $(OBJECTS) re-runs wildcard every time!
|
|
437
|
+
|
|
438
|
+
# FAST: Simple expansion (evaluated once)
|
|
439
|
+
SOURCES := $(wildcard src/*.c)
|
|
440
|
+
OBJECTS := $(SOURCES:.c=.o)
|
|
441
|
+
# Evaluated once when defined
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### 2. Minimize Shell Invocations
|
|
445
|
+
|
|
446
|
+
```makefile
|
|
447
|
+
# SLOW: Multiple shell calls
|
|
448
|
+
FILES = $(shell ls *.c)
|
|
449
|
+
COUNT = $(shell ls *.c | wc -l)
|
|
450
|
+
|
|
451
|
+
# FAST: Single shell call
|
|
452
|
+
FILES := $(wildcard *.c)
|
|
453
|
+
COUNT := $(words $(FILES))
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### 3. Use Static Pattern Rules
|
|
457
|
+
|
|
458
|
+
```makefile
|
|
459
|
+
OBJECTS := main.o utils.o helper.o
|
|
460
|
+
|
|
461
|
+
# FASTER: Static pattern rule (make knows exact files)
|
|
462
|
+
$(OBJECTS): %.o: %.c
|
|
463
|
+
$(CC) -c $< -o $@
|
|
464
|
+
|
|
465
|
+
# SLOWER: Pattern rule (make searches for matches)
|
|
466
|
+
%.o: %.c
|
|
467
|
+
$(CC) -c $< -o $@
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### 4. Reduce Makefile Parsing Time
|
|
471
|
+
|
|
472
|
+
```makefile
|
|
473
|
+
# SLOW: Complex shell commands in variable assignment
|
|
474
|
+
VERSION = $(shell git describe --tags --always --dirty)
|
|
475
|
+
|
|
476
|
+
# FAST: Use := to evaluate once
|
|
477
|
+
VERSION := $(shell git describe --tags --always --dirty)
|
|
478
|
+
|
|
479
|
+
# FASTER: Cache in file
|
|
480
|
+
VERSION := $(file < VERSION.txt)
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### 5. Avoid Recursive Make
|
|
484
|
+
|
|
485
|
+
**Inefficient: Recursive Make**
|
|
486
|
+
|
|
487
|
+
```makefile
|
|
488
|
+
# Top-level Makefile
|
|
489
|
+
SUBDIRS := lib1 lib2 app
|
|
490
|
+
|
|
491
|
+
all:
|
|
492
|
+
for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
**Problems:**
|
|
496
|
+
- Multiple make invocations (slow)
|
|
497
|
+
- Incorrect dependency tracking
|
|
498
|
+
- Parallel builds broken
|
|
499
|
+
|
|
500
|
+
**Efficient: Non-Recursive Make**
|
|
501
|
+
|
|
502
|
+
```makefile
|
|
503
|
+
# Single Makefile
|
|
504
|
+
LIB1_SRC := $(wildcard lib1/*.c)
|
|
505
|
+
LIB2_SRC := $(wildcard lib2/*.c)
|
|
506
|
+
APP_SRC := $(wildcard app/*.c)
|
|
507
|
+
|
|
508
|
+
ALL_SRC := $(LIB1_SRC) $(LIB2_SRC) $(APP_SRC)
|
|
509
|
+
OBJECTS := $(ALL_SRC:.c=.o)
|
|
510
|
+
|
|
511
|
+
# Single dependency tree
|
|
512
|
+
# Accurate parallel builds
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
**Reference:** "Recursive Make Considered Harmful" by Peter Miller
|
|
516
|
+
|
|
517
|
+
## Performance Profiling
|
|
518
|
+
|
|
519
|
+
### Timing Individual Targets
|
|
520
|
+
|
|
521
|
+
```makefile
|
|
522
|
+
# Time recipe execution
|
|
523
|
+
%.o: %.c
|
|
524
|
+
@echo "Compiling $<..."
|
|
525
|
+
@time $(CC) $(CFLAGS) -c $< -o $@
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### Build Time Measurement
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
# Time entire build
|
|
532
|
+
time make -j4
|
|
533
|
+
|
|
534
|
+
# Output:
|
|
535
|
+
# real 0m12.345s
|
|
536
|
+
# user 0m45.678s
|
|
537
|
+
# sys 0m3.456s
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### Debug Output for Performance Analysis
|
|
541
|
+
|
|
542
|
+
```bash
|
|
543
|
+
# Show what make is doing
|
|
544
|
+
make -d
|
|
545
|
+
|
|
546
|
+
# Show only remake decisions
|
|
547
|
+
make -d --debug=basic
|
|
548
|
+
|
|
549
|
+
# Show implicit rule search
|
|
550
|
+
make -d --debug=implicit
|
|
551
|
+
|
|
552
|
+
# Profile make itself
|
|
553
|
+
make --profile=profile.log
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### Finding Bottlenecks
|
|
557
|
+
|
|
558
|
+
```makefile
|
|
559
|
+
# Add timing to critical paths
|
|
560
|
+
$(TARGET): $(OBJECTS)
|
|
561
|
+
@echo "==> Linking $(TARGET)"
|
|
562
|
+
@time $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
|
563
|
+
|
|
564
|
+
%.o: %.c
|
|
565
|
+
@echo "==> Compiling $<"
|
|
566
|
+
@time $(CC) $(CFLAGS) -c $< -o $@
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
## Optimization Best Practices
|
|
570
|
+
|
|
571
|
+
### 1. Structure for Parallelism
|
|
572
|
+
|
|
573
|
+
```makefile
|
|
574
|
+
# Good: Independent compilation
|
|
575
|
+
OBJECTS := a.o b.o c.o d.o
|
|
576
|
+
|
|
577
|
+
program: $(OBJECTS)
|
|
578
|
+
$(CC) $^ -o $@
|
|
579
|
+
|
|
580
|
+
%.o: %.c
|
|
581
|
+
$(CC) -c $< -o $@
|
|
582
|
+
|
|
583
|
+
# make -j4 compiles 4 files at once
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### 2. Accurate Dependencies
|
|
587
|
+
|
|
588
|
+
```makefile
|
|
589
|
+
# Use automatic dependency generation
|
|
590
|
+
CFLAGS += -MMD -MP
|
|
591
|
+
-include $(OBJECTS:.o=.d)
|
|
592
|
+
|
|
593
|
+
# Not manual maintenance
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### 3. Minimal Clean
|
|
597
|
+
|
|
598
|
+
```makefile
|
|
599
|
+
# Keep intermediate files by default
|
|
600
|
+
clean:
|
|
601
|
+
$(RM) $(TARGET)
|
|
602
|
+
|
|
603
|
+
# Full clean only when needed
|
|
604
|
+
distclean: clean
|
|
605
|
+
$(RM) $(OBJECTS) $(DEPENDS)
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### 4. Efficient Variable Usage
|
|
609
|
+
|
|
610
|
+
```makefile
|
|
611
|
+
# Use := for computed values
|
|
612
|
+
SOURCES := $(wildcard src/*.c)
|
|
613
|
+
OBJECTS := $(SOURCES:.c=.o)
|
|
614
|
+
|
|
615
|
+
# Use ?= for user overrides
|
|
616
|
+
CC ?= gcc
|
|
617
|
+
CFLAGS ?= -O2
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### 5. Avoid Unnecessary Work
|
|
621
|
+
|
|
622
|
+
```makefile
|
|
623
|
+
# Don't rebuild if nothing changed
|
|
624
|
+
config.h: config.h.in Makefile
|
|
625
|
+
@sed 's/@VERSION@/$(VERSION)/g' $< > $@.tmp
|
|
626
|
+
@if ! cmp -s $@ $@.tmp; then \
|
|
627
|
+
echo " GEN $@"; \
|
|
628
|
+
mv $@.tmp $@; \
|
|
629
|
+
else \
|
|
630
|
+
rm -f $@.tmp; \
|
|
631
|
+
fi
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
## Complete Optimized Example
|
|
635
|
+
|
|
636
|
+
```makefile
|
|
637
|
+
# Optimized Makefile for C project
|
|
638
|
+
.DELETE_ON_ERROR:
|
|
639
|
+
.SUFFIXES:
|
|
640
|
+
|
|
641
|
+
PROJECT := optimized
|
|
642
|
+
VERSION := 1.0.0
|
|
643
|
+
|
|
644
|
+
# User-overridable (use ?=)
|
|
645
|
+
CC ?= gcc
|
|
646
|
+
CFLAGS ?= -Wall -Wextra -O2
|
|
647
|
+
PREFIX ?= /usr/local
|
|
648
|
+
|
|
649
|
+
# Computed once (use :=)
|
|
650
|
+
SRCDIR := src
|
|
651
|
+
BUILDDIR := build
|
|
652
|
+
OBJDIR := $(BUILDDIR)/obj
|
|
653
|
+
|
|
654
|
+
SOURCES := $(wildcard $(SRCDIR)/*.c)
|
|
655
|
+
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
|
|
656
|
+
DEPENDS := $(OBJECTS:.o=.d)
|
|
657
|
+
TARGET := $(BUILDDIR)/$(PROJECT)
|
|
658
|
+
|
|
659
|
+
# Check for ccache
|
|
660
|
+
ifneq ($(shell command -v ccache 2>/dev/null),)
|
|
661
|
+
CC := ccache $(CC)
|
|
662
|
+
endif
|
|
663
|
+
|
|
664
|
+
# Optimization flags for dependencies
|
|
665
|
+
DEPFLAGS = -MMD -MP
|
|
666
|
+
|
|
667
|
+
.PHONY: all clean distclean profile
|
|
668
|
+
|
|
669
|
+
all: $(TARGET)
|
|
670
|
+
|
|
671
|
+
# Link (serial)
|
|
672
|
+
$(TARGET): $(OBJECTS)
|
|
673
|
+
@mkdir -p $(@D)
|
|
674
|
+
@echo " LD $@"
|
|
675
|
+
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
|
676
|
+
|
|
677
|
+
# Compile (parallel-safe)
|
|
678
|
+
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
|
679
|
+
@mkdir -p $(@D)
|
|
680
|
+
@echo " CC $<"
|
|
681
|
+
$(CC) $(CPPFLAGS) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
682
|
+
|
|
683
|
+
# Include auto-generated dependencies
|
|
684
|
+
-include $(DEPENDS)
|
|
685
|
+
|
|
686
|
+
# Minimal clean (keeps .o for faster rebuild)
|
|
687
|
+
clean:
|
|
688
|
+
$(RM) $(TARGET)
|
|
689
|
+
|
|
690
|
+
# Full clean
|
|
691
|
+
distclean:
|
|
692
|
+
$(RM) -r $(BUILDDIR)
|
|
693
|
+
|
|
694
|
+
# Profile build
|
|
695
|
+
profile:
|
|
696
|
+
time $(MAKE) clean
|
|
697
|
+
time $(MAKE) -j$(shell nproc) all
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
## Benchmarking Results
|
|
701
|
+
|
|
702
|
+
**Example project: 100 C files**
|
|
703
|
+
|
|
704
|
+
| Configuration | Build Time | Rebuild Time |
|
|
705
|
+
|---------------|------------|--------------|
|
|
706
|
+
| Sequential (make) | 45s | 12s |
|
|
707
|
+
| Parallel -j2 | 25s | 7s |
|
|
708
|
+
| Parallel -j4 | 15s | 4s |
|
|
709
|
+
| Parallel -j8 | 12s | 3s |
|
|
710
|
+
| Parallel + ccache (cold) | 14s | 3s |
|
|
711
|
+
| Parallel + ccache (warm) | 3s | 1s |
|
|
712
|
+
|
|
713
|
+
**Key takeaways:**
|
|
714
|
+
- Parallel builds: 3-4x speedup
|
|
715
|
+
- ccache (warm): 10x speedup on clean builds
|
|
716
|
+
- Accurate dependencies: Only rebuild what changed
|
|
717
|
+
|
|
718
|
+
## Advanced Optimization
|
|
719
|
+
|
|
720
|
+
### Precompiled Headers
|
|
721
|
+
|
|
722
|
+
```makefile
|
|
723
|
+
# Generate precompiled header
|
|
724
|
+
$(OBJDIR)/common.h.gch: $(SRCDIR)/common.h
|
|
725
|
+
@mkdir -p $(@D)
|
|
726
|
+
$(CC) $(CPPFLAGS) $(CFLAGS) -x c-header $< -o $@
|
|
727
|
+
|
|
728
|
+
# Use precompiled header
|
|
729
|
+
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(OBJDIR)/common.h.gch
|
|
730
|
+
$(CC) $(CPPFLAGS) $(CFLAGS) -include $(OBJDIR)/common.h -c $< -o $@
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### Link-Time Optimization (LTO)
|
|
734
|
+
|
|
735
|
+
```makefile
|
|
736
|
+
# Enable LTO for release builds
|
|
737
|
+
release: CFLAGS += -flto -O3
|
|
738
|
+
release: LDFLAGS += -flto -O3
|
|
739
|
+
release: $(TARGET)
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
### Unity Builds
|
|
743
|
+
|
|
744
|
+
```makefile
|
|
745
|
+
# Combine all sources into one compilation unit
|
|
746
|
+
unity.c: $(SOURCES)
|
|
747
|
+
@echo "Generating unity build..."
|
|
748
|
+
@for src in $(SOURCES); do \
|
|
749
|
+
echo "#include \"$$src\"" >> $@; \
|
|
750
|
+
done
|
|
751
|
+
|
|
752
|
+
unity.o: unity.c
|
|
753
|
+
$(CC) $(CFLAGS) -c $< -o $@
|
|
754
|
+
|
|
755
|
+
# Fast single-file compilation
|
|
756
|
+
# Trade-off: No parallel compilation
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
## Profiling Tools
|
|
760
|
+
|
|
761
|
+
```bash
|
|
762
|
+
# Make's built-in profiling
|
|
763
|
+
make --profile=profile.log
|
|
764
|
+
# Analyze profile.log
|
|
765
|
+
|
|
766
|
+
# Time individual targets
|
|
767
|
+
make -d 2>&1 | grep -E "Considering|Must remake"
|
|
768
|
+
|
|
769
|
+
# strace for system call analysis
|
|
770
|
+
strace -c make 2>&1 | tail -20
|
|
771
|
+
|
|
772
|
+
# Remake (make debugger)
|
|
773
|
+
remake --debug
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
## References
|
|
777
|
+
|
|
778
|
+
- [GNU Make Manual - Parallel Execution](https://www.gnu.org/software/make/manual/html_node/Parallel.html)
|
|
779
|
+
- [GNU Make Manual - Parallel Disable (.WAIT, .NOTPARALLEL)](https://www.gnu.org/software/make/manual/html_node/Parallel-Disable.html)
|
|
780
|
+
- [GNU Make 4.4 Release Notes](https://lists.gnu.org/archive/html/info-gnu/2022-10/msg00008.html)
|
|
781
|
+
- [GNU Make 4.4.1 Release Notes](https://lists.gnu.org/archive/html/info-gnu/2023-02/msg00011.html)
|
|
782
|
+
- [Recursive Make Considered Harmful](http://aegis.sourceforge.net/auug97.pdf)
|
|
783
|
+
- [ccache Documentation](https://ccache.dev/manual/latest.html)
|
|
784
|
+
- [Auto-Dependency Generation](https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/)
|