【问题标题】:Xcode 4 can't locate public header files from static library dependencyXcode 4 无法从静态库依赖项中找到公共头文件
【发布时间】:2011-07-29 11:14:23
【问题描述】:

辅助搜索的替代标题

  • Xcode 找不到标头
  • Xcode 中缺少 .h
  • 未找到 Xcode .h 文件
  • 找不到词法或预处理器问题文件

我正在开发一个来自 Xcode 3 的 iOS 应用程序项目。我现在已经转移到 Xcode 4,我的项目构建了许多静态库。

这些静态库还声明公共头文件,并且这些头文件由应用程序代码使用。在 Xcode 3.x 中,标头被复制(作为构建阶段)到 public headers directory,然后在应用程序项目中,public headers directory 被添加到 headers search list

在 Xcode 4 下,构建目录移动到 ~/Library/Developer/Xcode/DerivedData/my-project

问题是如何在标题搜索设置中引用这个新位置?看来:

  • public headers directory 相对于 DerivedData 目录,但是
  • headers search 目录相对于其他东西(可能是项目位置)

我应该如何在 Xcode 4 中为 iOS 开发设置一个静态库目标,以确保在尝试编译为依赖项时使用静态库的客户端可以使用头文件?

【问题讨论】:

标签: xcode4 header preprocessor static-libraries


【解决方案1】:

我看到的解决这个问题的每个解决方案要么看起来不优雅(将标头复制到应用程序的项目中),要么过于简化,以至于它们只能在琐碎的情况下工作。

简短的回答

将以下路径添加到您的用户标题搜索路径

“$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts”

为什么会这样?

首先,我们需要了解问题所在。在正常情况下,也就是说当你运行、测试、分析或分析时,Xcode 会构建你的项目并将输出放在 Build/Products/Configuration/Products 目录中,该目录可以通过 $BUILT_PRODUCTS_DIR 宏。

大多数关于静态库的指南建议将 Public Headers 文件夹路径 设置为 $TARGET_NAME,这意味着您的 lib 文件变为 $BUILT_PRODUCTS_DIR/ libTargetName.a 和您的标头被放入 $BUILT_PRODUCTS_DIR/TargetName。只要您的应用在其搜索路径中包含 $BUILT_PRODUCTS_DIR,那么导入将在上述 4 种情况下工作。但是,当您尝试存档时,这将不起作用。

存档的工作方式略有不同

当您归档项目时,Xcode 会使用另一个名为 ArchiveIntermediates 的文件夹。在该文件夹中,您将找到 /YourAppName/BuildProductsPath/Release-iphoneos/。这是您进行归档时 $BUILT_PRODUCTS_DIR 指向的文件夹。如果您在那里查看,您会看到构建的静态库文件有一个符号链接,但缺少带有标题的文件夹。

要查找头文件(和 lib 文件),您需要转到 IntermediateBuildFilesPath/UninstalledProducts/。还记得当您被告知将静态库的 Skip Install 设置为 YES 时吗?这就是设置存档时的效果。

旁注:如果您没有将其设置为跳过安装,您的标头将被放置到另一个位置,并且 lib 文件将被复制到您的存档中,从而阻止您导出可以提交到的 .ipa 文件应用商店。

经过大量搜索,我找不到与UninstalledProducts文件夹完全对应的宏,因此需要使用“$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts”构造路径

总结

对于您的静态库,请确保您跳过安装并将您的公共标头放入 $TARGET_NAME。

对于您的应用,将您的用户标头搜索路径设置为“$(BUILT_PRODUCTS_DIR)”,它适用于常规构建,以及“$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts”,它适用于归档构建。

