Skip to main content

C++ multi-file merge & code golf / minifier tool

Project description

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, endl replacement, inline removal, and trailing return 0; removal in main.
  • 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cppgolf-0.1.10.tar.gz (77.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cppgolf-0.1.10-py3-none-any.whl (61.7 kB view details)

Uploaded Python 3

File details

Details for the file cppgolf-0.1.10.tar.gz.

File metadata

  • Download URL: cppgolf-0.1.10.tar.gz
  • Upload date:
  • Size: 77.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for cppgolf-0.1.10.tar.gz
Algorithm Hash digest
SHA256 bddbb79a0b0e79bd84487e04a0ddee950b9973a7adffbfe5dd5bc7c3349dc038
MD5 35ae45a17d3c9cfb0be203a2d551c398
BLAKE2b-256 9bbf1c8557df2182c517dfc37bf094b9773e6f87eb0850f9f57e9d4953a1cd30

See more details on using hashes here.

File details

Details for the file cppgolf-0.1.10-py3-none-any.whl.

File metadata

  • Download URL: cppgolf-0.1.10-py3-none-any.whl
  • Upload date:
  • Size: 61.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for cppgolf-0.1.10-py3-none-any.whl
Algorithm Hash digest
SHA256 a6c15b8254fa15ca32acf5959b175a997e4fa80b26f68a4a4cfc3af531da3044
MD5 e6bdbc946c5dba381074b4655d8f21ac
BLAKE2b-256 d9c3d4eaad7a18fc997ff37852b0fbff0246d6cc27cfd6ef44e64cfd55ed9d62

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page