【问题标题】:-I and -isystem different behaviour when compiling-I 和 -isystem 编译时的不同行为
【发布时间】:2018-09-18 01:24:21
【问题描述】:

我有 3 个 CMake 项目:myapp-avr(AVR 可执行文件)、myapp-unix(Unix 可执行文件)和 my_lib(可执行文件导入的 c++ 静态库)。当我编译 MyLib 项目时,我一点问题都没有。我还可以成功编译 myapp-avr 和 myapp-unix 项目。但是,在链接我的 app-avr 时出现错误,例如“未定义的引用”。

我将一个示例上传到 GitHub:https://github.com/cajomferro/basic-cmake。我的 CMake 结构基于 Pablo Ariasal 示例项目:https://github.com/pabloariasal/modern-cmake-sample

我现在知道问题与 -isystem 选项有关。为什么相同的命令可以与 -I 选项一起使用,但不能与 -isystem 选项一起使用(这是用于导入/供应商库的选项)?

不起作用:(由 CMake 自动生成)

/usr/local/CrossPack-AVR/bin/avr-g++ -DARDUINO=10805 -DF_CPU=16000000L -isystem mylib/include -Os -g -w -fpermissive -fno -exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega328p -std=gnu++11 -o src/main.cpp.obj -c src/main.cpp

作品:

/usr/local/CrossPack-AVR/bin/avr-g++ -DARDUINO=10805 -DF_CPU=16000000L -I mylib/include -Os -g -w -fpermissive -fno -exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega328p -std=gnu++11 -o src/main.cpp.obj -c src/main.cpp


根据avr-g++手册,-isystem的意思是:在-I指定的所有目录之后但在标准系统目录之前搜索头文件。将其标记为系统目录,使其获得与应用于标准系统目录相同的特殊处理

此外,在阅读 -I 选项时,avr-g++ 说:您不应该使用此选项来添加包含供应商提供的系统头文件的目录(为此使用 -isystem)

我想这就是 CMake 使用 -isystem 选项而不是使用 -I 自动生成 Make 文件的原因。因为在我的 CMake 配置中,我使用 find_package() 命令链接库,所以 CMake 将其解释为供应商提供的系统?!

这个项目与 clang(也使用 -isystem)配合得很好。我的问题是 avr-g++。

在使用 avr-g++ 的 -isystem 之前有人遇到过问题吗?是否可以强制 CMake 使用 -I?谢谢!!

【问题讨论】:

  • 我不太确定你的问题是什么。 -I-isystem 做不同的事情。所以……他们做的事情是不同的。有关的。但不一样。大多数第 3 方库都应该使用 -I,除了少数伪装成其他类型的库(我在看着你,Boost)。
  • 也许你曾经在 extern "C" 块中包含了标题,然后你又在这样的块之外包含了它。没有minimal reproducible example,很难判断你做错了什么。确保不要在 extern "C" 块中包含标题,并将 #pragma once 放在标题顶部以确保它只包含一次。
  • 感谢您的回答。我更新了我的问题以便更好地解释我的问题。

标签: c++ cmake avr


【解决方案1】:

问题解决了!根据https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html,显然 -isystem 在 GNU 编译器上有不同的行为:

在非常旧的系统上,一些预定义的系统头目录 得到更特殊的待遇。 GNU C++ 考虑头文件中的代码 在这些目录中找到被外部“C”块包围的目录。

这些人也有类似的问题:https://github.com/conan-io/conan/issues/269

所以为了避免这种混乱,只需通知 CMake 使用 -I 代替。需要一个简单的行:NO_SYSTEM_FROM_IMPORTED ON (https://cmake.org/cmake/help/latest/prop_tgt/NO_SYSTEM_FROM_IMPORTED.html)。

一个例子是:

set_target_properties(my_target
    PROPERTIES
    NO_SYSTEM_FROM_IMPORTED ON
    )

在 myapp-avr 可执行文件的 CMakeLists.txt 中可以找到完整示例:https://github.com/cajomferro/basic-cmake/blob/master/myapp-avr/CMakeLists.txt

【讨论】:

  • 啊!并且不要忘记搜索被这些引号包围的“-isystem”,否则谷歌会忽略它;)
  • 这是精确的解决方案。伙计,这个“功能”太隐蔽了,几乎是一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 2011-03-23
  • 2021-05-25
  • 1970-01-01
  • 2010-12-17
  • 2021-05-03
相关资源
最近更新 更多