【讨论】:

  • 这与 DerivedData 文件夹有何关系?
  • 常规构建转到:DerivedData/WorkspaceName-hash/Build/Products/Debug-iphoneos/TargetName.app --- 归档构建转到:DerivedData/WorkspaceName-hash/Build/Intermediates/ArchiveIntermediates/ TargetName/BuildProductsPath/Release-iphoneos/TargetName.app
  • 对我来说,使用带有递归复选框的“$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts”不起作用。只要我使用没有递归标志的“$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/”,它就对我有用。
  • 请注意,您的 $(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts 实际上是 $(TARGET_BUILD_DIR)。即使在存档时。 ;)
  • 对于我在 Xcode 5 中:$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/include/NAME OF LIBRARY 我没有设置为 YES:始终搜索用户路径。
【解决方案2】:

我在开发自己的静态库时遇到了同样的问题,尽管 Colin 的回答非常有帮助,但在使用 Workspace 在 Xcode 4 下运行和归档项目时,我必须对其进行一些修改以使其工作一致且简单。

我的方法的不同之处在于您可以为所有构建配置使用单个用户标头路径。

我的方法如下:

创建工作区

  1. 在 Xcode 4 下,转到文件、新建、工作区。
  2. 然后,您可以从 Finder 中将 .xcodeproj 项目拖入您想要使用的静态库以及您正在构建的使用该库的新应用程序中。有关设置工作区的更多信息,请参阅 Apple Docs:https://developer.apple.com/library/content/featuredarticles/XcodeConcepts/Concept-Workspace.html

静态库项目设置

  1. 确保所有静态库的标头都设置为复制到“公共”。这是在静态库目标 > 构建阶段的设置下完成的。在“复制标题”阶段,确保所有标题都在“公共”部分中。
  2. 接下来转到构建设置,找到“公共标题文件夹路径”并输入库的路径。我选择使用这个:

包括/图书馆名称

我已将它与 RestKit 一起使用,并发现它最适合我的所有静态库。这样做是告诉 Xcode 将我们在步骤 1 中移动到“公共”标题部分的所有标题复制到我们在此处指定的文件夹中,该文件夹在构建时驻留在派生数据文件夹中。与 RestKit 一样,我喜欢使用单个“包含”文件夹来包含我在项目中使用的每个静态库。

我也不喜欢在这里使用宏,因为它允许我们稍后在使用静态库配置项目时使用单个用户标头搜索路径。

  1. 找到“跳过安装”并确保将其设置为“是”。

使用静态库的项目设置

  1. 在 Build Phases > Link Binary With Libraries 下将静态库添加为框架,并为要使用的任何静态库添加 libLibraryName.a 文件。
  2. 接下来确保项目设置为搜索用户搜索路径。这是在 Build Settings > Always Search User Paths 下完成的,并确保将其设置为 YES。
  3. 在同一区域找到 User Header Search Paths 并添加:

    "$(PROJECT_TEMP_DIR)/../UninstalledProducts/include"

这告诉 Xcode 在 Xcode 在构建过程中创建的中间构建文件夹中查找静态库。在这里,我们有一个“include”文件夹,用于我们在步骤 2 中为静态库项目设置设置的静态库位置。这是让 Xcode 正确找到静态库的最重要步骤。

配置工作区

在这里我们要配置工作区,以便在我们构建应用程序时它会构建静态库。这是通过编辑用于我们应用程序的方案来完成的。

  1. 确保您已选择将创建您的应用程序的方案。
  2. 从方案下拉菜单中,选择编辑方案。
  3. 选择左侧列表顶部的构建。按中间窗格上的 + 添加新目标。
  4. 您应该会看到您尝试链接的库的静态库。选择 iOS 静态库。
  5. 单击运行和存档。这会告诉方案在您构建应用时为静态库编译库。
  6. 将静态库拖到应用程序目标上方。这使得静态库在您的应用程序目标之前编译。

开始使用库

现在,您应该可以使用

导入静态库了
import <LibraryName/LibraryName.h>

这种方法解决了必须为不同的配置使用不同的用户头路径的麻烦,因此编译存档应该没有问题。

为什么会这样?

