Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make clang -E omit precompiled header

PrecompiledHeader.h:

#include "stdio.h"

main.cpp:

#include "PrecompiledHeader.h"
#include "stdio.h"

int main()
{
   return 123;
}

Creating precompiled header:

clang -x c++-header PrecompiledHeader.h -o PrecompiledHeader.pch

Running clang preprocessor on main.cpp:

clang main.cpp -include-pch PrecompiledHeader.pch -E 

This currently outputs many many many pages of output (stdio.h). However, what I would like to get is only the main function, and have the contents of PrecompiledHeader.h be omitted from the output.

Is there any way to make clang do this? (if someone knows the answer to the same question for visualstudio's cl.exe I'd love to know about it too :)

like image 600
Lucas Meijer Avatar asked Jun 03 '16 14:06

Lucas Meijer


People also ask

How do I turn off precompiled headers?

To turn off precompiled headersSelect the Configuration properties > C/C++ > Precompiled Headers property page. In the property list, select the drop-down for the Precompiled Header property, and then choose Not Using Precompiled Headers.

Do I need precompiled headers?

Usage of precompiled headers may significantly reduce compilation time, especially when applied to large header files, header files that include many other header files, or header files that are included in many translation units.

How do I precompile a header file?

The compiler options for precompiled headers are /Y . In the project property pages, the options are located under Configuration Properties > C/C++ > Precompiled Headers. You can choose to not use precompiled headers, and you can specify the header file name and the name and path of the output file.

What is the use of precompiled headers?

Precompiled headers (PCH) are a performance feature supported by some compilers to compile a stable body of code, and store the compiled state of the code in a binary file. During subsequent compilations, the compiler will load the stored state, and continue compiling the specified file.


1 Answers

Hardly such a way exists or will be built into clang (or any other C++ compiler) in the future. The problem is that precompiled headers are used to speed up the compilation step which is usually significantly more expensive than the preprocessing step. As a result, if you are going to just preprocess your source, the precompiled header will simply not be used. One way that has a negligibly small chance of producing what you want is to use the -include option instead of the -include-pch option (note that you must specify the *.h rather than the *.pch file to it):

clang main.cpp -include PrecompiledHeader.h -E

The guaranteed way of solving your problem is to pipe the preprocessed output through a simple filter program that looks at the # line "file" directives and removes text coming from #includeed files:

clang main.cpp -E|remove_included_code

remove_included_code can be easily implemented in python, bash, C/C++, etc. Here is a C++ implementation (C++ was chosen so that it can be most easily used under Windows):

remove_included_code.cpp

#include <iostream>
#include <cstdlib>

using namespace std;
typedef std::string Str;

bool isLineDirective(const Str& line)
{
    return line.size() >= 3
        && line[0] == '#'
        && line[1] == ' '
        && isdigit(line[2]);
}

Str getFile(const Str& line)
{
    const Str::size_type start = line.find_first_of('"') + 1;
    const Str::size_type end = line.find_first_of('"', start);
    return line.substr(start, end - start);
}

int main()
{
    Str line;
    getline(cin, line);
    if ( !isLineDirective(line) ) {
        cerr << "Error: Input must start with a '# line \"file\"' directive\n";
        exit(1);
    }

    const Str startFile = getFile(line);
    Str currentFile = startFile;
    while ( getline(cin, line) ) {
        if ( isLineDirective(line) )
            currentFile = getFile(line);
        else if (currentFile == startFile )
            cout << line << endl;
    }

    return 0;
}

The advantage of this solution is that it will work with all compilers.

like image 77
Leon Avatar answered Sep 27 '22 17:09

Leon