【问题标题】:Why does Xcode 6 incorrectly include from user path before system path?为什么 Xcode 6 在系统路径之前错误地包含来自用户路径?
【发布时间】:2015-03-03 22:24:29
【问题描述】:

我正在尝试使用 Xcode 6.1.1 构建我为 Windows、OSX 下的 Visual Studio 完成的项目。

我遇到了一个问题,文件中需要包含#include <string.h>。但是,在与执行此操作的文件相同的文件夹中,还有一个名为 string.h 的文件。

在我的 Visual Studio 项目下,这仍然解析文件,首先搜索系统路径。

在 Xcode 项目中,我确保在“用户标题搜索路径”下设置了我自己的路径 - Xcode 扩展到正确的路径。我还将“始终搜索用户路径”设置为否 - 根据文档,应首先搜索系统路径: https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW110

但由于某种原因,#include <string.h> 似乎被视为#include "string.h"

配置是在项目中定义的,我确保目标不会覆盖它。

这是系统包含<>的一些Xcode/OSX东西吗?先搜索包含文件的路径?

我的本​​地string.h 文件位于ruby/api/string.h,相对于我的用户标头搜索路径中的包含路径。


https://gist.github.com/thomthom/034b539bede38dd68261 的结果: https://gist.github.com/thomthom/034b539bede38dd68261

【问题讨论】:

  • 也许可以尝试使用#import <string.h>,或者将项目中的文件string.h重命名为其他名称。 <> vs "" 通常表示标准库路径或用户头路径。
  • #import 不是 Objective C 的东西吗?虽然重命名可以解决它 - 在我看来这是错误的行为,我更愿意找到问题的根源而不是重命名一堆文件。
  • 大部分是的;不过,它可以与C++C 等一起使用。我对您的问题的困惑是您是否尝试在项目中使用标准库或特别是“string.h” - 或两者兼而有之?
  • 两者 - 我需要我自己的 string.h 我使用 #include "ruby/api/string.h" - 当我需要系统标头(实际上它被我包含的 Ruby 标头使用)时使用:#include <string.h> 但是后者在 Xcode 中不起作用 - 而它在 Visual Studio 中起作用。 Xcode 似乎会在与包含文件相同的文件夹中查找 #include <> 的文件,然后再查看系统文件夹。
  • <string.h> 被我正在使用的第三方库使用 - 无法更改。将我自己的“ruby/api/string.h”更改为“ruby/api/string.hpp”确实可以解决名称冲突。

标签: c++ c xcode6 include-path


【解决方案1】:

搜索以满足#include 指令的路径以及搜索它们的顺序是实现定义的。这包括是否在任何默认路径之前、之后或代替任何默认路径搜索任何用户指定的包含路径(如果甚至支持)。

#include 指令的两种 形式都是这种情况。特别是,尽管实现执行某种相对搜索以查找使用双引号包含语法指定的文件是很常见的,但 C 并不要求这样做。它只要求如果用于解析双引号包含的实现定义的机制失败,编译器必须回退到用于解析尖括号包含的实现定义的方法。

此外,C 仅针对给定标题名称​​唯一 标识要包含的文件的情况指定行为。根据人们如何解释“唯一”,人们可能会声称 C 在您描述的情况下根本没有定义任何行为,因为您没有唯一地标识要包含的标头。不过,这有点疯狂——我认为最好根据实现定义的定位标头的方法来解释“唯一”。

最好的办法是避免标题名称与标准标题名称冲突。其中一个版本是将它们放在一个子目录中,该子目录将其名称作为前缀。例如,将string.h 放入src/myapp/,并将其包含为

#include "myapp/string.h"

为使其尽可能安全,请确保目录 src/ 位于包含搜索路径中。

【讨论】:

  • 我的string.h 文件嵌套在子文件夹下:ruby/api/string.h,我将其包括在内:#include "ruby/api/string.h"。但#include <string.h> 似乎解析到同一个文件。 - 所以你是说#include <string.h> 可能是为我与Xcode 一起使用的编译器硬编码的,以便首先查看当前文件夹 - 无论如何?有没有办法覆盖它并强制它首先查看系统文件夹?
  • @thomthom,您的标题已经在嵌套子目录中,这绝不会改变我的建议。如果在编译本身不提供此类标头的源时,生成的名称可以被识别为标头,那么您会遇到名称冲突,最好避免这种冲突。您仍然可以通过将其推送到子目录中来做到这一点,即myapp/ruby/api/string.h。如果您不想更改名称,则必须查阅您使用的每个编译器的文档,以了解如何处理此问题。
  • 我对此感到有些困惑“您仍然可以通过将其推送到子目录中来做到这一点” - 但我看不出该子文件夹与它所在的当前子文件夹有何不同. 我确实在 CLang 文档中找到了这一点:“如果包含文件被视为系统头文件,则查找相对于当前目录的文件的 #include 指令被视为包含系统头文件。”虽然 - 我没有看到包含文件如何被视为系统头文件。我想我最终不得不放弃并简单地重命名。虽然希望找到确切的原因。
  • @thomthom,关键是将源引用内部标头的名称更改为不与系统标头冲突的名称。将标头移动到子目录(或以任何其他方式更改其名称)必须与更改源中的 #include 指令相结合,如我的回答中所述。
【解决方案2】:

在查看your gist 时,我注意到与您的屏幕截图有出入:

HEADER_SEARCH_PATHS = /Users/thomas/SourceTree/SUbD/SUbD/../ThirdParty/include/ruby/mac /Users/thomas/SourceTree/SUbD/SUbD/../ThirdParty/include/ruby/mac/universal-darwin12.5.0

这应该是:

HEADER_SEARCH_PATHS = /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include

【讨论】:

  • 那些来自我的目标。在这些路径没有影响之前将$(inherit) 添加到列表中。将我的 ruby/api/string.h 重命名为 ruby/api/string.hpp 确实可以解决它。但是,当我找不到明确的答案时,它仍然困扰着我。
  • HEADER_SEARCH_PATHS 不应该包含您的用户包含的路径,这就是 USER_HEADER_SEARCH_PATHS 应该包含的内容。
  • 这些路径是第三方库。
  • 另外一个建议是尝试设置USE_HEADERMAP = NOmore info
  • 看起来合乎逻辑。但它没有用。它似乎不在USER_HEADER_SEARCH_PATHSHEADER_SEARCH_PATHS 中。我也有类似的差异。尝试将用户路径移动到 USER_* 并将系统路径放入 HEADER_*。那没有帮助。如果用户目录位于任何路径中,Xcode 将首先选择该路径 :(.
猜你喜欢
  • 1970-01-01
  • 2010-11-20
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 2014-12-13
相关资源
最近更新 更多