这一切都取决于这条路:

"$(PROJECT_TEMP_DIR)/../UninstalledProducts/include"

因为我们将静态库配置为使用“跳过安装”,所以编译后的文件被移动到临时构建目录中的“UninstalledProjects”文件夹中。我们这里的路径也解析为我们为静态库设置的“include”文件夹,并用于我们的用户标题搜索路径。两者一起工作让 Xcode 知道在编译过程中在哪里可以找到我们的库。由于 Debug 和 Release 配置都存在这个临时构建目录,因此 Xcode 只需要一个路径即可搜索静态库。

【讨论】:

  • 你太棒了,伙计!这真的很有帮助,而且正如你所描述的那样工作。
  • 太棒了。我应该在哪里送花:)
  • 设置后,有些人可能会遇到“...] unrecognized selector sent to class 0x...”。如果您这样做,请尝试将其添加到项目的 Targets->Project->Build Settings->Linking->Other Linker Flags-all_load
  • 如果用户标题搜索路径有空格,请确保它们用引号引起来。
  • Xcode 4.6.2 没有为我写任何内容到“$(PROJECT_TEMP_DIR)/../UninstalledProducts/include”。知道我错过了什么吗?还是 Xcode 的行为再次发生了变化?
【解决方案3】:

Xcode 4 项目编译静态库失败

相关问题:“lexical or preprocessor issue file not found ” in Xcode 4

错误可能包括:缺少头文件、“词法或预处理器问题”

解决方案:

  1. 检查“用户标头路径”是否正确
  2. 将“始终搜索用户路径”设置为是
  3. 在您的项目中创建一个名为“Indexing headers”的组并将标题拖到该组,不要在出现提示时添加到任何目标。

【讨论】:

  • 另一个容易被忽视但极其重要的步骤:确保您的搜索路径用双引号括起来以转义任何空格。我总是忘记这样做。
  • 感谢@Brad,这确实是一个非常重要和有帮助的评论。
【解决方案4】:

这是一个非常有用的线程。在研究我自己的情况时,我发现 Apple 有一份 2012 年 9 月的 12 页文档,标题为“在 iOS 中使用静态库”。这是pdf链接:http://developer.apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf

它比大多数 Internet 讨论要简单得多,并且通过一些小模块来说明我正在使用的外部库的配置方式,它对我来说效果很好。最重要的部分可能是:

如果您的库目标具有“复制标头”构建阶段,您应该 删除它;复制标头构建阶段不能与静态一起正常工作 在 Xcode 中执行“存档”操作时的库目标。

使用 Xcode 4.4 或更高版本创建的新静态库目标将出现 具有适当配置的标题复制文件阶段,因此您 在创建一个之前应该检查你是否已经有一个。如果 你没有,按目标编辑器底部的“添加构建阶段” 并选择“添加复制文件”。披露新的 Copy Files 版本 阶段并将目标设置为“产品目录”。设置子路径 包括/${PRODUCT_NAME}。这会将文件复制到名为 在你的库(取自 PRODUCT_NAME 构建设置)之后,在里面 一个名为 include 的文件夹,位于您构建的产品目录中。这 构建产品目录中的包含文件夹是默认的 应用程序的标头搜索路径,因此这是一个合适的位置 放头文件。

我确信在许多现有情况下,Apple 的方法可能还不够。我在这里为刚开始在静态图书馆花园路径上旅行的任何人发布此信息 - 这可能是简单案例的最佳起点。

【讨论】:

  • 对于那些遵循上述链接的人..当心:在创建库项目时要求您删除虚拟模板文件的步骤..不要删除 *.pch 文件..它会最终会困扰你 + 上述建议不适用于类别.. 不过有一个解决方法(在某处看到)
  • 感谢您提供 Apple 官方构建静态库的方法的链接。我开始使用这个approach 构建我的静态库,但无法存档。 @abbood - 删除生成的pch文件有什么问题?
  • 如果你删除 .pch 文件.. 项目根本不会编译..(出于存档或其他目的)..
  • 它对我不起作用。当我尝试使用 "" 导入语句时它不起作用我需要 。而且在归档时它无法找到标题。有什么想法吗?
