CPPGolf
cppgolf is a C/C++ multi-file merge and code-golf/minifier tool.
Install
pip install cppgolf
libclang-backed features such as symbol renaming, type renaming, and static deduplication are optional at runtime. The base CLI and text transforms work without clang.cindex.
CLI
cppgolf solution.cpp
cppgolf solution.cpp -o golf.cpp
cppgolf solution.cpp --merge-only -I include/
cppgolf solution.cpp -DDEBUG=1 --inject-define --merge-only
cppgolf solution.cpp -I include/ --rename-functions --stats
cppgolf solution.cpp -DBOTZONE_PIKAFISH_STANDALONE=1 -DZSTD_DISABLE_ASM
cppgolf solution.cpp --no-rename
cppgolf solution.cpp --config cppgolf.toml --flatten-cfg
Common options
| Option | Meaning |
|---|---|
-o FILE |
Write output to a file instead of stdout. |
-I DIR |
Add an include search directory. Can be repeated. |
-D MACRO[=VALUE] |
Pass a macro definition to libclang-backed optional passes. Can be repeated. |
--inject-define |
Write -D macro definitions into the generated source code. |
--merge-only |
Only merge files. Skip all later transforms and compression passes. |
--no-merge |
Skip inlining #include "...". |
--no-strip-comments |
Keep comments. |
--no-compress-ws |
Keep whitespace formatting. |
--no-std-ns |
Do not add using namespace std;. |
--no-typedefs |
Do not add shortcuts such as ll / ld. |
--no-rename |
Disable symbol renaming. |
--no-win-lean |
Do not inject Windows header conflict guards. |
--keep-main-return |
Keep the trailing return 0; in main. |
--keep-endl |
Keep endl. |
--keep-inline |
Keep inline. |
--dedup-statics |
Deduplicate merged static definitions with libclang. |
--aggressive |
Remove braces from single-statement if / for / while. |
--shortcuts |
Insert #define shortcuts for frequent cout / cin. |
--rename-functions |
Also rename user-defined functions and methods. |
--rename-type |
Add typedef aliases for long user-defined type names. |
--config PATH |
Read cppgolf options from a TOML config file. |
--cfg-helper PATH |
Explicitly use the required cppgolf-cfg-helper executable for CFG flattening. |
--cfg-helper-include PATH |
Add a system/cross-platform header directory used only by the CFG helper parser. Can be repeated. |
--flatten-cfg |
Flatten configured function bodies into a switch-based state machine. |
--flatten-cfg-function NAME |
Add an exact function name for control-flow flattening. |
--flower |
Insert both dead-code and declaration flowers. |
--flower-dead-code |
Insert only complex always-false dead-code blocks in function bodies. |
--flower-decls |
Insert only inert global/namespace/class declarations. |
--flower-function NAME |
Limit dead-code flower insertion to an exact function name. Can be repeated. |
--flower-seed N |
Set the deterministic flower seed. |
--flower-dead-blocks N |
Maximum dead-code flower blocks per function. |
--flower-decl-count N |
Maximum inert declarations to insert. |
--stats |
Print size reduction statistics to stderr. |
Configuration
Control-flow flattening is an obfuscation pass and can increase code size. It is disabled by default and only touches configured functions.
[flatten_cfg]
enabled = true
helper = "build/cfg-helper/cppgolf-cfg-helper.exe"
helper_includes = ["C:/msys64/usr/include"]
functions = [
"evaluate",
"Stockfish::Search::Worker::search",
"Stockfish::Tablebases::probe",
]
exclude = ["main"]
Flower insertion is also disabled by default. It uses the same cppgolf-cfg-helper parser as CFG flattening to find safe insertion points.
[flower]
enabled = true
dead_code = true
declarations = true
functions = ["target", "N::Box::run"]
exclude = ["main"]
seed = 1
dead_blocks_per_function = 1
declaration_count = 24
When --flatten-cfg, [flatten_cfg].enabled, --flower, or [flower].enabled is active, cppgolf-cfg-helper is required. cppgolf searches for it in this order: explicit --cfg-helper / Python API path, TOML flatten_cfg.helper, CPPGOLF_CFG_HELPER, build/cfg-helper/cppgolf-cfg-helper(.exe) under the current working directory, the same path under the package repository root, then PATH.
For cross-platform flattening, pass target headers to the helper parser with --cfg-helper-include or flatten_cfg.helper_includes. When an MSYS /usr/include directory such as C:/msys64/usr/include is provided, cppgolf automatically uses the matching MSYS GCC include bundle and x86_64-pc-msys target for helper parsing.
Build the helper with normal LLVM/Clang CMake package discovery:
cmake -S tools/cfg-helper -B build/cfg-helper -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_DIR=/path/to/llvm/lib/cmake/llvm \
-DClang_DIR=/path/to/llvm/lib/cmake/clang
cmake --build build/cfg-helper --config Release
If LLVM is installed in a standard prefix, CMAKE_PREFIX_PATH=/path/to/llvm or llvm-config --cmakedir can also be used to locate the packages.
Python API
from pathlib import Path
from cppgolf import process
result, merged_size = process(
Path("solution.cpp"),
include_dirs=[],
defines=["BOTZONE_PIKAFISH_STANDALONE=1"],
inject_defines=False,
merge_only=False,
rename_symbols=False,
flatten_cfg=False,
flatten_cfg_functions=[],
flower=False,
flower_seed=1,
cfg_helper_path=None,
)
print(merged_size)
print(result)
Individual passes can also be used directly:
from cppgolf import compress_whitespace, strip_comments
from cppgolf.transforms import golf_typedefs
code = Path("a.cpp").read_text()
code = strip_comments(code)
code = golf_typedefs(code)
code = compress_whitespace(code)
Features
- Merge local
#include "..."files recursively and deduplicate top-level system headers. - Strip comments while preserving strings, character literals, and raw strings.
- Apply safe default text transforms such as
std::removal, typedef shortcuts,endlreplacement,inlineremoval, and trailingreturn 0;removal inmain. - Compress whitespace at token granularity while preserving preprocessor line structure.
- Optionally rename symbols and user-defined types with libclang.
- Optionally flatten configured function bodies with the required Clang CFG helper.
Metadata
Release files for cppgolf 0.1.10
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cppgolf-0.1.10.tar.gz | 77.4 kB | Without provenance | Details for cppgolf-0.1.10.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cppgolf-0.1.10-py3-none-any.whl | Python 3 | none | any | Details for cppgolf-0.1.10-py3-none-any.whl |
Total release size: 139.1 kB
Release files / cppgolf-0.1.10.tar.gz
| Download URL | cppgolf-0.1.10.tar.gz |
|---|---|
| Size | 77.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bddbb79a0b0e79bd84487e04a0ddee950b9973a7adffbfe5dd5bc7c3349dc038
|
|
BLAKE2b-256 checksum How to use checksums |
9bbf1c8557df2182c517dfc37bf094b9773e6f87eb0850f9f57e9d4953a1cd30
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.9
|
Release files / cppgolf-0.1.10-py3-none-any.whl
| Download URL | cppgolf-0.1.10-py3-none-any.whl |
|---|---|
| Size | 61.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a6c15b8254fa15ca32acf5959b175a997e4fa80b26f68a4a4cfc3af531da3044
|
|
BLAKE2b-256 checksum How to use checksums |
d9c3d4eaad7a18fc997ff37852b0fbff0246d6cc27cfd6ef44e64cfd55ed9d62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.9
|
Security for cppgolf 0.1.10
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.