【问题标题】:controlling which project header file Xcode will include控制 Xcode 将包含哪个项目头文件
【发布时间】:2010-04-07 23:57:40
【问题描述】:

我的 Xcode 项目使用两个目标构建同一产品的变体。两者的区别仅在于使用了哪个版本的包含库。对于 .c 源文件,使用目标复选框很容易将正确的版本分配给正确的目标。但是,包含头文件总是包含同一个。这对一个目标是正确的,但对另一个目标是错误的。

有没有办法控制每个目标包含哪个头文件?

这是我的项目文件层次结构(在 Xcode 中复制):

MyProject
  TheirOldLib
    theirLib.h
    theirLib.cpp
  TheirNewLib
    theirLib.h
    theirLib.cpp
myCode.cpp

而 myCode.cpp 会执行以下操作:

#include "theirLib.h"
…
somecode()
{
#if OLDVERSION
  theirOldLibCall(…);
#else
  theirNewLibCall(…);
#endif
}

当然,我为一个目标定义OLDVERSION 而不是另一个目标。

注意#include 必须如图所示。以下两项均因找不到文件错误而失败:

#include "TheirOldLib/theirLib.h"
#include "TheirNewLib/theirLib.h"

那么有没有办法告诉 Xcode 每个目标包含哪个 theirLib.h

约束:
- 两个头文件同名。作为最后的手段,我可​​以重命名其中一个,但我宁愿避免这样做,因为这会导致其他平台上的大量头发拉扯。
- 必须更改 #include 以添加对封闭文件夹的引用也是我宁愿避免的事情,因为我需要使用条件编译指令执行两次。
- 我可以随意调整我的项目,因为我认为合适

感谢您的帮助。

【问题讨论】:

    标签: xcode include search-path


    【解决方案1】:

    答案的关键部分是使用 USE_HEADERMAP = NO,正如 Chris 在评论中所建议的那样。以下是详细信息。

    短配方(在 Xcode 3.2.2 中检查):

    1. 为每个相关目标添加 USE_HEADERMAP = NO 的自定义构建设置。方法如下:
      1.1。在“构建”窗格中打开目标的信息面板。
      1.2.下拉窗口左下方的动作弹出菜单,选择“添加用户自定义设置”。
      1.3.在新添加的行中,将第一列(“Setting”)设置为USE_HEADERMAP,将第二列(“Value”)设置为NO

    2. 为每个目标添加正确的包含路径(目标构建设置“标题搜索路径”)。在我的示例中,这将是:
      2.1。为“旧”目标添加TheirOldLib
      2.2.为“新”目标添加TheirNewLib

    第 1 步 禁用 Xcode 的自动标头映射功能,通过该功能,项目中包含的任何头文件都可以通过其名称直接访问,无论其实际路径如何。当两个标头具有相同的名称时,此功能会导致无法解决的歧义。

    第 2 步 允许 #include "theirLib.h" 在不限定头文件实际路径名的情况下工作。

    这两个步骤一起满足了我的两个约束。

    最后,据我所知,USE_HEADERMAP 没有由 Apple 记录。我将为此填写一份错误报告,因为此设置在许多情况下至关重要,正如谷歌搜索所揭示的那样。报告为 rdar://7840694。也在开放雷达上http://openradar.appspot.com/radar?id=253401

    【讨论】:

    • 这非常有效。谢谢你。发帖人应该将此标记为答案。
    • 是否应该在步骤 2 中使用“用户标题搜索路径”而不是“标题搜索路径”?当你使用 #include "" 而不是 #include
    • 我猜你是对的。 Header Search Paths 有效,但 User Header Search Paths 应该更好。
    【解决方案2】:

    USE_HEADERMAP=NO 对于某些项目来说太过分了。使用HEADERMAP_INCLUDES_FLAT_ENTRIES_FOR_TARGET_BEING_BUILT=NO 可能就足够了。

    此处的文档:
    https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html

    【讨论】:

    • 确实如此。让我们添加这个设置必须添加到用户定义部分,在 xcode 中,选择目标,点击小 +,添加用户定义...完成
    【解决方案3】:

    Xcode 通过创建头映射文件来加速构建。

    除了为编译器提供搜索头文件的目录列表之外,您还可以为它提供头文件映射文件。头映射文件就像一个哈希表,查找键是include 参数,值是头的路径。

    以下是此类地图文件的示例:
    注意: 这不是头映射文件的实际语法,它只是人类可读的表示

    Foo.h -> /usr/include/Foo.h
    Bar.h -> /home/user/Documents/ProjectA/src/include/Bar.h
    foo/bar/foobar.h -> /home/user/Documents/ProjectB/inc/foo/bar/foobar.h
    

    这三个条目匹配

    #include "Foo.h"
    #include "Bar.h"
    #include "foo/bar/foobar.h"
    

    现在 Xcode 有三个设置来控制头映射文件的生成。

    1. HEADERMAP_INCLUDES_FLAT_ENTRIES_FOR_TARGET_BEING_BUILT
      如果YES(默认),属于正在构建的目标的所有头文件都将添加到头映射文件中,并且可以使用include "header.h" 包含在内。请注意,标头只能属于框架/库/捆绑目标,不能属于应用程序/程序目标。

    2. HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES
      如果YES(默认),则所有其他目标的标头都将添加到标头映射文件中,并且可以使用include <TargetName/header.h> 包含在内。请注意,对于非框架目标也是如此。

    3. HEADERMAP_INCLUDES_PROJECT_HEADERS
      如果YES(默认),则构建目标所属的项目文件中存在的所有其他标头也将添加到标头映射文件中,并且可以使用include "header.h"包含。

    此外,还有一个通用设置USE_HEADERMAP 控制是否应该生成头映射文件。只有YES(默认),Xcode 才会生成一个头映射文件并将其作为参数传递给编译器。

    如果标头未在标头映射文件中列出或未使用标头映射,编译器将使用以下两种搜索策略之一来搜索标头:

    如果标头使用<...> 导入,它将在所有使用-I 选项(HEADER_SEARCH_PATHS)指定的目录,所有使用-isystem 选项(Xcode 中的SYSTEM_HEADER_SEARCH_PATHS)指定的目录中搜索,以及 stanadrd 系统头目录(所选 SDK 的/usr/include 和属于已安装开发者工具的其他目录);完全按照给定的顺序和每个类别中的顺序。

    如果标头使用"..." 导入,它将在与正在构建的.c/.m 文件相同的目录中搜索所有使用-iquote 选项指定的目录(Xcode 中的USER_HEADER_SEARCH_PATHS),并在同一目录中搜索<...>;完全按照给定的顺序和每个类别中的顺序。

    【讨论】:

      【解决方案4】:

      为什么不能在每个目标中使用不同的包含路径?

      【讨论】:

      • 如果您有两个名称相同但路径不同的标头,则需要在两个目标的自定义构建设置中设置 USE_HEADERMAP = NO。
      • 整洁。我想我从来没有尝试过。很高兴看到 Mike Ferris 仍在与可用性作斗争。
      • 在每个目标中使用不同的包含路径不起作用:包含文件 in 项目始终可以由 Xcode 访问而根本没有路径。这就是问题首先出现的原因:没有消除歧义的路径,似乎没有办法告诉 Xcode 哪个文件是要包含的正确文件。 Chris 的建议是禁用该功能,以反转为更传统的包含路径方案。我会详细写下答案。
      【解决方案5】:

      使用 USE_HEADERMAP=NO 并在“用户标题搜索路径”中首先包含您的自定义目录,然后递归地包含项目目录:${PROJECT_DIR}/TheirNewLib ${PROJECT_DIR}/**

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多