包含来自包含 header 的搜索路径因不同的编译器而异

Include search paths from included header varies for different compilers

我有以下文件夹结构:

project
├── header1.h
├── folder
│   └── header2.h
└── main.cpp

来源如下:

//main.cpp
#include "header1.h"
#include "folder/header2.h"
int main() {}

//header1.h
#pragma once
void function1() {}

//folder/header2.h
#pragma once
#include "header1.h"
void function2() {}

所以 'header2.h' 包括不在同一文件夹中的 'header1.h'。

使用cl main.cpp编译此代码成功:

Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe main.obj

但是对于 gcc main.cpp 我得到错误:

In file included from main.cpp:2:0:
folder/header2.h:2:21: fatal error: header1.h: No such file or directory
 #include "header1.h"
                     ^
compilation terminated.

这完全有道理。似乎微软正在使用他们自己的规则来解析包含。 有没有办法为 cl(和 Visual Studio)禁用此行为? 有没有办法为 gcc 启用 cl-like 行为?


UPD.

我已在 Windows:

上使用 Clang 4.0.0 clang++ main.cpp 检查过
In file included from main.cpp:2:
./folder/header2.h:2:10: warning: #include resolved using non-portable Microsoft search rules as: ./header1.h

[-Wmicrosoft-include] #include "header1.h" ^ 1 warning generated.

它甚至为此制定了特定规则 -Wmicrosoft-include

This article 解释了 include 指令的两种形式(""<>)是如何被 VC++ 处理的。

我想 "" 形式的 (3) 点导致了对项目中可能包含目录的非常广泛的搜索:

Quoted form

(3) In the directories of the currently opened include files, in the reverse order in which they were opened. The search begins in the directory of the parent include file and continues upward through the directories of any grandparent include files.

这就是为什么当 header2.hmain.cpp 中处理时,它也包括 header1.h,它不会给你错误。

GCC 搜索规则大不相同:

  1. For the quote form of the include directive, the directory of the current file is searched first.
  2. For the quote form of the include directive, the directories specified by -iquote options are searched in left-to-right order, as they appear on the command line.
  3. Directories specified with -I options are scanned in left-to-right order.
  4. Directories specified with -isystem options are scanned in left-to-right order.
  5. Standard system directories are scanned.
  6. Directories specified with -idirafter options are scanned in left-to-right order.

它不会自动搜索到目前为止打开的包含文件的目录(之前包含),这是您出错的原因。我认为没有办法绕过此限制并强制其中一个编译器使用另一个编译器使用的搜索逻辑。