简体   繁体   English

如何使clang -E省略预编译头

[英]How to make clang -E omit precompiled header

PrecompiledHeader.h: PrecompiledHeader.h:

#include "stdio.h"

main.cpp: 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: 在main.cpp上运行clang预处理器:

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

This currently outputs many many many pages of output (stdio.h). 这当前输出许多页输出(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. 但是,我想得到的只是main函数,并且从输出中省略了PrecompiledHeader.h的内容。

Is there any way to make clang do this? 有没有办法让clang这样做? (if someone knows the answer to the same question for visualstudio's cl.exe I'd love to know about it too :) (如果有人知道visualstudio的cl.exe同样问题的答案,我也很想知道:)

Hardly such a way exists or will be built into clang (or any other C++ compiler) in the future. 这种方式很难存在或将来会被构建到clang(或任何其他C ++编译器)中。 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): 生成所需内容的可能性极小的一种方法是使用-include选项而不是-include-pch选项(请注意,必须指定*.h而不是*.pch文件):

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 #include ed files: 解决问题的有保证的方法是通过一个简单的过滤程序来管道预处理的输出,该程序查看#line # line "file"指令并删除来自#include ed文件的文本:

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可以在python,bash,C / C ++等中轻松实现。这是一个C ++实现(选择C ++使其在Windows下最容易使用):

remove_included_code.cpp 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. 该解决方案的优点是它可以与所有编译器一起使用。

edit: I don't see anything special about precompiled headers in this case - any means of conditionally preventing the expansion of an #include will do. 编辑:在这种情况下,我没有看到有关预编译头的任何特殊内容 - 任何有条件地阻止扩展#include的方法都可以。

I achieve this for standard header includes by wrapping in an ifdef, such that the preprocessed output contains #include "foo" but not the contents. 我通过包装在ifdef中来实现标准头包含,这样预处理的输出包含#include“foo”而不包含内容。 For example, 例如,

#ifdef PRECOMPILE
#define TMP #include <stdio.h>
TMP
#undef TMP
#else
#include <stdio.h>
#endif

Then pass -DPRECOMPILE along with -E. 然后传递-DPRECOMPILE和-E。

The preprocessed output then contains the unexpanded #include. 然后,预处理的输出包含未扩展的#include。 I find this more useful than the simpler alternative of wrapping the #include in #ifdef when reading the preprocessed output. 我发现这比在读取预处理输出时在#ifdef中包装#include更简单的替代方法更有用。

Primarily though, this means I can run macro-heavy code through the preprocessor then clang-format before compiling as normal, for a far improved debugging experience. 但主要是,这意味着我可以在正常编译之前通过预处理器然后使用clang-format运行宏量大的代码,以获得远远改进的调试体验。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM