@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,530 @@
|
|
|
1
|
+
# Makefile Structure and Organization
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide covers the organization and structure of well-designed Makefiles, including variable definitions, target organization, pattern rules, and modular design patterns.
|
|
6
|
+
|
|
7
|
+
## Basic Makefile Structure
|
|
8
|
+
|
|
9
|
+
A well-organized Makefile follows this general structure:
|
|
10
|
+
|
|
11
|
+
```makefile
|
|
12
|
+
# 1. Header and metadata
|
|
13
|
+
# 2. Special targets (.POSIX, .DELETE_ON_ERROR, .SUFFIXES)
|
|
14
|
+
# 3. User-overridable variables
|
|
15
|
+
# 4. Project-specific variables
|
|
16
|
+
# 5. .PHONY declarations
|
|
17
|
+
# 6. Default target (all)
|
|
18
|
+
# 7. Build rules
|
|
19
|
+
# 8. Install rules
|
|
20
|
+
# 9. Clean rules
|
|
21
|
+
# 10. Test rules
|
|
22
|
+
# 11. Help target
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 1. Header and Metadata
|
|
26
|
+
|
|
27
|
+
```makefile
|
|
28
|
+
# Project: MyApp
|
|
29
|
+
# Description: Brief description of the project
|
|
30
|
+
# Author: Your Name
|
|
31
|
+
# License: MIT
|
|
32
|
+
# Version: 1.0.0
|
|
33
|
+
|
|
34
|
+
# Ensure POSIX compatibility (optional)
|
|
35
|
+
.POSIX:
|
|
36
|
+
|
|
37
|
+
# Delete target files if recipe fails
|
|
38
|
+
.DELETE_ON_ERROR:
|
|
39
|
+
|
|
40
|
+
# Disable built-in suffix rules
|
|
41
|
+
.SUFFIXES:
|
|
42
|
+
|
|
43
|
+
# Custom suffixes if needed
|
|
44
|
+
.SUFFIXES: .c .o .h
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Special Targets Explained
|
|
48
|
+
|
|
49
|
+
- **.POSIX**: Declares intent for POSIX compliance (optional, increases portability)
|
|
50
|
+
- **.DELETE_ON_ERROR**: If a recipe fails, delete the target file (prevents corrupted builds)
|
|
51
|
+
- **.SUFFIXES**: Clear built-in suffix rules, then optionally declare custom ones
|
|
52
|
+
|
|
53
|
+
## 2. Variable Organization
|
|
54
|
+
|
|
55
|
+
### User-Overridable Variables (use ?=)
|
|
56
|
+
|
|
57
|
+
Variables that users should be able to override from the command line or environment:
|
|
58
|
+
|
|
59
|
+
```makefile
|
|
60
|
+
# Compiler and tools
|
|
61
|
+
CC ?= gcc
|
|
62
|
+
CXX ?= g++
|
|
63
|
+
LD ?= $(CC)
|
|
64
|
+
AR ?= ar
|
|
65
|
+
RANLIB ?= ranlib
|
|
66
|
+
INSTALL ?= install
|
|
67
|
+
RM ?= rm -f
|
|
68
|
+
MKDIR_P ?= mkdir -p
|
|
69
|
+
|
|
70
|
+
# Compiler flags
|
|
71
|
+
CFLAGS ?= -Wall -Wextra -O2
|
|
72
|
+
CXXFLAGS ?= -Wall -Wextra -O2
|
|
73
|
+
CPPFLAGS ?=
|
|
74
|
+
LDFLAGS ?=
|
|
75
|
+
LDLIBS ?=
|
|
76
|
+
|
|
77
|
+
# Installation paths (GNU conventions)
|
|
78
|
+
PREFIX ?= /usr/local
|
|
79
|
+
EXEC_PREFIX ?= $(PREFIX)
|
|
80
|
+
BINDIR ?= $(EXEC_PREFIX)/bin
|
|
81
|
+
LIBDIR ?= $(EXEC_PREFIX)/lib
|
|
82
|
+
INCLUDEDIR ?= $(PREFIX)/include
|
|
83
|
+
DATAROOTDIR ?= $(PREFIX)/share
|
|
84
|
+
DATADIR ?= $(DATAROOTDIR)
|
|
85
|
+
MANDIR ?= $(DATAROOTDIR)/man
|
|
86
|
+
|
|
87
|
+
# DESTDIR for staged installations
|
|
88
|
+
DESTDIR ?=
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Why ?= instead of =:**
|
|
92
|
+
- `?=` only sets the variable if not already defined
|
|
93
|
+
- Allows users to override: `make CC=clang CFLAGS="-O3 -march=native"`
|
|
94
|
+
- Respects environment variables
|
|
95
|
+
|
|
96
|
+
### Project-Specific Variables (use :=)
|
|
97
|
+
|
|
98
|
+
Variables internal to the Makefile that should not be overridden:
|
|
99
|
+
|
|
100
|
+
```makefile
|
|
101
|
+
# Project configuration
|
|
102
|
+
PROJECT := myapp
|
|
103
|
+
VERSION := 1.0.0
|
|
104
|
+
TARGET := $(PROJECT)
|
|
105
|
+
|
|
106
|
+
# Directory structure
|
|
107
|
+
SRCDIR := src
|
|
108
|
+
INCDIR := include
|
|
109
|
+
BUILDDIR := build
|
|
110
|
+
OBJDIR := $(BUILDDIR)/obj
|
|
111
|
+
DEPDIR := $(BUILDDIR)/deps
|
|
112
|
+
|
|
113
|
+
# Source files (use wildcards or explicit lists)
|
|
114
|
+
SOURCES := $(wildcard $(SRCDIR)/*.c)
|
|
115
|
+
HEADERS := $(wildcard $(INCDIR)/*.h)
|
|
116
|
+
|
|
117
|
+
# Derived file lists
|
|
118
|
+
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
|
|
119
|
+
DEPENDS := $(OBJECTS:.o=.d)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Why := instead of =:**
|
|
123
|
+
- `:=` performs immediate expansion (evaluated once)
|
|
124
|
+
- `=` performs recursive expansion (evaluated each use)
|
|
125
|
+
- `:=` is more efficient for computed values
|
|
126
|
+
|
|
127
|
+
### Variable Expansion Example
|
|
128
|
+
|
|
129
|
+
```makefile
|
|
130
|
+
# Wrong: = causes recursive expansion
|
|
131
|
+
FILES = $(wildcard *.c)
|
|
132
|
+
# Expands every time $(FILES) is used
|
|
133
|
+
|
|
134
|
+
# Right: := evaluates once
|
|
135
|
+
FILES := $(wildcard *.c)
|
|
136
|
+
# Evaluated immediately, more efficient
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## 3. Target Organization
|
|
140
|
+
|
|
141
|
+
### .PHONY Declarations
|
|
142
|
+
|
|
143
|
+
Declare all non-file targets as .PHONY to ensure they always run:
|
|
144
|
+
|
|
145
|
+
```makefile
|
|
146
|
+
.PHONY: all clean install uninstall test check help
|
|
147
|
+
.PHONY: build dist distclean format lint
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Why .PHONY is critical:**
|
|
151
|
+
- Without .PHONY, if a file named "clean" exists, `make clean` won't run
|
|
152
|
+
- .PHONY tells make these targets don't create files
|
|
153
|
+
- Improves make performance by skipping unnecessary stat() calls
|
|
154
|
+
|
|
155
|
+
### Default Target
|
|
156
|
+
|
|
157
|
+
The first target in the Makefile is the default (run when `make` is called without arguments):
|
|
158
|
+
|
|
159
|
+
```makefile
|
|
160
|
+
## Build all targets
|
|
161
|
+
.PHONY: all
|
|
162
|
+
all: $(TARGET)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Best practices:**
|
|
166
|
+
- Name it `all`
|
|
167
|
+
- Make it the first target after variable definitions
|
|
168
|
+
- It should build everything but not install or clean
|
|
169
|
+
|
|
170
|
+
## 4. Build Rules
|
|
171
|
+
|
|
172
|
+
### Explicit Rules
|
|
173
|
+
|
|
174
|
+
```makefile
|
|
175
|
+
# Link the executable
|
|
176
|
+
$(TARGET): $(OBJECTS)
|
|
177
|
+
@mkdir -p $(@D)
|
|
178
|
+
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Pattern Rules (Preferred)
|
|
182
|
+
|
|
183
|
+
Pattern rules use `%` to match multiple files:
|
|
184
|
+
|
|
185
|
+
```makefile
|
|
186
|
+
# Compile C source files to object files
|
|
187
|
+
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
|
188
|
+
@mkdir -p $(@D)
|
|
189
|
+
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
|
|
190
|
+
|
|
191
|
+
# Alternative without directories:
|
|
192
|
+
%.o: %.c
|
|
193
|
+
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Automatic Variables
|
|
197
|
+
|
|
198
|
+
| Variable | Meaning |
|
|
199
|
+
|----------|---------|
|
|
200
|
+
| `$@` | Target file name |
|
|
201
|
+
| `$<` | First prerequisite |
|
|
202
|
+
| `$^` | All prerequisites (with duplicates removed) |
|
|
203
|
+
| `$+` | All prerequisites (with duplicates) |
|
|
204
|
+
| `$?` | Prerequisites newer than target |
|
|
205
|
+
| `$*` | Stem of pattern match |
|
|
206
|
+
| `$(@D)` | Directory part of target |
|
|
207
|
+
| `$(@F)` | File part of target |
|
|
208
|
+
|
|
209
|
+
**Example using automatic variables:**
|
|
210
|
+
|
|
211
|
+
```makefile
|
|
212
|
+
# Without automatic variables (verbose):
|
|
213
|
+
hello: hello.o utils.o
|
|
214
|
+
gcc -o hello hello.o utils.o
|
|
215
|
+
|
|
216
|
+
# With automatic variables (concise):
|
|
217
|
+
hello: hello.o utils.o
|
|
218
|
+
$(CC) -o $@ $^
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## 5. Dependency Management
|
|
222
|
+
|
|
223
|
+
### Manual Dependencies
|
|
224
|
+
|
|
225
|
+
```makefile
|
|
226
|
+
main.o: main.c common.h
|
|
227
|
+
utils.o: utils.c utils.h common.h
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Problems:**
|
|
231
|
+
- Tedious to maintain
|
|
232
|
+
- Easy to get out of sync
|
|
233
|
+
- Error-prone for large projects
|
|
234
|
+
|
|
235
|
+
### Automatic Dependency Generation (Recommended)
|
|
236
|
+
|
|
237
|
+
```makefile
|
|
238
|
+
# Generate dependencies automatically during compilation
|
|
239
|
+
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
|
240
|
+
@mkdir -p $(@D)
|
|
241
|
+
$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -c $< -o $@
|
|
242
|
+
|
|
243
|
+
# Include generated dependency files
|
|
244
|
+
-include $(DEPENDS)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Flags explained:**
|
|
248
|
+
- `-MMD`: Generate dependency file (.d)
|
|
249
|
+
- `-MP`: Add phony targets for headers (prevents errors if header deleted)
|
|
250
|
+
- `-include`: Include files, ignoring errors if they don't exist yet (first build)
|
|
251
|
+
|
|
252
|
+
## 6. VPATH and Source Organization
|
|
253
|
+
|
|
254
|
+
### VPATH for Source Directories
|
|
255
|
+
|
|
256
|
+
```makefile
|
|
257
|
+
# Search for source files in multiple directories
|
|
258
|
+
VPATH = src:include:lib
|
|
259
|
+
|
|
260
|
+
# Make will search these directories for prerequisites
|
|
261
|
+
main.o: main.c common.h
|
|
262
|
+
$(CC) -c $< -o $@
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### vpath Directive (More Specific)
|
|
266
|
+
|
|
267
|
+
```makefile
|
|
268
|
+
# Search pattern-specific paths
|
|
269
|
+
vpath %.c src
|
|
270
|
+
vpath %.h include
|
|
271
|
+
vpath %.o build/obj
|
|
272
|
+
|
|
273
|
+
%.o: %.c
|
|
274
|
+
$(CC) -c $< -o $@
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**When to use VPATH:**
|
|
278
|
+
- Multi-directory projects
|
|
279
|
+
- Separating source and build directories
|
|
280
|
+
- Organizing headers separately
|
|
281
|
+
|
|
282
|
+
## 7. Include Directives
|
|
283
|
+
|
|
284
|
+
### Modular Makefiles
|
|
285
|
+
|
|
286
|
+
Split large Makefiles into smaller, focused files:
|
|
287
|
+
|
|
288
|
+
```makefile
|
|
289
|
+
# Main Makefile
|
|
290
|
+
include config.mk
|
|
291
|
+
include rules.mk
|
|
292
|
+
include targets.mk
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**config.mk** (variables):
|
|
296
|
+
```makefile
|
|
297
|
+
CC := gcc
|
|
298
|
+
CFLAGS := -Wall -O2
|
|
299
|
+
PREFIX := /usr/local
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**rules.mk** (pattern rules):
|
|
303
|
+
```makefile
|
|
304
|
+
%.o: %.c
|
|
305
|
+
$(CC) $(CFLAGS) -c $< -o $@
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**targets.mk** (phony targets):
|
|
309
|
+
```makefile
|
|
310
|
+
.PHONY: clean
|
|
311
|
+
clean:
|
|
312
|
+
$(RM) *.o $(TARGET)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Conditional Includes
|
|
316
|
+
|
|
317
|
+
```makefile
|
|
318
|
+
# Include file if it exists
|
|
319
|
+
-include config.mk
|
|
320
|
+
|
|
321
|
+
# Include multiple files
|
|
322
|
+
-include $(DEPENDS)
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**`-` prefix**: Suppress errors if file doesn't exist
|
|
326
|
+
|
|
327
|
+
## 8. Multi-Directory Projects
|
|
328
|
+
|
|
329
|
+
### Non-Recursive Make (Recommended)
|
|
330
|
+
|
|
331
|
+
**Single Makefile approach:**
|
|
332
|
+
|
|
333
|
+
```makefile
|
|
334
|
+
# Directory structure:
|
|
335
|
+
# project/
|
|
336
|
+
# Makefile
|
|
337
|
+
# src/
|
|
338
|
+
# main.c
|
|
339
|
+
# utils.c
|
|
340
|
+
# lib/
|
|
341
|
+
# libfoo.c
|
|
342
|
+
|
|
343
|
+
SRCDIR := src
|
|
344
|
+
LIBDIR := lib
|
|
345
|
+
BUILDDIR := build
|
|
346
|
+
|
|
347
|
+
SRC_SOURCES := $(wildcard $(SRCDIR)/*.c)
|
|
348
|
+
LIB_SOURCES := $(wildcard $(LIBDIR)/*.c)
|
|
349
|
+
ALL_SOURCES := $(SRC_SOURCES) $(LIB_SOURCES)
|
|
350
|
+
|
|
351
|
+
OBJECTS := $(ALL_SOURCES:%.c=$(BUILDDIR)/%.o)
|
|
352
|
+
|
|
353
|
+
$(TARGET): $(OBJECTS)
|
|
354
|
+
$(CC) $^ -o $@
|
|
355
|
+
|
|
356
|
+
$(BUILDDIR)/%.o: %.c
|
|
357
|
+
@mkdir -p $(@D)
|
|
358
|
+
$(CC) $(CFLAGS) -c $< -o $@
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Advantages:**
|
|
362
|
+
- Single make invocation
|
|
363
|
+
- Accurate dependency tracking
|
|
364
|
+
- Parallel builds work correctly
|
|
365
|
+
- Easier to maintain
|
|
366
|
+
|
|
367
|
+
### Recursive Make (Avoid if Possible)
|
|
368
|
+
|
|
369
|
+
```makefile
|
|
370
|
+
# Top-level Makefile
|
|
371
|
+
SUBDIRS := src lib tests
|
|
372
|
+
|
|
373
|
+
.PHONY: all
|
|
374
|
+
all:
|
|
375
|
+
for dir in $(SUBDIRS); do $(MAKE) -C $$dir; done
|
|
376
|
+
|
|
377
|
+
.PHONY: clean
|
|
378
|
+
clean:
|
|
379
|
+
for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Problems with recursive make:**
|
|
383
|
+
- Incorrect dependency tracking across directories
|
|
384
|
+
- Slower (multiple make invocations)
|
|
385
|
+
- Parallel builds can break
|
|
386
|
+
- See: "Recursive Make Considered Harmful" paper
|
|
387
|
+
|
|
388
|
+
## 9. Recipe Formatting
|
|
389
|
+
|
|
390
|
+
### Silent Commands
|
|
391
|
+
|
|
392
|
+
```makefile
|
|
393
|
+
# @ prefix suppresses command echo
|
|
394
|
+
clean:
|
|
395
|
+
@echo "Cleaning build artifacts..."
|
|
396
|
+
@$(RM) *.o
|
|
397
|
+
|
|
398
|
+
# Without @:
|
|
399
|
+
clean:
|
|
400
|
+
echo "Cleaning..." # This line is printed
|
|
401
|
+
$(RM) *.o # This line is printed
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Multi-Line Recipes
|
|
405
|
+
|
|
406
|
+
```makefile
|
|
407
|
+
# Each line is a separate shell invocation
|
|
408
|
+
bad:
|
|
409
|
+
cd subdir
|
|
410
|
+
make all # ERROR: cd didn't persist!
|
|
411
|
+
|
|
412
|
+
# Solution 1: Use && to chain commands
|
|
413
|
+
good:
|
|
414
|
+
cd subdir && make all
|
|
415
|
+
|
|
416
|
+
# Solution 2: Use semicolons
|
|
417
|
+
good2:
|
|
418
|
+
cd subdir; make all
|
|
419
|
+
|
|
420
|
+
# Solution 3: Use backslash continuation
|
|
421
|
+
good3:
|
|
422
|
+
cd subdir && \
|
|
423
|
+
make all
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Error Handling
|
|
427
|
+
|
|
428
|
+
```makefile
|
|
429
|
+
# - prefix ignores errors
|
|
430
|
+
clean:
|
|
431
|
+
-$(RM) *.o # Continue even if rm fails
|
|
432
|
+
|
|
433
|
+
# Without -:
|
|
434
|
+
clean:
|
|
435
|
+
$(RM) *.o # Make stops if rm fails
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## 10. Complete Example
|
|
439
|
+
|
|
440
|
+
```makefile
|
|
441
|
+
# Project: example
|
|
442
|
+
# Description: Example project structure
|
|
443
|
+
|
|
444
|
+
.DELETE_ON_ERROR:
|
|
445
|
+
.SUFFIXES:
|
|
446
|
+
|
|
447
|
+
# Variables
|
|
448
|
+
CC ?= gcc
|
|
449
|
+
CFLAGS ?= -Wall -Wextra -O2
|
|
450
|
+
PREFIX ?= /usr/local
|
|
451
|
+
|
|
452
|
+
PROJECT := example
|
|
453
|
+
VERSION := 1.0.0
|
|
454
|
+
SRCDIR := src
|
|
455
|
+
BUILDDIR := build
|
|
456
|
+
OBJDIR := $(BUILDDIR)/obj
|
|
457
|
+
|
|
458
|
+
SOURCES := $(wildcard $(SRCDIR)/*.c)
|
|
459
|
+
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
|
|
460
|
+
DEPENDS := $(OBJECTS:.o=.d)
|
|
461
|
+
TARGET := $(BUILDDIR)/$(PROJECT)
|
|
462
|
+
|
|
463
|
+
# Phony targets
|
|
464
|
+
.PHONY: all clean install test help
|
|
465
|
+
|
|
466
|
+
# Default target
|
|
467
|
+
all: $(TARGET)
|
|
468
|
+
|
|
469
|
+
# Build rules
|
|
470
|
+
$(TARGET): $(OBJECTS)
|
|
471
|
+
@mkdir -p $(@D)
|
|
472
|
+
@echo " LD $@"
|
|
473
|
+
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
|
|
474
|
+
|
|
475
|
+
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
|
476
|
+
@mkdir -p $(@D)
|
|
477
|
+
@echo " CC $<"
|
|
478
|
+
$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -c $< -o $@
|
|
479
|
+
|
|
480
|
+
-include $(DEPENDS)
|
|
481
|
+
|
|
482
|
+
# Install
|
|
483
|
+
install: $(TARGET)
|
|
484
|
+
install -d $(DESTDIR)$(PREFIX)/bin
|
|
485
|
+
install -m 755 $(TARGET) $(DESTDIR)$(PREFIX)/bin/$(PROJECT)
|
|
486
|
+
|
|
487
|
+
# Clean
|
|
488
|
+
clean:
|
|
489
|
+
$(RM) -r $(BUILDDIR)
|
|
490
|
+
|
|
491
|
+
# Test
|
|
492
|
+
test: $(TARGET)
|
|
493
|
+
@echo "Running tests..."
|
|
494
|
+
@$(TARGET) --test
|
|
495
|
+
|
|
496
|
+
# Help
|
|
497
|
+
help:
|
|
498
|
+
@echo "$(PROJECT) v$(VERSION)"
|
|
499
|
+
@echo ""
|
|
500
|
+
@echo "Targets:"
|
|
501
|
+
@echo " all - Build the project (default)"
|
|
502
|
+
@echo " install - Install to PREFIX (default: /usr/local)"
|
|
503
|
+
@echo " clean - Remove build artifacts"
|
|
504
|
+
@echo " test - Run tests"
|
|
505
|
+
@echo " help - Show this message"
|
|
506
|
+
@echo ""
|
|
507
|
+
@echo "Variables:"
|
|
508
|
+
@echo " CC=$(CC)"
|
|
509
|
+
@echo " CFLAGS=$(CFLAGS)"
|
|
510
|
+
@echo " PREFIX=$(PREFIX)"
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
## Best Practices Summary
|
|
514
|
+
|
|
515
|
+
1. **Use .DELETE_ON_ERROR** to prevent corrupted builds
|
|
516
|
+
2. **Declare .PHONY** for all non-file targets
|
|
517
|
+
3. **Use ?= for user-overridable variables** (CC, CFLAGS, PREFIX)
|
|
518
|
+
4. **Use := for project variables** (SOURCES, OBJECTS)
|
|
519
|
+
5. **Use automatic variables** ($@, $<, $^) for concise rules
|
|
520
|
+
6. **Generate dependencies automatically** (-MMD -MP)
|
|
521
|
+
7. **Prefer non-recursive make** over recursive make
|
|
522
|
+
8. **Use pattern rules** (%.o: %.c) over suffix rules
|
|
523
|
+
9. **Create directories automatically** (@mkdir -p $(@D))
|
|
524
|
+
10. **Document targets** with ## comments for help output
|
|
525
|
+
|
|
526
|
+
## References
|
|
527
|
+
|
|
528
|
+
- [GNU Make Manual - Makefile Structure](https://www.gnu.org/software/make/manual/html_node/Makefile-Contents.html)
|
|
529
|
+
- [GNU Coding Standards - Makefile Conventions](https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html)
|
|
530
|
+
- [Recursive Make Considered Harmful](http://aegis.sourceforge.net/auug97.pdf)
|