包含的标题中的搜索路径因不同的编译器而异

时间:2018-01-31 09:29:52

标签: c++ gcc cl

我有以下文件夹结构:

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的行为?

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“header1.h”                ^       生成了1个警告。

它甚至还有一个特定的规则-Wmicrosoft-include

1 个答案:

答案 0 :(得分:1)

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

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

  

引用表格

     

(3)在当前打开的包含文件的目录中,在   它们被打开的相反顺序。搜索开始于   父包含文件的目录并继续向上通过   任何祖父母的目录都包含文件。

这就是为什么,当header2.hmain.cpp内处理header1.h时,它也包含import javax.swing.JOptionPane; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Provides; public class Main { public static void main(String[] args) { CallingService callingService = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(CallingService.class).to(DefaultCallingService.class); bind(CalledService.class).to(DefaultCalledService.class); } @Provides String provideParameter() { return JOptionPane.showInputDialog(null); } }).getInstance(CallingService.class); callingService.requestStuffExecution(); } } ,它不会给您带来任何错误。

GCC搜索规则完全不同:

  
      
  1. 对于include伪指令的引用形式,首先搜索当前文件的目录。
  2.   
  3. 对于include伪指令的引用形式,-iquote选项指定的目录按从左到右的顺序搜索,如   它们出现在命令行中。
  4.   
  5. 使用-I选项指定的目录按从左到右的顺序扫描。
  6.   
  7. 使用-isystem选项指定的目录按从左到右的顺序扫描。
  8.   
  9. 扫描标准系统目录。
  10.   
  11. 使用-idirafter选项指定的目录按从左到右的顺序扫描。
  12.   

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