Comprehensive toolkit for validating, linting, and optimizing Makefiles. Use this skill when working with Makefiles (Makefile, makefile, *.mk files), validating build configurations, checking for best practices, identifying security issues, or debugging Makefile problems.
Overall
score
100%
Does it follow best practices?
Validation for skill structure
Comprehensive guide to using mbake (Makefile formatter and linter) for Makefile validation and formatting.
mbake is a modern Python-based tool designed to format and validate Makefiles with intelligent features. It's the first comprehensive Makefile formatter and linter, filling a 50-year gap in build tooling.
Current Version: See PyPI for latest
While mbake is excellent for GNU Make formatting, be aware of these limitations:
.SUFFIXES special targetmbake format --check warns about different things than mbake format fixesFor additional linting coverage, consider using checkmake alongside mbake.
# Install mbake
pip install mbake
# Upgrade to latest version
pip install --upgrade mbake
# Verify installation
mbake --version# Create venv
python3 -m venv mbake-env
# Activate venv
source mbake-env/bin/activate # Linux/macOS
# or
mbake-env\Scripts\activate # Windows
# Install mbake
pip install mbake
# Use mbake
mbake format Makefile
# Deactivate when done
deactivateNote: The makefile-validator skill automatically handles venv creation and cleanup.
Install the "mbake Makefile Formatter" extension from the VS Code marketplace:
# 1. Check current formatting status
mbake format --check Makefile
# 2. Preview changes before applying
mbake format --diff Makefile
# 3. Apply formatting
mbake format Makefile
# 4. Validate syntax
mbake validate Makefile# Initialize configuration file
mbake init
# This creates ~/.bake.toml with default settings
# Edit the file to customize mbake behavior
# View current configuration
mbake config
# Format with current settings
mbake format Makefilembake formatFormat and standardize Makefile structure.
# Basic formatting
mbake format Makefile
# Check formatting without modifying (CI/CD)
mbake format --check Makefile
# Exit code: 0 (properly formatted), 1 (needs formatting)
# Show diff of changes
mbake format --diff Makefile
# Backup before formatting
mbake format --backup Makefile
# Creates Makefile.bak
# Validate after formatting
mbake format --validate Makefile
# Specify custom config file
mbake format --config /path/to/.bake.toml Makefile
# Format multiple files
mbake format Makefile tests/*.mk build/*.mkOptions:
--check: Check formatting without modifying (exit 0 if formatted, 1 if not)--diff: Display potential changes without applying--backup: Create .bak backup before modifying--validate: Run syntax validation after formatting--config PATH: Use custom configuration filembake validateValidate Makefile syntax using GNU Make.
# Validate syntax
mbake validate Makefile
# Validates with: make -f Makefile --dry-run
# Exit code: 0 (valid), 1 (invalid)
# Validate multiple files
mbake validate Makefile src/*.mkWhat it checks:
mbake initCreate initial configuration file.
# Create ~/.bake.toml with defaults
mbake init
# The configuration file includes all formatting options
# Edit it to customize mbake behaviormbake configDisplay current configuration settings.
# Show active configuration
mbake config
# Output includes:
# - Configuration file location
# - All active settings
# - Default values for unset optionsmbake updateUpdate mbake to the latest version.
# Update via pip
mbake update
# Equivalent to: pip install --upgrade mbake~/.bake.tomlCreate and edit ~/.bake.toml to customize mbake behavior:
# ~/.bake.toml - mbake configuration
# Add spaces around = in variable assignments
# Example: VAR = value (instead of VAR=value)
space_around_assignment = true
# Add space after : in target definitions
# Example: target : prerequisites (instead of target: prerequisites)
space_after_colon = true
# Normalize line continuation characters (backslashes)
# Removes trailing spaces before \ and ensures proper continuation
normalize_line_continuations = true
# Remove trailing whitespace from all lines
remove_trailing_whitespace = true
# Fix missing tabs in recipes (convert spaces to tabs)
# This is critical - Makefiles MUST use tabs for recipes
fix_missing_recipe_tabs = true
# Automatically detect and insert .PHONY declarations
# Analyzes recipes to identify phony targets (clean, test, etc.)
auto_insert_phony_declarations = true
# Group multiple .PHONY declarations into single declaration
# .PHONY: clean test (instead of two separate lines)
group_phony_declarations = true
# Place .PHONY declarations at the top of the file
# If false, keeps them near their target definitions
phony_at_top = falseCreate .bake.toml in your project root:
# Project-specific mbake settings
# These override ~/.bake.toml for this project
space_around_assignment = false # Compact style for this project
auto_insert_phony_declarations = true
phony_at_top = truePriority:
.bake.toml in current directory (highest)~/.bake.toml in home directory| Option | Type | Default | Description |
|---|---|---|---|
space_around_assignment | bool | true | Add spaces around = |
space_after_colon | bool | true | Add space after : |
normalize_line_continuations | bool | true | Clean backslash continuations |
remove_trailing_whitespace | bool | true | Remove end-of-line spaces |
fix_missing_recipe_tabs | bool | true | Convert spaces to tabs in recipes |
auto_insert_phony_declarations | bool | true | Auto-detect and add .PHONY |
group_phony_declarations | bool | true | Combine .PHONY lines |
phony_at_top | bool | false | Place .PHONY at file start |
Automatically converts spaces to tabs in recipe sections.
# Before (spaces - invalid!)
build:
echo "Building..."
go build -o app
# After (tabs - correct!)
build:
echo "Building..."
go build -o appConsistent spacing around assignments.
# Before (inconsistent)
VAR1=value
VAR2 =value
VAR3= value
VAR4 = value
# After (consistent)
VAR1 = value
VAR2 = value
VAR3 = value
VAR4 = valueStandardizes spacing after target colons.
# Before
target1:prerequisites
target2 :prerequisites
target3: prerequisites
# After
target1: prerequisites
target2: prerequisites
target3: prerequisitesAutomatically identifies phony targets by analyzing recipes.
# Before
clean:
rm -rf build
test:
go test ./...
install:
cp app /usr/local/bin/
# After
.PHONY: clean test install
clean:
rm -rf build
test:
go test ./...
install:
cp app /usr/local/bin/Detection Logic:
rm, mkdir, echo commands → Phonynpm, go test, docker commands → Phonycurl, ssh, scp commands → PhonyCleans up line continuation characters.
# Before (trailing space after \, inconsistent)
SOURCES = main.c \
utils.c\
config.c \
# After (consistent, no trailing spaces)
SOURCES = main.c \
utils.c \
config.cRemoves all trailing spaces and tabs.
# Before (invisible trailing spaces marked with ·)
VAR = value···
build:···
echo "test"··
# After (clean)
VAR = value
build:
echo "test"Validates Makefile syntax before and after formatting.
mbake format --validate MakefileValidation Process:
make --dry-runSelectively disable formatting for specific sections.
# Standard formatting applies here
VAR1=value
target1:prerequisites
# bake-format off
# Preserve legacy formatting in this section
VAR2 = value
target2 : prerequisites
echo "custom spacing"
# bake-format on
# Standard formatting resumes
VAR3=value
target3:prerequisitesUse cases:
name: Validate Makefiles
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install mbake
run: pip install mbake
- name: Check Makefile formatting
run: mbake format --check Makefile
- name: Validate Makefile syntax
run: mbake validate Makefile
- name: Check all .mk files
run: |
for file in $(find . -name "*.mk" -o -name "Makefile"); do
echo "Checking $file..."
mbake format --check "$file"
mbake validate "$file"
done# .gitlab-ci.yml
validate-makefiles:
image: python:3.11
stage: test
before_script:
- pip install mbake
script:
- find . -name "Makefile" -o -name "*.mk" | while read file; do
echo "Validating $file";
mbake format --check "$file";
mbake validate "$file";
done
only:
- merge_requests
- mainInstall as a pre-commit hook:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: mbake-format
name: mbake format
entry: mbake format --check
language: system
files: (Makefile|.*\.mk)$
- id: mbake-validate
name: mbake validate
entry: mbake validate
language: system
files: (Makefile|.*\.mk)$Install and use:
# Install pre-commit
pip install pre-commit
# Install hooks
pre-commit install
# Run manually
pre-commit run --all-filesAdd to your Makefile:
# Self-validation targets
.PHONY: format-check format-fix validate-makefile
format-check:
@echo "Checking Makefile formatting..."
@mbake format --check $(MAKEFILE_LIST)
format-fix:
@echo "Applying formatting to Makefile..."
@mbake format $(MAKEFILE_LIST)
validate-makefile:
@echo "Validating Makefile syntax..."
@mbake validate $(MAKEFILE_LIST)
# Run all checks
.PHONY: check
check: format-check validate-makefile
@echo "All checks passed!"Usage:
# Check formatting and syntax
make check
# Auto-fix formatting
make format-fix
# Validate only
make validate-makefileInstall "mbake Makefile Formatter" from marketplace.
Features:
Add to .vscode/settings.json:
{
"[makefile]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "mbake.mbake-formatter",
"editor.insertSpaces": false,
"editor.detectIndentation": false,
"editor.tabSize": 8
},
"mbake.validateOnSave": true,
"mbake.autoFixOnSave": false
}Add to .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "mbake: Format Makefile",
"type": "shell",
"command": "mbake",
"args": ["format", "${file}"],
"problemMatcher": []
},
{
"label": "mbake: Validate Makefile",
"type": "shell",
"command": "mbake",
"args": ["validate", "${file}"],
"problemMatcher": []
},
{
"label": "mbake: Check Format",
"type": "shell",
"command": "mbake",
"args": ["format", "--check", "${file}"],
"problemMatcher": []
}
]
}Add to .vimrc or init.vim:
" Format Makefile with mbake
autocmd FileType make nnoremap <buffer> <leader>f :!mbake format %<CR>:e<CR>
" Validate Makefile
autocmd FileType make nnoremap <buffer> <leader>v :!mbake validate %<CR>
" Check format
autocmd FileType make nnoremap <buffer> <leader>c :!mbake format --check %<CR>
" Ensure tabs in Makefiles
autocmd FileType make setlocal noexpandtab tabstop=8 shiftwidth=8Add to .emacs or init.el:
;; mbake formatting for Makefiles
(defun mbake-format-buffer ()
"Format current Makefile with mbake."
(interactive)
(shell-command (format "mbake format %s" (buffer-file-name)))
(revert-buffer t t t))
(defun mbake-validate-buffer ()
"Validate current Makefile with mbake."
(interactive)
(compile (format "mbake validate %s" (buffer-file-name))))
;; Key bindings
(add-hook 'makefile-mode-hook
(lambda ()
(local-set-key (kbd "C-c f") 'mbake-format-buffer)
(local-set-key (kbd "C-c v") 'mbake-validate-buffer)))# Format all Makefiles in project
find . -name "Makefile" -o -name "*.mk" | xargs mbake format
# Check all files without modifying
find . -name "Makefile" -o -name "*.mk" | xargs mbake format --check
# Create backups of all files
find . -name "Makefile" -o -name "*.mk" | while read file; do
mbake format --backup "$file"
done# Format only specific files
mbake format Makefile build.mk test.mk
# Format with pattern
mbake format **/*.mk
# Exclude certain files
find . -name "*.mk" ! -name "legacy.mk" | xargs mbake format# 1. Review changes before applying
mbake format --diff Makefile > changes.diff
# 2. Review the diff
less changes.diff
# 3. If satisfied, apply
mbake format Makefile
# 4. Validate result
mbake validate Makefile# Check if formatting is needed before commit
git diff --cached --name-only | grep -E '(Makefile|.*\.mk)$' | while read file; do
if ! mbake format --check "$file"; then
echo "Error: $file needs formatting"
echo "Run: mbake format $file"
exit 1
fi
done# Refactor entire codebase
#!/bin/bash
echo "Refactoring all Makefiles..."
find . -type f \( -name "Makefile" -o -name "*.mk" \) | while read file; do
echo "Processing: $file"
# Backup
cp "$file" "$file.backup"
# Format
if mbake format "$file"; then
echo " ✓ Formatted"
else
echo " ✗ Format failed"
mv "$file.backup" "$file"
continue
fi
# Validate
if mbake validate "$file"; then
echo " ✓ Validated"
rm "$file.backup"
else
echo " ✗ Validation failed - reverting"
mv "$file.backup" "$file"
fi
done
echo "Refactoring complete!"# Problem: mbake not in PATH
$ mbake format Makefile
bash: mbake: command not found
# Solution: Ensure pip install directory is in PATH
export PATH="$HOME/.local/bin:$PATH"
# Or use python -m
python3 -m mbake format Makefile# Problem: Validation fails after formatting
$ mbake format --validate Makefile
Error: Syntax validation failed
# Solution: Check format disable comments
# Look for unclosed # bake-format off sections
grep -n "bake-format" Makefile
# Or restore from backup
cp Makefile.bak Makefile# Problem: Settings in .bake.toml ignored
$ mbake format Makefile
# Formatting doesn't match config
# Solution: Verify config file location
mbake config
# Or specify config explicitly
mbake format --config .bake.toml Makefile# Problem: Cannot write to file
$ mbake format Makefile
Error: Permission denied
# Solution: Check file permissions
ls -l Makefile
chmod u+w Makefile# Problem: Wrong Python version
$ pip install mbake
ERROR: mbake requires Python '>=3.9'
# Solution: Use correct Python version
python3.11 -m pip install mbake
# Or use pyenv
pyenv install 3.11
pyenv local 3.11
pip install mbake# Enable verbose output (if supported in future versions)
MBAKE_DEBUG=1 mbake format Makefile
# Check Python environment
python3 -c "import mbake; print(mbake.__version__)"
# Validate manually
make -f Makefile --dry-runmbake uses standard exit codes:
| Code | Meaning | Commands |
|---|---|---|
| 0 | Success / No changes needed | All commands |
| 1 | Formatting needed / Validation failed | format --check, validate |
| 2 | Error occurred | All commands |
Usage in Scripts:
# Check formatting
if mbake format --check Makefile; then
echo "Formatting OK"
else
echo "Needs formatting"
exit 1
fi
# Validate
mbake validate Makefile || {
echo "Validation failed!"
exit 1
}--diff before applying formatting--backup for important files--validate flag# bake-format off comments.bake.tomlcheckmake is a complementary linter that can be used alongside mbake for additional coverage.
# With Go (1.16+)
go install github.com/checkmake/checkmake/cmd/checkmake@latest
# Docker
docker run --rm -v $(pwd):/data checkmake/checkmake Makefile# Basic linting
checkmake Makefile
# List available rules
checkmake list-rules
# JSON output
checkmake --output json Makefile
# With config file
checkmake --config checkmake.ini Makefile# Makefile validation target
.PHONY: lint
lint:
@echo "Running mbake..."
mbake format --check Makefile
mbake validate Makefile
@echo "Running checkmake..."
checkmake Makefile || true
@echo "Lint complete!"# GitHub Actions example
- name: Lint Makefile
run: |
pip install mbake
go install github.com/checkmake/checkmake/cmd/checkmake@latest
mbake format --check Makefile
mbake validate Makefile
checkmake Makefile--dry-run supportmbake is released under the MIT License.
Note: This documentation covers mbake as used by the makefile-validator skill. For the latest features and updates, visit the official GitHub repository.
Install with Tessl CLI
npx tessl i pantheon-ai/makefile-validator@0.1.0