控制Xcode将包含哪个项目头文件

Jea*_*uys 14 xcode include search-path

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

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

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

MyProject
  TheirOldLib
    theirLib.h
    theirLib.cpp
  TheirNewLib
    theirLib.h
    theirLib.cpp
myCode.cpp
Run Code Online (Sandbox Code Playgroud)

和myCode.cpp做的事情如下:

#include "theirLib.h"
…
somecode()
{
#if OLDVERSION
  theirOldLibCall(…);
#else
  theirNewLibCall(…);
#endif
}
Run Code Online (Sandbox Code Playgroud)

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

注意#include必须如图所示.以下两个都失败,找不到文件错误:

#include "TheirOldLib/theirLib.h"
#include "TheirNewLib/theirLib.h"
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢你的帮助.

Jea*_*uys 22

答案的关键部分是使用Chris在评论中建议的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不是苹果记载,据我可以告诉.我将填写一份错误报告,因为这个设置在许多情况下都是至关重要的,因为谷歌搜索显示.报告为rdar:// 7840694.同样在开放雷达上http://openradar.appspot.com/radar?id=253401

  • 不应该在第2步中使用"用户标题搜索路径"而不是"标题搜索路径"吗?因为你使用#include""而不是#include <> (2认同)

ble*_*ter 7

对于某些项目,USE_HEADERMAP = NO是过度杀伤.仅使用HEADERMAP_INCLUDES_FLAT_ENTRIES_FOR_TARGET_BEING_BUILT = NO就足够了.文档在这里:https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW159


Mec*_*cki 6

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
Run Code Online (Sandbox Code Playgroud)

这三个条目匹配

#include "Foo.h"
#include "Bar.h"
#include "foo/bar/foobar.h"
Run Code Online (Sandbox Code Playgroud)

现在 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 才会生成头映射文件并将其作为参数传递给编译器。

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

如果使用 导入头文件,它将在使用选项 ( )<...>指定的所有目录、使用选项指定的所有目录(在 Xcode 中)以及 stanadrd 系统头目录(所选 SDK 的以及属于该 SDK 的其他目录)中进行搜索。安装的开发人员工具);完全按照该顺序,并且在每个类别中都按照给定的顺序。-IHEADER_SEARCH_PATHS-isystemSYSTEM_HEADER_SEARCH_PATHS/usr/include

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