Registry / serialization / pcpp
library1.30pypypi✓ verified 84d ago

PCPP is a pure Python implementation of a C99 preprocessor. It's designed to preprocess C and C++ source code, handling directives like `#include`, `#define`, and conditional compilation. A key use case is for processing header-only C++ libraries into single-file includes and for integration with documentation tools like Doxygen. The library is actively maintained, though with an infrequent release cadence, with the latest significant update in late 2021.

pip install pcpp
INSTALL
IMPORT
SIG · PCPP
P
pcpp
serializationpythonv1.30
Install
1.6s avg
Import
45ms
Disk
17MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v1.30 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.047s · 18.4MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 1.6s · import 0.044s · 19MB
17MB installed
● package 17MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Preprocessor
from pcpp.preprocessor import Preprocessor
The primary class for C preprocessor operations.

This quickstart demonstrates how to instantiate the `Preprocessor` class, define custom macros, feed it C source code, and retrieve the preprocessed output. The `parse` method takes a file-like object, and `stream` returns an iterator of tokens which can be joined to form the final string.

from pcpp.preprocessor import Preprocessor import io # Example C code as a string c_code = ''' #define MY_MACRO "Hello, World!" #define VERSION 10 #if VERSION > 5 const char* message = MY_MACRO; #else const char* message = "Old version"; #endif int main() { printf("%s\n", message); return 0; } ''' # Create a Preprocessor instance p = Preprocessor() # Define additional macros (optional) p.define("DEBUG") # Prepare input stream (from string or file) input_stream = io.StringIO(c_code) # Parse and preprocess the input p.parse(input_stream) # Get the preprocessed output output = p.stream() # You can iterate through the tokens or get the full string output processed_code = ''.join(str(x) for x in output) print(processed_code) # Expected output for VERSION=10 and DEBUG defined: # const char* message = "Hello, World!"; # # int main() { # printf("%s\n", message); # return 0; # }
Debug
Known issues
breakingIn v1.21, the paths emitted by `pcpp` into `#line` directives became relative to the working directory where the `Preprocessor` was initialized. Previously, these might have been absolute or behaved differently.
fix
If relying on `#line` directives for debugging or tools, ensure your build system or downstream tools are aware of and correctly interpret relative paths. Adjust expectations for `__FILE__` and `__LINE__` macros accordingly.
affects: >=1.21
gotchaStarting with v1.20, `pcpp` no longer collapses whitespace in the output by default. If your application expects compact output, you must explicitly enable compression.
fix
When using the command-line tool, use the `--compress` option. When using the API, check for a corresponding `compress` attribute or method on the `Preprocessor` instance (consult the documentation for exact API usage).
affects: >=1.20
gotchaSpecial C preprocessor 'magic' macros like `__DATE__`, `__TIME__`, `__FILE__`, `__LINE__`, and `__COUNTER__` have specific handling. By default, `pcpp` might expand these, but if you need them passed through unexpanded (e.g., for Doxygen), specific options are required.
fix
Use the `passthru_magic_macros` option when initializing `Preprocessor` or the `--passthru-magic-macros` command-line argument if you want these macros to remain unexpanded in the output.
affects: All
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'pcpp'
The 'pcpp' library is not installed in the current Python environment.
fix
Ensure the library is installed using pip: `pip install pcpp`
FileNotFoundError: No such file or directory: 'some_header.h'
The preprocessor could not find an included file (e.g., via `#include <some_header.h>` or `#include "some_header.h"`) because its directory was not added to the search paths.
fix
Add the directory containing the header file to the preprocessor's include paths using `p.add_path('/path/to/headers')` or the `-I` command-line option. Relative paths are often resolved from the current working directory, but explicit paths are robust.
SyntaxError: invalid preprocessor expression in #if/#elif directive
The C preprocessor expression within an `#if` or `#elif` directive is malformed or uses constructs not supported by C99, leading to a parsing error.
fix
Review the expression for correct C99 preprocessor syntax. Ensure all macros used in the expression are defined or handle undefined macros gracefully. PCPP v1.30 improved expression evaluation with a yacc-based parser, fixing many issues from older `eval()`-based approaches.
Upgrade
Version history
1.30latest on PyPI · released Oct 29, 2021
Audit
Dependencies
plyrequiredUsed for parsing C preprocessor expressions with its yacc module, fundamental to PCPP's core functionality.
Agent activity
11 hits · last 30 days
node
10
Resources
pcpp — pip install pcpp · libregistry