【解决方案5】:

http://developer.apple.com/library/ios/#technotes/iOSStaticLibraries/Articles/creating.html

根据 Apple 文档:

您的库将具有该库的客户端需要导入的一个或多个头文件。要配置将哪些标头导出到客户端,请选择您的库项目以打开项目编辑器,选择库目标以打开目标编辑器,然后选择构建阶段选项卡。如果你的库目标有一个“Copy Headers”构建阶段,你应该删除它;在 Xcode 中执行“存档”操作时,复制标头构建阶段无法与静态库目标一起正常工作。

【讨论】:

    【解决方案6】:

    查看 Jonah Wlliam 的解决方案(中途)和 GitHub 模型(在 cmets 中)以获得洞察力。 http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/

    【讨论】:

    • 虽然这可能在技术上回答问题,it would be preferable 供您在答案中包含链接文章的基本部分,并提供链接以供参考。不这样做会使答案面临链接失效的风险。
    【解决方案7】:

    $(OBJROOT)/UninstalledProducts/exactPathToHeaders 添加到 标题搜索路径。

    由于某种原因,递归复选框对我不起作用,我不得不将路径的其余部分添加到标题所在的位置。

    在 Xcode 中的 Log Navigator(断点导航器右侧的选项卡)下,您可以看到构建历史记录。如果您选择实际构建失败,您可以展开其详细信息以查看 setenv PATH 并检查以确保您的头文件的路径在那里。

    【讨论】:

    • 关于递归复选框的好注释,同样的问题。
    • 是的,我还必须指定一个特定的子文件夹,检查递归不起作用。
    • 我最终还是使用了这条路径(只是因为它更短)“$(PROJECT_TEMP_DIR)/../UninstalledProducts/SubProjectHeaders”
    【解决方案8】:

    上面的答案在 Xcode 7 上都不适合我,但它们给了我一个好主意。对于在 Xcode 7 上苦苦挣扎的人,我通过将以下内容添加到用户标题搜索路径(包括引号)来解决此问题

    "$(BUILT_PRODUCTS_DIR)/usr/local/include"
    

    根据静态库的“Public Header Folder Path”设置中的内容更改相对URL部分usr/local/include

    【讨论】:

      【解决方案9】:

      在我的情况下,我的工作区有几个静态库项目,其中一个具有依赖关系,包括与另一个的头文件。问题在于建造顺序。在 Build 部分下的编辑 Scheme 页面中,我取消了并行化选项并根据依赖关系排列了目标的顺序,并通过问题解决了

      【讨论】:

        【解决方案10】:

        将以下路径添加到您的用户标题搜索路径:

        $(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts
        

        这是经过验证的!

        【讨论】:

          【解决方案11】:

          冒着暴露自己是个白痴的风险......我整个下午都在忍受 XCode 拒绝找到我的 .h 文件的痛苦。

          然后我意识到了。

          因为我使用的是“XCode 4”,所以我“明智地”决定将我的所有项目放在一个名为“XCode 4 projects”的文件夹的子文件夹中。

          文件夹名称中的那些空格把 XCode 搞砸了!

          将此文件夹重命名为“XCode_4_Projects”给我的生活带来了欢乐(也少了脏话)。

          再次提醒我,今年是什么年?

          也许有人可以告诉苹果开发者...

          【讨论】:

            【解决方案12】:

            这些答案都不适合我。这是做了什么。将以下内容准确添加(复制并粘贴,包括双引号)到您的 User Header Search Paths 构建设置:

            "$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/include/"
            

            请注意,与其他答案相比,添加了“/include/”子目录。正如其他用户所指出的,“递归”选项似乎没有任何作用,因此您可以忽略它。

            我的项目现在可以在导入以下形式的静态库头文件时成功归档:

            #import "LibraryName/HeaderFile.h"
            

            您确实不需要启用 始终搜索用户路径 设置,除非您使用尖括号 (#import &lt;LibraryName/HeaderFile.h&gt;) 包含静态库标题,但您确实应该如果它不是系统/框架头文件,无论如何都不要这样做。

            【讨论】:

              【解决方案13】:

              这是导致我提出这个问题的一个相关问题,所以我将我的解决方案严格添加为文档/它可以节省另一个灵魂出汗的时间

              DropboxSDK.h 文件未找到

              在尝试让 VES 为 iOS 编译几天后,我最终遇到了这个问题。 DropboxSDK.h 绝对可以到达search headers 我什至将它添加到framework headers 搜索路径,included 直接.h 并竭尽全力尝试找到DropboxSDK.h

              解决方案

              EXPLICITYDropboxSDK.framework 文件拖入Xcode 的Project Navigation 并确保选中Copy Files if needed。还要确保根据需要检查您的目标。

              警告

              build phases 中设置显式框架位置对我不起作用。我必须将 .framework 到 Xcode 中,并确保将文件复制到我的项目中。

              #mbp2015 #xcode7 #ios9

              【讨论】:

                【解决方案14】:

                有各种复杂的方法可以做到这一点,并且在这个线程中提出了一些非常聪明的解决方案。

                所有这些解决方案的主要问题是它严重降低了库的可移植性。

                • 每次您需要使用您的资料库开始一个新项目并将其存档到 iTunes 时, 这是一个配置地狱。
                • 每次您需要分享您的项目 对于您的团队或客户,它可能因任何原因而中断(上下文, Xcode 版本,随便,..)

                我的选择最终还是按照 Apple 的推荐(WWDC 视频)简单地使用框架。

                这很容易,最后做同样的工作!

                另一个似乎可行的非常优雅的解决方案是使用 Private Cocoapods。 Cocoapods 完成所有的配置工作,头文件复制等等。

                框架摇滚!

                【讨论】:

                • 你在哪里设置这个? simply use frameworks - always -
                • 它没有设置在任何地方。这只是一种架构选择。框架是更容易链接和管理的“现代库”。在此消息发布时,swift 仍然不允许构建二进制库。
                【解决方案15】:

                这就是为我解决同样问题的方法。

                我有一个 App Target 和一个 iMessage Extension Target。 然后我有 2 个 SDK(我自己的),App Target 链接到它们。

                问题是:我的 iMessage 目标也使用了我的 2 个 SDK(单独的项目),但它没有在 Build Phases 中链接它们 --> Link Binary With Libraries。我必须将我的 2 个 SDK 添加到那里的 iMessage Target 中,以匹配我的 App 目标,现在它存档了。

                所以这个故事的寓意是:如果您有多个目标,例如扩展,请确保您的所有目标都链接到他们需要的库。它能够构建和部署到模拟器和设备,但不能存档。

                【讨论】:

                  【解决方案16】:

                  更新:Xcode 9

                  上面的答案对我使用 Xcode 9 无效,但这个 answer 对我来说非常有效。我已将$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include 添加到我的“标题搜索路径”中,Xcode 确实链接了我的静态库的标题,没有任何问题。

                  【讨论】:

                    【解决方案17】:

                    省去麻烦,然后这样做 = 在您的 Mac 上创建新用户帐户 -- 在新用户帐户下打开项目 -- 所有问题都消失了。节省您的时间并保持理智。所有那些书呆子的回复都无济于事!

                    祝你好运

                    【讨论】:

                      猜你喜欢
                      • 2023-03-03
                      • 1970-01-01
                      • 2012-01-28
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-08-23
                      • 2019-12-19
                      • 1970-01-01
                      相关资源
                      最近更新 更多