Recommended Free Tools
To parse C with pycparser, preprocess the source first, then make sure the preprocessor can find headers that provide the macros and typedef names needed by the parser. For standard C headers, the practical shortcut is pycparser’s bundled utils/fake_libc_include directory: its minimal declarations usually provide enough information to build an AST without parsing every detail of your system’s C library.
Why pycparser needs preprocessed C
pycparser.CParser parses C syntax; it does not itself interpret directives such as #include and #define. Its parser expects preprocessed input. Run a preprocessor such as cpp, gcc -E, or clang -E, or use pycparser.parse_file to have pycparser invoke a preprocessor. The preprocessor expands includes and macros and removes comments before parsing.
This matters because C syntax depends on typedef names. In a declaration such as T *x;, the parser must know whether T names a type; macros can also affect how the tokens are interpreted. The parser needs enough declaration information to recognize type names, but ordinary AST construction does not require the full semantic contents of every included header.
What fake headers do—and what they leave out
A fake header is a small replacement for a real header. It preserves the macros and typedefs that affect parsing while omitting implementation details the parser does not need. If all that matters is that T is a type name, a complicated original typedef may be represented by a simple declaration such as typedef int T;.
#1 Best Overall
This is useful when analyzing source, traversing its AST, or rewriting it. A fake declaration can let the parser recognize a type without reproducing the actual structure layout or full library API. The trade-off is that the resulting AST is not a complete account of the real header’s semantics.
Use pycparser’s fake standard-library headers
For standard C library includes, add pycparser’s utils/fake_libc_include directory to the preprocessor’s include search path. The pycparser README describes these as minimal standard headers containing the bare necessities for parsing; their smaller size can also avoid the overhead of processing large real system headers. See the pycparser v2.20 README.
A basic command-line workflow is:
gcc -E -I<project-headers> -I<pycparser>/utils/fake_libc_include source.c > source_pp.c
python -c "import pycparser; pycparser.parse_file('source_pp.c')"
Replace the angle-bracketed paths with real directories on your system. If preprocessing reports a missing project header, add the directory containing it with another -I option. The same general approach works with clang -E or cpp; exact flags depend on the preprocessor and project.
Adjust include paths and extensions for real projects
Large projects often need their own include directories in addition to fake libc headers. Eli Bendersky’s Redis walkthrough illustrates the sequence: add the project’s source include directory, add the fake libc directory, and add dependency include directories when needed. For Redis’s Lua dependency, that meant including redis/deps/lua/src. The walkthrough is in On Parsing C, Type Declarations and Fake Headers.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
If the compiler continues to pull in host system headers, -nostdinc prevents it from searching its built-in standard include directories. This is useful when you intend to use the fake headers instead of the machine’s real libc headers. Some code also uses compiler-specific syntax that pycparser cannot parse directly. In the Redis example, GNU __attribute__ syntax was removed for preprocessing with -D'__attribute__(x)='.
gcc -nostdinc -E -D'__attribute__(x)='
-I<project-headers>
-I<dependency-headers>
-I<pycparser>/utils/fake_libc_include
source.c > source_pp.c
python -c "import pycparser; pycparser.parse_file('source_pp.c')"
Only use the extension-removal macro when it matches the code you need to parse. Preprocessor substitutions can change the input, so preserve the definitions that affect the syntax or declarations relevant to your analysis.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Choose fake or real headers based on the result you need
| Approach | Best suited to | Main trade-off |
|---|---|---|
| Fake headers | AST construction, source analysis, or rewriting when the required macros and typedef names are known. | They omit semantic details such as complete struct definitions, accurate function declarations, and field availability. |
| Real headers or a more complete compatibility layer | Work that depends on complete declarations or compiler-like semantic analysis. | More implementation-specific headers and extensions must be handled, and preprocessing may require platform-specific configuration. |
Fake headers are not a substitute for a compiler frontend when the task depends on whether a field truly exists, the exact declaration of a function, or the complete definition of a structure. For that kind of semantic completeness, use real headers or a more complete compatibility layer and account for the target platform’s extensions.
Quick Recap
Best Value
Troubleshoot common parsing failures
- Preprocessor directives appear in parser input: preprocess the file with
gcc -E,clang -E, orcpp, or configureparse_fileto invoke a preprocessor. - A type name is rejected or parsed incorrectly: check that the relevant typedef is visible before its use and that the right header or fake declaration was included.
- An include file cannot be found: add the directory containing that project or dependency header with
-I. - Host system headers appear despite using fake libc: try
-nostdinc, then explicitly supply the project and fake-header include paths needed for preprocessing. - Compiler extensions cause syntax errors: identify the specific extension and handle it in preprocessing, as with the Redis example’s
__attribute__substitution. Avoid removing syntax that your analysis needs to preserve. - Parsing succeeds but declarations are incomplete: that is the expected limit of a minimal fake header; provide fuller declarations if the analysis needs semantic details.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

