CPP(1)
π cpp, the C Preprocessor π
manual page CPP(1), GNU π
β¨ NAME β¨
okay so the whole thing is called cpp, and it's The C Preprocessor π
β¨ SYNOPSIS β¨
cpp [-Dmacro[=defn]...] [-Umacro]
[-Idir...] [-iquotedir...]
[-M|-MM] [-MG] [-MF filename]
[-MP] [-MQ target...]
[-MT target...]
infile [[-o] outfile]
Only the most useful options are shown up top π For the fuller list of preprocessor-specific options, keep scrolling. cpp also takes most gcc driver options, which aren't listed here, so for those you'll want the GCC documentation.
β¨ DESCRIPTION β¨
The C preprocessor, aka cpp, is a macro processor π¦ The C compiler uses it automatically to transform your program before compilation. It's called a macro processor because you can define macros, which are short abbreviations for longer constructs.
The C preprocessor is meant for C, C++, and Objective-C source code only. People have historically abused it as a general text processor, and it's giving chaos π It will choke on input that doesn't follow C's lexical rules. For example, apostrophes get read as the start of character constants, and that causes errors. You also can't count on it keeping anything about the input that doesn't matter to C-family languages. If you preprocess a Makefile, all the hard tabs get removed, and the Makefile will not work.
β οΈ Preprocessing a Makefile strips every hard tab, so the Makefile will not work afterwards. Don't do that to your Makefile, bestie π
Having said that, you can sometimes get away with running cpp on things that aren't C π§ Other Algol-ish languages are often safe (Ada, etc.). Assembly is also fine, but be careful. -traditional-cpp mode keeps more white space and is otherwise more permissive. A lot of the problems go away if you write C or C++ style comments instead of native language comments, and keep your macros simple.
Whenever you can, use a preprocessor built for the language you're writing in π Modern versions of the GNU assembler have macro facilities. Most high-level languages have their own conditional compilation and inclusion mechanisms. If all else fails, reach for a true general text processor, like GNU M4.
C preprocessors vary a little from one another. This manual covers the GNU C preprocessor, which gives you a small superset of ISO Standard C features. In its default mode, the GNU C preprocessor skips a few things the standard requires. These are features that are rarely, if ever, used, and skipping them can change the meaning of a program that expects them, which is lowkey a plot twist π If you want strict ISO Standard C, use -std=c90, -std=c99, -std=c11 or -std=c17, depending on which version of the standard you're going for. To get all the mandatory diagnostics, you also have to add -pedantic.
This manual describes how the ISO preprocessor behaves. To cut down on random differences, the traditional preprocessor should act the same way wherever the ISO behaviour doesn't clash with traditional semantics. The differences that do exist are spelled out in the section Traditional Mode β¨
For clarity, unless noted otherwise, any mention of CPP in this manual means GNU CPP πΈ
β¨ OPTIONS β¨
The cpp command takes two file names as arguments, infile and outfile π The preprocessor reads infile, along with any other files it pulls in with #include. Everything the combined input files produce gets written to outfile.
Either infile or outfile can be -. As infile, it means read from standard input. As outfile, it means write to standard output. If you leave either file out, it works the same as if you'd put - for that file. You can also use the -o outfile option to name the output file.
Unless noted otherwise, or the option ends in =, any option that takes an argument can have that argument right after the option, or with a space in between. So -Ifoo and -I foo do the exact same thing π
Lots of options have multi-letter names, so you can't bundle single-letter options together. -dM is very different from -d -M π
-D nameβ Predefinesnameas a macro, with the definition1.-D name=definitionβ The contents ofdefinitionget tokenized and processed as if they showed up during translation phase three in a#definedirective. The definition gets cut off at any embedded newline characters.- If you call the preprocessor from a shell, or something shell-like, you might need the shell's quoting syntax to protect characters like spaces, since those mean something to the shell.
- Want a function-like macro on the command line? Put its argument list in parentheses before the equals sign (if there is one). Parentheses mean something to most shells, so quote the option. With
shandcsh,-D'name(args...)=definition'works β¨ -Dand-Uoptions are processed in the order you type them on the command line. All the-imacros fileand-include fileoptions get processed after every-Dand-Uoption.
-U nameβ Cancels any previous definition ofname, whether it was built in or set with a-Doption π§-include fileβ Processesfileas if#include "file"showed up as the first line of the primary source file. The first directory searched forfileis the preprocessor's working directory, not the directory with the main source file. If it's not found there, it gets searched for in the rest of the#include "..."search chain as normal.- If you give several
-includeoptions, the files get included in the order they appear on the command line.
- If you give several
-imacros fileβ Exactly like-include, except any output made by scanningfilegets tossed. The macros it defines stay defined. This lets you grab all the macros from a header without also processing its declarations π¦- Every file given with
-imacrosgets processed before every file given with-include.
- Every file given with
-undefβ Doesn't predefine any system-specific or GCC-specific macros. The standard predefined macros stay defined.-pthreadβ Defines the extra macros you need to use the POSIX threads library π§΅ Use this option consistently for both compilation and linking. It's supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets.-Mβ Instead of spitting out the preprocessed result, outputs a rulemakecan use to describe the dependencies of the main source file. The preprocessor outputs one make rule that has the object file name for that source file, a colon, and the names of all the included files. That includes files coming from-includeor-imacroscommand-line options π- Unless you set it explicitly (with
-MTor-MQ), the object file name is the source file name with its suffix swapped for the object file suffix, and any leading directory parts removed. - If there are lots of included files, the rule gets split across several lines using
\-newline. The rule has no commands. - This option does not hide the preprocessor's debug output, like
-dM. To keep that debug output from mixing in with the dependency rules, explicitly name the dependency output file with-MF, or use an environment variable likeDEPENDENCIES_OUTPUT. Debug output still goes to the regular output stream as usual. - Passing
-Mto the driver implies-E, and suppresses warnings with an implicit-w.
- Unless you set it explicitly (with
-MMβ Like-M, but doesn't mention header files found in system header directories, or header files included directly or indirectly from such a header π- This means the choice of angle brackets or double quotes in an
#includedirective doesn't, by itself, decide whether that header shows up in-MMdependency output.
- This means the choice of angle brackets or double quotes in an
-MF fileβ When used with-Mor-MM, names a file to write the dependencies to. If you don't give a-MFswitch, the preprocessor sends the rules to the same place it would send preprocessed output.- When used with the driver options
-MDor-MMD,-MFoverrides the default dependency output file. - If
fileis-, the dependencies get written to stdout.
- When used with the driver options
-MGβ Used together with an option like-Mthat asks for dependency generation,-MGassumes missing header files are generated files and adds them to the dependency list without raising an error π The dependency filename is taken straight from the#includedirective, with no path prepended.-MGalso suppresses preprocessed output, since a missing header file makes that useless.- This feature is used for automatically updating makefiles.
-Mno-modulesβ Disables dependency generation for compiled module interfaces.-MPβ Tells CPP to add a phony target for each dependency other than the main file, so each one depends on nothing. These dummy rules get around the errorsmakethrows if you delete header files without updating the Makefile to match π«Ά Here's typical output:
test.o: test.c test.h
test.h:
-MT targetβ Changes the target of the rule that dependency generation emits. By default, CPP takes the name of the main input file, deletes any directory components and file suffix like.c, and adds the platform's usual object suffix. That result is the target.- An
-MToption sets the target to exactly the string you give it. If you want multiple targets, you can put them in a single argument to-MT, or use multiple-MToptions. - For example,
-MT '$(objpfx)foo.o'might give:
- An
$(objpfx)foo.o: foo.c
-MQ targetβ Same as-MT, but it quotes any characters that are special to Make β¨-MQ '$(objpfx)foo.o'gives:
$$(objpfx)foo.o: foo.c
- The default target is automatically quoted, as if it had been given with
-MQ.
-MDβ-MDis equivalent to-M -MF file, except that-Eis not implied π The driver figures outfilebased on whether an-ooption is given. If it is, the driver uses that argument with a suffix of.d. Otherwise, it takes the input file name, removes any directory components and suffix, and applies a.dsuffix.- If
-MDis used together with-E, any-oswitch is understood to name the dependency output file. But if-MDis used without-E, each-ois understood to name a target object file. - Since
-Eisn't implied,-MDcan generate a dependency output file as a side effect of the compilation process πΈ
- If
-MMDβ Basically-MD, but it only mentions your header files and skips the system ones π-fpreprocessedβ okay so this one tells the preprocessor that the input file has already been preprocessed π That means it skips macro expansion, trigraph conversion, escaped newline splicing, and most directives. It still spots and removes comments, so you can pass a file preprocessed with-Cto the compiler without any drama. In this mode the integrated preprocessor is basically just a tokenizer for the front ends β¨
-fpreprocessed is switched on automatically if the input file ends in .i, .ii or .mi. Those are the extensions GCC uses for preprocessed files made by -save-temps π§
-fdirectives-onlyβ When preprocessing, it handles directives but does not expand macros π¦ How it behaves depends on-Eand-fpreprocessed:- With
-E, it only handles directives like"#define","#ifdef", and"#error". Other stuff like macro expansion and trigraph conversion is skipped. The-dDoption also gets turned on automatically π - With
-fpreprocessed, predefining the command line and most builtin macros is disabled. Context-dependent macros like__LINE__still get handled normally. This lets you compile files that were previously preprocessed with-E -fdirectives-onlyπ - With both
-Eand-fpreprocessed, the-fpreprocessedrules win π This lets you fully preprocess files that were previously preprocessed with-E -fdirectives-only.
- With
-fdollars-in-identifiersβ Lets$be used in identifiers π-fextended-identifiersβ Accepts universal character names and extended characters in identifiers π This is turned on by default for C99 (and later C standard versions) and C++, so you're probably already getting it.-fno-canonical-system-headersβ When preprocessing, this stops system header paths from getting shortened with canonicalization πΈ-fmax-include-depth=depthβ Sets how deep nested#includes can go. The default is200β-ftabstop=widthβ Sets the distance between tab stops π This helps the preprocessor report correct column numbers in warnings or errors, even when tabs show up on the line. If the value is less than1or greater than100, the option gets ignored. The default is8π-ftrack-macro-expansion[=level]β Tracks where tokens are located across macro expansions π This lets the compiler show a diagnostic about the current macro expansion stack when a compilation error happens inside a macro expansion. The catch is that it makes the preprocessor and compiler eat more memory π₯² The level parameter lets you pick how precisely token locations get tracked, so you can trade precision for memory if you need to:- Level
0deactivates this option. - Level
1tracks token locations in a degraded mode for minimal memory overhead. In this mode, every token that comes out of expanding an argument of a function-like macro has the same location. - Level
2tracks token locations completely. This is the most memory-hungry one π
- Level
If you give this option no argument, the default level is 2.
Heads up: -ftrack-macro-expansion=2 is activated by default, so you're already on the most memory-hungry setting unless you change it.
-fmacro-prefix-map=old=newβ When preprocessing files living in directory old, the__FILE__and__BASE_FILE__macros expand as if those files lived in directory new instead πΊοΈ You can use this to turn an absolute path into a relative one by using.for new, which can lead to more reproducible builds that don't depend on location. This option also affects__builtin_FILE()during compilation. See also-ffile-prefix-map.-fexec-charset=charsetβ Sets the execution character set, which is used for string and character constants π€ The default isUTF-8. charset can be any encoding the system'siconvlibrary routine supports.-fwide-exec-charset=charsetβ Sets the wide execution character set, used for wide string and character constants π The default isUTF-32orUTF-16, whichever matches the width ofwchar_t. Just like-fexec-charset, charset can be any encoding the system'siconvlibrary routine supports.
Watch out: you'll run into problems with encodings that don't fit exactly in wchar_t π¬
-finput-charset=charsetβ Sets the input character set, which is used to translate from the input file's character set into the source character set GCC uses π₯ If the locale doesn't specify one, or GCC can't get that info from the locale, the default isUTF-8. Either the locale or this command-line option can override it. Right now, if they conflict, the command-line option takes precedence π charset can be any encoding the system'siconvlibrary routine supports.-fworking-directoryβ Turns on linemarkers in the preprocessor output so the compiler knows the working directory at the time of preprocessing ποΈ When this is on, the preprocessor emits a second linemarker after the initial one, with the current working directory followed by two slashes. When that directory shows up in the preprocessed input, GCC uses it as the working directory in some debugging information formats. This option is implicitly enabled if debugging information is enabled, but you can block that with the negated form-fno-working-directory.
If the-Pflag is in the command line, this option does nothing, since no#linedirectives get emitted whatsoever π ββοΈ
-A predicate=answerβ Makes an assertion with the predicate predicate and the answer answer π This form is the preferred one over the older-A predicate(answer)form. The older one is still supported, but the new one is better because it doesn't use shell special characters.-A -predicate=answerβ Cancels an assertion with the predicate predicate and the answer answer π«-Cβ Don't throw away comments! π«Ά All comments get passed through to the output file, except for comments inside processed directives, which get deleted along with the directive.
Be ready for side effects with-C. It makes the preprocessor treat comments as tokens in their own right. For example, a comment at the start of what would be a directive line turns that line into an ordinary source line, since the first token on the line is no longer a#π
-CCβ Don't throw away comments, even during macro expansion π¦ This is like-C, except comments inside macros also get passed through to the output file where the macro gets expanded.
On top of the -C side effects, -CC converts all C++-style comments inside a macro into C-style comments. This stops a later use of that macro from accidentally commenting out the rest of the source line π The -CC option is mostly used to support lint comments π§Ή
-Pβ Stops linemarkers from being generated in the preprocessor output π« This might come in handy when you're running the preprocessor on something that isn't C code and will get sent to a program that could get confused by linemarkers.-traditional,-traditional-cppβ Tries to imitate pre-standard C preprocessors instead of the ISO C preprocessors π°οΈ
Note that GCC doesn't otherwise try to emulate a pre-standard C compiler, and these options only work with the -E switch or when you invoke CPP explicitly.
-trigraphsβ Supports ISO C trigraphs πΊ These are three-character sequences that all start with??, which ISO C defines to stand for single characters. For example,??/stands for\, so'??/n'is a character constant for a newline π
By default GCC ignores trigraphs, but in standard-conforming modes it converts them. See the -std and -ansi options.
-remapβ Turns on special code to work around file systems that only allow super short file names, like MS-DOS πΎ-Hβ Prints the name of each header file used, in addition to the other normal stuff π Each name is indented to show how deep it sits in the#includestack. Precompiled header files get printed too, even if they turn out to be invalid. An invalid precompiled header file is printed with...x, and a valid one is printed with...!β-dlettersβ Tells GCC to make debugging dumps during compilation, as specified by letters π The flags documented here are the ones relevant to the preprocessor. Other letters are interpreted by the compiler proper, or reserved for future versions of GCC, so they're silently ignored.
If you specify letters whose behavior conflicts, the result is undefined. That's a big nope π ββοΈ
-dMβ Instead of the normal output, this generates a list of#definedirectives for all the macros defined during the execution of the preprocessor, including predefined macros π It's a great way to find out what's predefined in your version of the preprocessor. Assuming you have no filefoo.h, this command:
touch foo.h; cpp -dM foo.h
shows all the predefined macros β¨
-dDβ Like-dM, except it doesn't include the predefined macros, and it outputs both the#definedirectives and the result of preprocessing. Both kinds of output go to the standard output file π€-dNβ Like-dD, but it only emits the macro names, not their expansions π·οΈ-dIβ Outputs#includedirectives in addition to the result of preprocessing π-dUβ Like-dD, except only macros that get expanded, or whose definedness gets tested in preprocessor directives, are output. The output is delayed until the macro is used or tested, and#undefdirectives are also output for macros that were tested but undefined at the time π§
-fdebug-cppβ This one is only useful for debugging GCC π οΈ When used from CPP or with-E, it dumps debugging information about location maps. Every token in the output gets preceded by the dump of the map its location belongs to.
When used from GCC without -E, this option has no effect.
-I dir,-iquote dir,-isystem dir,-idirafter dirβ Adds the directory dir to the list of directories searched for header files during preprocessing ππ¦
Okay so if dir begins with = or $SYSROOT, that bit gets swapped out for the sysroot prefix β¨ peep --sysroot and -isysroot for the deets π
Directories given with -iquote only apply to the quote form of the directive, #include "file" π -I, -isystem, and -idirafter apply to the lookup for both #include "file" and #include <file> π¦
You can stack up any number or combo of these options on the command line to search for header files in a bunch of directories π The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file gets searched first π
- For the quote form, the
-iquotedirectories get searched left-to-right, in the order they show up on the command line π«Ά -Idirectories get scanned left-to-right π§-isystemdirectories get scanned left-to-right π- The standard system directories get scanned π°
-idirafterdirectories get scanned left-to-right, last but not least πΈ
You can use -I to override a system header file and swap in your own version, since these directories get searched before the standard system header file directories π¦ But ngl, don't use this option to add directories full of vendor-supplied system header files π« Use -isystem for that π
The -isystem and -idirafter options also mark the directory as a system directory, so it gets the same special treatment as the standard system directories π«Ά
If a standard system include directory, or a directory given with -isystem, is also given with -I, the -I option gets ignored π The directory still gets searched, but as a system directory at its normal spot in the system include chain. This is so GCC's procedure for fixing buggy system headers and the ordering for the #include_next directive don't get accidentally changed π
If you really need to change the search order for system directories, use the -nostdinc and/or -isystem options.
-I-β Splits the include path πͺ This option is deprecated, so please use-iquoteinstead for-Idirectories that come before the-I-, and remove the-I-option.
Any directories given with -I before -I- only get searched for headers requested with #include "file". They do not get searched for #include <file>. If more directories are given with -I after the -I-, those get searched for all #include directives π
On top of that, -I- stops the directory of the current file from being used as the first search directory for #include "file". There's no way to override this effect of -I- π
-iprefix prefixβ Sets prefix as the prefix for later-iwithprefixoptions π If the prefix is a directory, make sure you include the final/.-iwithprefix dir,-iwithprefixbefore dirβ Tacks dir onto the prefix you set earlier with-iprefix, then adds the result to the include search path π§-iwithprefixbeforeputs it in the same place-Iwould, and-iwithprefixputs it where-idirafterwould.-isysroot dirβ This one's like the--sysrootoption, but it only applies to header files. The exception is Darwin targets, where it applies to both header files and libraries π Check out the--sysrootoption for more info.-imultilib dirβ Uses dir as a subdirectory of the directory that holds the target-specific C++ headers π-nostdincβ Skips the standard system directories when searching for header files π Only the directories you explicitly give with-I,-iquote,-isystem, and/or-idirafterget searched, plus the directory of the current file if it's appropriate.-nostdinc++β Skips the C++-specific standard directories for header files, but still searches the other standard directories π (This one's used when building the C++ library.)-Wcomment,-Wcommentsβ Warns whenever a comment-start sequence/*shows up inside a/*comment, or whenever a backslash-newline shows up in a//comment β οΈ This warning is enabled by-Wall.-Wtrigraphsβ Warns if any trigraphs show up that might change what the program means π Trigraphs inside comments don't get warned about, except the ones that would form escaped newlines.
This option is implied by -Wall. If -Wall isn't given, this option is still on unless trigraphs are enabled. Want trigraph conversion without warnings but still get the other -Wall warnings? Use -trigraphs -Wall -Wno-trigraphs π«Ά
-Wundefβ Warns if an undefined identifier gets evaluated in an#ifdirective. Those identifiers get replaced with zero π’-Wexpansion-to-definedβ Warns wheneverdefinedshows up in the expansion of a macro, including when the macro gets expanded by an#ifdirective. That usage isn't portable π This warning is also enabled by-Wpedanticand-Wextra.-Wunused-macrosβ Warns about macros defined in the main file that are unused π§Ή A macro counts as used if it's expanded or tested for existence at least once. The preprocessor also warns if the macro hasn't been used by the time it gets redefined or undefined.
Built-in macros, macros defined on the command line, and macros defined in include files don't get warned about.
Note: If a macro is actually used, but only in skipped conditional blocks, the preprocessor still reports it as unused. To avoid the warning in that case, you might improve the scope of the macro's definition by, for example, moving it into the first skipped block. Or you could give it a dummy use with something like this:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsβ Stops the warning for when an#elseor an#endifhas text after it π This happens sometimes in older programs with code like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO should be in comments. This warning is on by default.
β¨ ENVIRONMENT β¨
This section covers the environment variables that affect how CPP operates πΈ You can use them to specify directories or prefixes for searching include files, or to control dependency output.
You can also specify places to search with options like -I, and control dependency output with options like -M. These take precedence over environment variables, which in turn take precedence over the configuration of GCC π
π§ CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH
Each variable's value is a list of directories separated by a special character, a lot like PATH π€οΈ That's where it looks for header files. The special character, "PATH_SEPARATOR", depends on the target and gets set at GCC build time. For Microsoft Windows-based targets it's a semicolon, and for almost all other targets it's a colon.
CPATH specifies a list of directories to search as if they were given with -I, but after any paths given with -I options on the command line. This variable gets used no matter which language is being preprocessed π
The remaining variables only apply when preprocessing the particular language they name. Each one specifies a list of directories to search as if they were given with -isystem, but after any paths given with -isystem options on the command line.
In all of these variables, an empty element tells the compiler to search its current working directory π Empty elements can show up at the beginning or end of a path. For example, if the value of CPATH is ":/special/include", that has the same effect as -I. -I/special/include π¦
π DEPENDENCIES_OUTPUT
If this variable is set, its value says how to output dependencies for Make, based on the non-system header files the compiler processes π οΈ System header files get ignored in the dependency output.
The value can be just a file name, in which case the Make rules get written to that file, with the target name guessed from the source file name. Or the value can take the form file target, in which case the rules get written to file using target as the target name.
In other words, this environment variable is the same as combining the options -MM and -MF, with an optional -MT switch too π
π SUNPRO_DEPENDENCIES
This variable is the same as DEPENDENCIES_OUTPUT, except system header files aren't ignored. So it implies -M rather than -MM π The dependence on the main input file is omitted, though.
β° SOURCE_DATE_EPOCH
If this variable is set, its value is a UNIX timestamp that replaces the current date and time in the __DATE__ and __TIME__ macros, so the embedded timestamps come out reproducible π
The value of SOURCE_DATE_EPOCH must be a UNIX timestamp, which means the number of seconds (excluding leap seconds) since 01 Jan 1970 00:00:00, written in ASCII. It's identical to the output of date +%s on GNU/Linux and other systems that support the %s extension in the date command π§
The value should be a known timestamp, like the last modification time of the source or package, and the build process should set it π«Ά
β¨ SEE ALSO β¨
gpl(7), gfdl(7), fsf-funding(7), gcc(1), and the Info entries for cpp and gcc ππ
β¨ COPYRIGHT β¨
Copyright (c) 1987-2022 Free Software Foundation, Inc.
This document is free to copy, distribute, and/or modify under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation π A copy of the license is in the man page gfdl(7). This manual has no Invariant Sections. The Front-Cover Texts are (a) (see below), and the Back-Cover Texts are (b) (see below).
(a) The FSF's Front-Cover Text is:
A GNU Manual
(b) The FSF's Back-Cover Text is:
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.
Okay bestie, that's the whole page π Dated 2022-02-22, from gcc-12, signed off as CPP(1) πΈ Go be a preprocessor queen πβ¨
π¦ where this page comes from
- ubuntu jammy: cpp-12-arm-linux-gnueabihf 12-20220222-1ubuntu1cross1
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms