18

我的 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"

那么有没有办法告诉 XcodetheirLib.h每个目标包含哪些内容?

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

谢谢你的帮助。

4

5 回答 5

23

答案的关键部分是使用 USE_HEADERMAP = NO 正如克里斯在评论中所建议的那样。这是详细信息。

短配方(在 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

于 2010-04-08T08:38:32.227 回答
9

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

于 2011-09-07T12:43:43.973 回答
5

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(安装的开发者工具);完全按照给定的顺序和每个类别中的顺序。SYSTEM_HEADER_SEARCH_PATHS/usr/include

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

于 2020-08-28T10:14:46.617 回答
-1

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

于 2010-04-08T00:12:55.107 回答
-1

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

于 2019-02-03T12:23:30.770 回答