yacd - Yet Another CompileDB

yacd (Yet Another CompileDB) is a command-line tool for generating compile_commands.json files from make logs of makefile-based projects. This tool is specifically designed for C/C++ projects and is particularly useful for embedded development and cross-compilation environments.
About the Name
Although it's called yacd, it's not yacc's younger brother! :)
Developed with Qoder
This tool was heavily implemented with the participation of Qoder (https://qoder.com/).
Features
- π Efficient Parsing: Fast parsing of logs generated by
make -Bnkw
- π― Precise Recognition: Smart identification of compilation commands, supporting multiple compilers (GCC, Clang, ARM toolchains, etc.)
- π Path Handling: Support for both absolute and relative paths, with automatic working directory tracking
- π§ Flexible Input: Multiple input methods - file input, direct make command execution, and standard input pipes
- π Real-time Processing: Execute make commands directly and process output without intermediate files
- β
Standards Compliant: Generates JSON files compliant with Language Server Protocol standards
- π§ͺ High Quality: Comprehensive unit test coverage ensuring code quality
Installation
Build from Source
Ensure you have Go 1.23 or higher installed.
git clone https://github.com/gerryqd/yacd.git
cd yacd
go build -o yacd .
Using Go Install
go install github.com/gerryqd/yacd@latest
Using Makefile
make build
Usage
Basic Usage
yacd supports three input methods:
- First, generate a make log:
make -Bnkw > build.log 2>&1
- Use yacd to generate compile_commands.json:
yacd -i build.log -o compile_commands.json
Method 2: Direct Make Command Integration
# Execute make command directly and process output
yacd -n "make clean all" -o compile_commands.json
yacd --dry-run "make" --verbose
# Read from stdin using pipe
make -Bnkw | yacd -o compile_commands.json
yacd < build.log -o compile_commands.json
Command Line Options
yacd [flags]
Flags:
-i, --input string Input make log file path
-n, --dry-run string Execute make command with -Bnkw flags and process output directly
-o, --output string Output compile_commands.json file path (default "compile_commands.json")
-r, --relative Use relative paths instead of absolute paths
-b, --base-dir string Base directory path (used with --relative)
-v, --verbose Verbose output
-h, --help Show help information
Examples
# Generate make log and process with yacd
make -Bnkw > build.log 2>&1
yacd -i build.log -o compile_commands.json -v
Direct Make Integration
# Execute make command directly
yacd -n "make clean all" -o compile_commands.json --verbose
yacd --dry-run "make" -o compile_commands.json
# Use pipe to process make output directly
make -Bnkw | yacd -o compile_commands.json --verbose
echo "sample make output" | yacd -o compile_commands.json
Using Relative Paths
yacd -i build.log -o compile_commands.json --relative --base-dir /project/root
Embedded Projects
# For ARM projects using direct integration
yacd -n "make CROSS_COMPILE=arm-none-eabi-" -o compile_commands.json --verbose
Supported Compilers
yacd supports automatic recognition of compilers using a simplified pattern matching approach. It can identify any compiler command containing the following patterns:
gcc (includes cross-compilers like arm-none-eabi-gcc, aarch64-linux-gnu-gcc)
g++ (includes cross-compilers like arm-none-eabi-g++)
clang
clang++
cc
This simplified approach is more universal and automatically supports various cross-compilation toolchains without requiring specific prefix definitions.
The generated compile_commands.json file complies with the Clang compilation database standard:
[
{
"directory": "/home/user/project",
"command": "arm-none-eabi-gcc -c -mcpu=cortex-m0 -mthumb -DNDEBUG main.c -o main.o",
"file": "/home/user/project/main.c",
"output": "/home/user/project/main.o"
}
]
Development
Project Structure
yacd/
βββ cmd/ # Command-line interface
βββ generator/ # JSON generator
βββ parser/ # Log parser
βββ types/ # Type definitions
βββ utils/ # Utility functions
β βββ errorutil/ # Error handling utilities
β βββ pathutil/ # Path handling utilities
βββ scripts/ # Helper scripts
βββ .github/workflows/ # CI/CD configuration
βββ Makefile # Build configuration
βββ go.mod # Go module definition
βββ go.sum # Go module checksums
βββ main.go # Application entry point
βββ README.md # Project documentation
βββ LICENSE # License file
Build and Test
# Format code
make fmt
# Static analysis
make vet
# Run tests
make test
# Generate test coverage report
make test-coverage
# Build binary
make build
# Show sample usage examples
make run
# Show all available commands
make help
Code Quality Checks
Run comprehensive code quality checks:
./scripts/quality-check.sh
This script performs the following checks:
- Code formatting verification
- Static analysis
- Compilation checks
- Unit tests
- Test coverage
- Module dependency verification
- Race condition detection
VSCode and clangd
The generated compile_commands.json can be directly used with VSCode's C/C++ extension and clangd:
- Place the generated file in the project root directory
- VSCode will automatically recognize it and provide intelligent code completion, navigation, and other features
CMake Projects
While CMake can natively generate compilation databases, yacd is still useful for hybrid build systems:
# For CMake projects using make backend
cmake --build . -- -Bnkw > build.log 2>&1
yacd -i build.log -o compile_commands.json
FAQ
Q: Why parse make logs instead of modifying Makefiles?
A: Parsing logs requires no modification to existing build systems, making it minimally invasive and particularly suitable for third-party projects or complex build environments that cannot be modified.
A: Yes, yacd is cross-platform and can run on Windows, Linux, and macOS. It supports three input methods: file input (-i), direct make command execution (-n), and standard input pipes.
Q: How does it handle complex Makefile include relationships?
A: yacd correctly handles working directory changes by tracking make's "Entering directory" and "Leaving directory" messages.
Q: Why do generated files contain absolute paths?
A: Absolute paths are used by default to ensure compatibility. Use the --relative option if you need relative paths.
A: Yes! Use the -n/--dry-run option to execute make commands directly, or use pipes to process make output in real-time: make -Bnkw | yacd -o compile_commands.json.
yacd has been optimized for performance:
- High memory efficiency, suitable for processing build logs from large projects
- Fast parsing speed, typically processing thousands of log lines per second
- Streaming processing support with stable memory usage
Contributing
We welcome contributions of all kinds!
- Fork the project
- Create a feature branch (
git checkout -b feature/amazing-feature)
- Commit your changes (
git commit -m 'Add some amazing feature')
- Push to the branch (
git push origin feature/amazing-feature)
- Create a Pull Request
Contribution Guidelines
- Ensure code passes all tests
- Add appropriate tests for new features
- Follow Go coding standards
- Update relevant documentation
License
This project is licensed under the MIT License. See the LICENSE file for details.
Acknowledgments
- Thanks to spf13/cobra for the excellent command-line framework
- Inspired by the design concepts from the bear project
- Thanks to compiledb-go for reference and inspiration
- Thanks to all contributors and users for their support
If you find this project useful, please give us a β star!
For any questions or suggestions, feel free to submit an issue.