在Xcode 4中使用静态库进行头管理

时间:2011-06-09 08:23:17

标签: xcode4 static-libraries header-files

在Xcode 4中导入静态库头是否有最佳实践?我的大多数项目都依赖于其他几个项目,因此我最近开始使用工作区功能从一个地方构建所有需要的模块(我觉得非常方便)。

我们不能在iOS上使用自定义框架,因此必须将依赖关系构建为静态库,并且我会遇到标题搜索路径问题。虽然框架在框架包中保留了它们的标头,但静态库没有选项。我讨厌为我导入的每个库单独设置用户标题搜索路径。理想情况下,我想将依赖项目拖到工作区,将库添加到主目标并构建,无需进一步设置。是否支持此工作流程?

3 个答案:

答案 0 :(得分:5)

我目前拥有的最佳解决方案是将所有支持库保留在公共文件夹中(例如Support),将标题搜索路径设置为Support/**。感觉笨拙,但有效。

答案 1 :(得分:3)

我所做的相当复杂,但对我来说效果很好。

在静态库项目的设置中,在“Packaging”部分中,我将“Wrapper Extension”设置为“framework”。然后我改变了:

"Public Headers Folder Path" to "$(PRODUCT_NAME).$(WRAPPER_EXTENSION)/Headers"

"Private Headers Folder Path" to $(PRODUCT_NAME).$(WRAPPER_EXTENSION)/PrivateHeaders

构建产品的最终结果是一个名为“MyLibraryName.framework”的文件夹,其内容看起来就像......好吧......一个框架。我喜欢这件事的一件事是我可以在我的代码中使用Framework样式包含:

#include <MyLibraryName/blah.h>

缺点是(正如“zoul”的回答中所发现的那样)“归档”命令无法正常工作。它不起作用的原因是Archive命令将最终构建产品和目标构建产品分离到单独的目录中。正常的“构建”不会这样做。归档时,系统会尝试在最终构建产品目录中查找静态库头,但由于系统将它们放在静态库的目标构建目录中,因此无法找到它们。

如果您考虑一下,Xcode认为您的静态库的目标只有一个“产品”。该产品是“libMyLibraryName.a”。但实际上目标有两个产品......一个是库,另一个是库的头集。 Archive命令的问题在于库是作为构建产品复制的,但标题不是。当您尝试运行存档时,最终会出现“无法找到标题”。

要解决这个问题,我所做的就是使用Run Script构建阶段。脚本看起来像这样(用Ruby编写):

if ENV["TARGET_BUILD_DIR"] != ENV["BUILT_PRODUCTS_DIR"] then
  $product_name = ENV['PRODUCT_NAME']
  $wrapper_extension = ENV['WRAPPER_EXTENSION']
  $target_build_dir = ENV['TARGET_BUILD_DIR']
  $built_products_dir = ENV['BUILT_PRODUCTS_DIR']

  $source_file = File.join($target_build_dir, $product_name + "." + $wrapper_extension)
  $dest_file = File.join($built_products_dir, $product_name + "." + $wrapper_extension)

  system "ln -s #{$source_file} #{$dest_file}" if File.exist?($source_file)
end

因此,如果Target构建目录和构建的产品目录不匹配...创建一个符号链接,指向我在构建的产品目录中创建的虚假“框架”。

正如我所说,这是一个复杂的方案,但它有效,让我使用我喜欢的框架式包含。如果Xcode允许iOS开发人员创建Frameworks(这也意味着iOS会让开发人员创建动态库,Apple不愿意这样做),或者Apple会创建一个框架变体,那么整个混乱将会大大简化......它包含一个静态库和随之而来的头文件(static_framework?),这样你就有了一个包含头文件和静态库的构建产品。

答案 2 :(得分:2)

我发现我可以将静态库标题设置为Headers文件夹(而不是默认的/usr/local/include)。此文件夹将显示在build-products文件夹中,我可以将用户标题搜索路径设置为$(BUILT_PRODUCTS_DIR)并递归。

如果所有库都设置为将其公共标题复制到此文件夹,我会得到所需的行为 - 添加新的依赖项时,我只需将项目拖到工作区,设置链接依赖项,我很高兴去。