Xcode 4可以从静态库依赖关系中找到公共标头文件
辅助搜索的备用标题
- Xcode 找不到标头
- Xcode 中缺少 .h
- 未找到 Xcode .h 文件
- 未找到词法或预处理器问题文件
我正在处理来自 Xcode 3 的 iOS 应用程序项目。我现在已转移到 Xcode 4 我的项目构建了一些静态库。
这些静态库还声明公共标头,并且这些标头由应用程序代码使用。在 Xcode 3.x 中,标头被复制(作为构建阶段)到公共标头目录
,然后在应用程序项目中,公共标头目录
被添加到>标题搜索列表
。
在 Xcode 4 下,构建目录被移动到 ~/Library/Developer/Xcode/DerivedData/my-project
。
问题是如何在标题搜索设置中引用这个新位置?看起来:
public headers目录
是相对于DerivedData
目录,但是headers search
目录是相对于其他东西(可能是项目位置)
如何我是否应该在 Xcode 4 中为 iOS 开发设置一个静态库目标,以确保在尝试编译为依赖项时使用静态库的客户端可以使用头文件?
Alternate titles to aid search
- Xcode can't find header
- Missing .h in Xcode
- Xcode .h file not found
- lexical or preprocessor issue file not found
I'm working on an iOS application project which came from Xcode 3. I have now moved to Xcode 4 my project builds a number of static libraries.
Those static libraries also declare public headers and those headers are used by the application code. In Xcode 3.x the headers were copied (as a build phase) to the public headers directory
, then in the application project the public headers directory
was added to the headers search list
.
Under Xcode 4 the build directory is moved to ~/Library/Developer/Xcode/DerivedData/my-project
.
The problem is how do I reference this new location in the headers search settings? It seems that:
public headers directory
is relative toDerivedData
directory, butheaders search
directory is relative to something else (possibly the project location)
How should I set up a static library target for iOS development in Xcode 4 that will ensure the header files are made available to the clients that use the static library when trying to compile as a dependancy?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
我见过的解决这个问题的每个解决方案要么看起来不优雅(将标头复制到应用程序的项目中),要么过于简化以至于它们只能在微不足道的情况下工作。
简短回答
将以下路径添加到您的用户标题搜索路径
为什么这有效?
首先,我们需要了解问题。在正常情况下,也就是说,当您运行、测试、分析或分析时,Xcode 会构建您的项目并将输出放入 Build/Products/Configuration/Products 目录中,该目录可通过 < strong>$BUILT_PRODUCTS_DIR 宏。
大多数有关静态库的指南建议将公共标头文件夹路径设置为$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/。还记得当您被告知将静态库的跳过安装设置为“是”吗?这就是您制作存档时设置的效果。
旁注:如果您不将其设置为跳过安装,您的标头将被放入另一个位置,并且 lib 文件将被复制到您的存档中,从而阻止您导出可以提交到 App Store 的 .ipa 文件。
经过大量搜索,我找不到任何与 UninstalledProducts 文件夹完全对应的宏,因此需要使用“$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts”构建路径
摘要
对于您的静态库,请确保您跳过安装并将公共标头放入 $TARGET_NAME 中。
对于您的应用程序,将用户标头搜索路径设置为“$(BUILT_PRODUCTS_DIR)”(适用于常规构建)和“$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts”(适用于存档构建)。
Each of the solutions I've seen to this problem have either seemed inelegant (copying headers into the application's project) or overly simplified to the point that they only work in trivial situations.
The short answer
Add the following path to your User Header Search Paths
Why does this work?
First, we need to understand the problem. Under normal circumstances, which is to say when you Run, Test, Profile or Analyze, Xcode builds your project and puts the output in the Build/Products/Configuration/Products directory, which is available via the $BUILT_PRODUCTS_DIR macro.
Most guides regarding static libraries recommend setting the Public Headers Folder Path to $TARGET_NAME, which means that your lib file becomes $BUILT_PRODUCTS_DIR/libTargetName.a and your headers are put into $BUILT_PRODUCTS_DIR/TargetName. As long as your app includes $BUILT_PRODUCTS_DIR in its search paths, then imports will work in the 4 situations given above. However, this will not work when you try to archive.
Archiving works a little differently
When you archive a project, Xcode uses a different folder called ArchiveIntermediates. Within that folder you'll find /YourAppName/BuildProductsPath/Release-iphoneos/. This is the folder that $BUILT_PRODUCTS_DIR points to when you do an archive. If you look in there, you'll see that there is a symlink to your built static library file but the folder with the headers is missing.
To find the headers (and the lib file) you need to go to IntermediateBuildFilesPath/UninstalledProducts/. Remember when you were told to set Skip Install to YES for static libraries? Well this is the effect that setting has when you make an archive.
Side note: If you don't set it to skip install, your headers will be put into yet another location and the lib file will be copied into your archive, preventing you from exporting an .ipa file that you can submit to the App Store.
After a lot of searching, I couldn't find any macro that corresponds to the UninstalledProducts folder exactly, hence the need to construct the path with "$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts"
Summary
For your static library, make sure that you skip install and that your public headers are placed into $TARGET_NAME.
For your app, set your user header search paths to "$(BUILT_PRODUCTS_DIR)", which works fine for regular builds, and "$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts", which works for archive builds.
我在开发自己的静态库时遇到了同样的问题,尽管 Colin 的答案非常有帮助,但我必须对其进行一些修改,以便在使用工作区在 Xcode 4 下运行和存档项目时一致且简单地工作。
我的方法的不同之处在于您可以对所有构建配置使用单个用户标头路径。
我的方法如下:
创建工作区
静态库项目设置
我在 RestKit 中采用了它,并发现它最适合我的所有静态库。它的作用是告诉 Xcode 将我们在步骤 1 中移动到“公共”标头部分的所有标头复制到我们在此处指定的文件夹,该文件夹在构建时位于 Derived Data 文件夹中。与 RestKit 一样,我喜欢使用单个“include”文件夹来包含我在项目中使用的每个静态库。
我也不喜欢在这里使用宏,因为它允许我们稍后在使用静态库配置项目时使用单个用户标头搜索路径。
使用静态库的项目设置
在同一区域中找到“用户标题搜索路径”并添加:
“$(PROJECT_TEMP_DIR)/../UninstalledProducts/include”
这告诉 Xcode 查找用于 Xcode 在构建过程中创建的中间构建文件夹中的静态库。在这里,我们有用于静态库位置的“include”文件夹,我们在步骤 2 中为静态库项目设置设置了该位置。这是让 Xcode 正确找到静态库的最重要的一步。
配置工作区
这里我们要配置工作区,以便在我们构建应用程序时它将构建静态库。这是通过编辑我们的应用程序使用的方案来完成的。
开始使用库
现在,您应该能够使用以下方法导入静态库。
此方法解决了不同配置必须具有不同用户标头路径的麻烦,因此编译存档应该没有问题。
为什么这有效?
这一切都取决于此路径:
因为我们将静态库配置为使用“Skip Install”,所以编译后的文件将移动到临时构建目录中的“UninstalledProjects”文件夹中。我们此处的路径也解析为我们为静态库设置并用于用户标头搜索路径的“include”文件夹。两者一起工作让 Xcode 知道在编译过程中在哪里可以找到我们的库。由于调试和发布配置都存在此临时构建目录,因此您只需要 Xcode 的单个路径即可搜索静态库。
I ran into this same issue when developing my own static library and although Colin's answer was very helpful, I had to modify it a bit to work consistently and simply when both running and archiving projects under Xcode 4 using a Workspace.
What's different about my method is you can use a single user header path for all your build configurations.
My method is as follows:
Create a Workspace
Static Library Project Settings
I've adopted this from use with RestKit and found it works best with all my static libraries. What this does is tells Xcode to copy all the headers we moved to the "Public" headers section in step 1 to the folder we specify here which resides within the Derived Data folder when building. Like with RestKit, I like using a single "include" folder to contain each static library I'm using in a project.
I also don't like using macros here because it will allow us to use a single user header search path later when we configure the project using the static library.
Settings for the Project Using the Static Library
In the same area find User Header Search Paths and add:
"$(PROJECT_TEMP_DIR)/../UninstalledProducts/include"
This tells Xcode to look for static libraries within the intermediate build folder that Xcode creates during the build process. In here, we have the "include" folder we are using for our static library locations we setup in step 2 for the static library project settings. This is the most important step in getting Xcode to correctly find your static libraries.
Configure the Workspace
Here we want to configure the workspace so that it will build the static library when we build our app. This is done by editing the scheme used for our app.
Start Using the Library
Now, you should be able to import your static library using
This method gets around the hassle of having to have different user header paths for different configurations, so you should have no problem compiling for archives.
Why does this work?
It all depends on this path:
Because we configure our static library to use "Skip Install", the compiled files are moved to the "UninstalledProjects" folder within the temporary build directory. Our path here also resolves to the "include" folder we setup for our static library and use for our user header search path. The two working together lets Xcode know where to find our library during the compile process. Since this temporary build directory exists for both Debug and Release configurations, you only need a single path for Xcode to search for static libraries.
Xcode 4 项目无法编译静态库
错误可能包括:缺少头文件、“词法或预处理器问题”
解决方案:
Xcode 4 Project Fails to compile a static library
Errors might include; missing header files, "lexical or preprocessor issue"
Solutions:
这是一个非常有帮助的线程。在研究我自己的情况时,我发现 Apple 有一份 2012 年 9 月的 12 页文档,标题为“在 iOS 中使用静态库”。这是 pdf 链接: http://developer.apple.com/library/ios/technotes/iOSStaticLibraries /iOSStaticLibraries.pdf
它比大多数互联网讨论要简单得多,并且通过一些小修改来说明我正在使用的外部库的配置方式,它对我来说效果很好。最重要的部分可能是:
我确信,在许多现有情况下,苹果的方法可能还不够。我在这里为那些刚刚开始静态图书馆花园路径之旅的人发布此内容 - 这可能是简单案例的最佳起点。
This was a very helpful thread. In researching for my own situation, I found that Apple has a 12-page document dated September 2012 titled "Using Static Libraries in iOS." Here's the pdf link: http://developer.apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf
It's much simpler than most of the Internet discussion, and with some small mods to account for how the external libraries I'm using are configured, it's working well for me. The most important part is probably:
I am sure that in many existing situations Apple's approach may not be enough. I post this here for anyone who is just beginning their journey on the static library garden path - this may be the best starting point for simple cases.
http://developer.apple.com/library/ios/ #technotes/iOSStaticLibraries/Articles/creating.html
根据 Apple 文档:
您的库将具有该库的客户端需要导入的一个或多个头文件。要配置将哪些标头导出到客户端,请选择库项目以打开项目编辑器,选择库目标以打开目标编辑器,然后选择构建阶段选项卡。如果您的库目标有“复制标头”构建阶段,您应该删除它;在 Xcode 中执行“存档”操作时,复制标头构建阶段无法与静态库目标正常工作。
http://developer.apple.com/library/ios/#technotes/iOSStaticLibraries/Articles/creating.html
Per Apple documention:
Your library will have one or more header files that clients of that library need to import. To configure which headers are exported to clients, select your library project to open the project editor, select the library target to open the target editor, and select the build phases tab. If your library target has a “Copy Headers” build phase, you should delete it; copy headers build phases do not work correctly with static library targets when performing the “Archive” action in Xcode.
看看 Jonah Wlliam 的解决方案(中间向下)& GitHub 模型(在评论中)以获得见解。
http://blog. Carbon Five.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/
Take a look at Jonah Wlliam's solution (mid way down) & GitHub model (in comments) for an insight.
http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/
将 $(OBJROOT)/UninstalledProducts/exactPathToHeaders 添加到标题搜索路径。
由于某种原因,递归复选框对我不起作用,我必须添加其余的标头所在位置的路径。
在 Xcode 中的日志导航器(断点导航器右侧的选项卡)下,您可以看到构建历史记录。如果您选择实际构建失败,您可以展开其详细信息以查看 setenv PATH 并检查以确保头文件的路径在那里。
Add $(OBJROOT)/UninstalledProducts/exactPathToHeaders to the Header Search Paths.
For some reason the recursive checkbox didn't work for me and I had to add the rest of the path to where the headers are located.
Under the Log Navigator in Xcode (the tab to the right of the break points navigator) you can see the build history. If you select the actual build failure you can expand its details to see the setenv PATH and check to make sure the path to your header files is there.
上面的答案在 Xcode 7 上都不适合我,但它们给了我一个好主意。对于那些在 Xcode 7 上苦苦挣扎的人,我通过将以下内容添加到用户头搜索路径(包括引号)来解决此问题
根据“公共头文件夹”中的内容更改相对 URL 部分
usr/local/include
静态库路径设置None of the answers above worked for me on Xcode 7 but they gave me a good idea though. For guys struggling on Xcode 7, I got this fixed by adding the following to User Header Search Paths (include quotes)
Change the relative URL part
usr/local/include
according to what's there in 'Public Header Folder Path' setting of static library就我而言,我的工作区有几个静态库项目,其中一个项目具有依赖关系,包括与另一个项目的头文件。问题出在建造顺序上。在“构建”部分下的“编辑方案”页面中,我取消选择并行化选项并根据依赖关系排列目标的顺序,并解决了问题
In my case my workspace had a couple of static library projects and one of them has dependency including header files with the other. The issue was with the order of building . In edit Scheme page under Build section, I deselected parallelize option and arranged the order of the targets as per the dependencies and it solved by problem
将以下路径添加到您的用户标题搜索路径中:
已验证!
Add the following path to your User Header Search Paths:
This is verified!
冒着暴露我是个白痴的风险...我整个下午都在遭受 XCode 拒绝找到我的 .h 文件的痛苦。
然后我意识到了。
因为我使用的是“XCode 4”,所以我“明智地”决定将所有项目放入名为“XCode 4 项目”的文件夹的子文件夹中。
文件夹名称中的那些空格将 XCode 搞得一团糟!
将此文件夹重命名为“XCode_4_Projects”给我的生活带来了欢乐(并且减少了咒骂)。
再次提醒我,今年是哪一年?
也许有人可以告诉苹果开发者......
At the risk of showing what an idiot I am... I've been suffering from XCode refusing to find my .h files all afternoon.
Then I realised.
Because I was using "XCode 4", I had "intelligently" decided to put all of my projects in a subfolders of a folder called "XCode 4 projects".
Those spaces in the folder name messed up XCode big-time !
Renaming this folder to "XCode_4_Projects" has brought joy (and less swearing) back into my life.
Remind me again, what year is this ?
Perhaps someone could tell the Apple developers...
这些答案都不适合我。这就是所做的。将以下内容准确添加(复制并粘贴,包括双引号)到您的用户标头搜索路径构建设置:
请注意与其他答案相比,添加了“/include/”子目录。正如其他用户所指出的,“递归”选项似乎没有做任何事情,因此您可以忽略它。
的项目现在能够在以以下形式导入静态库头文件时成功归档:
我 不需要需要启用始终搜索用户路径设置,除非您使用尖括号包含静态库标头(
#import
),但如果它不是系统/框架标头,那么无论如何你都不应该这样做。None of these answers worked for me. Here's what did. Add the following exactly (copy and paste including the double-quotes) to your User Header Search Paths build setting:
Note the addition of the "/include/" subdirectory as compared to other answers. As other users have pointed out, the "recursive" option doesn't seem to do anything, so you can ignore it.
My project was now able to archive successfully when importing static library header files in the following form:
You do not need to enable the Always Search User Paths setting unless you are including your static library headers with angle brackets (
#import <LibraryName/HeaderFile.h>
), but you really shouldn't be doing it that way anyway if it's not a system/framework header.这是一个相关问题,导致我提出这个问题,因此我严格添加我的解决方案以用于文档/它可以节省另一个灵魂时间的汗水
DropboxSDK.h 文件未找到
经过几天的尝试获取 VES为了针对 iOS 进行编译,我最终遇到了这个问题。
DropboxSDK.h
绝对可以到达搜索标头
,我什至将其添加到framework headers
搜索路径,include
直接找到.h
,并竭尽全力尝试找到DropboxSDK.h
。解决方案
EXPLICITY将
DropboxSDK.framework
文件拖动到Xcode的项目导航
中,并确保选中如果需要复制文件
。还要确保根据需要检查您的目标。警告
在
构建阶段
中设置显式框架位置对我来说不起作用。我必须将 .framework拖到 Xcode 中,并确保将文件复制到我的项目中。#mbp2015 #xcode7 #ios9
This is a related issue which led me to this question so I'm adding my solution strictly for documentation / it could save another soul hours of sweating
DropboxSDK.h file not found
After days of trying to get VES to compile for iOS I eventually ran into this issue. the
DropboxSDK.h
was definitely in reach ofsearch headers
I even added it to theframework headers
search path,include
d the.h
directly and went to all sorts of great lengths to try and getDropboxSDK.h
found.Solution
EXPLICITY drag the
DropboxSDK.framework
file into Xcode'sProject Navigation
and make sureCopy Files if needed
is checked. Also make sure your target is checked as needed.Warning
Setting the explicit framework location in
build phases
did not work for me. I had to drag the .framework into Xcode and make sure the files copied to my project.#mbp2015 #xcode7 #ios9
有各种复杂的方法可以做到这一点,并且在此线程中提出了一些非常聪明的解决方案。
所有这些解决方案的主要问题是它严重降低了库的可移植性。
这是一个配置地狱。
与您的团队或客户一起,它可能会因任何原因而中断(上下文、
Xcode 版本,无论如何,..)
我的选择最终是简单地使用框架 - 始终 - 正如 Apple 推荐的(WWDC 视频)。
它是如此简单,并且最终完成相同的工作!
另一个相当优雅且可行的解决方案是使用 Private Cocoapods。
Cocoapods 完成所有配置工作、标头复制等。
框架摇滚!
There is various complex ways to do this, and some very smart solutions are proposed in this thread.
The main problem to all these solution is that it seriously decrease your library portability.
it's a configuration hell.
with your team or customers, it can break for any reason ( context,
Xcode version, whatever,.. )
My choice has been finally to simply use frameworks - always - as recommended by Apple ( WWDC Videos ).
It is so easier and does the same job at the end !
Another quite elegant solution which seems to work is to use Private Cocoapods.
Cocoapods does all the configuration work, header copy and so.
Frameworks rock !
这就是为我解决同样问题的方法。
我有一个应用程序目标和一个 iMessage 扩展目标。
然后我有 2 个 SDK(我自己的),App Target 链接到它们。
问题是:我的 iMessage 目标也在使用我的 2 个 SDK(单独的项目),但它没有在构建阶段中链接到它们 -->将二进制文件与库链接。我必须将我的 2 个 SDK 添加到那里的 iMessage 目标,以匹配我的应用程序目标,现在它已存档。
所以这个故事的寓意是:如果您有多个目标(例如扩展),请确保所有目标都链接到它们所需的库。它能够构建并部署到模拟器和设备,但不能存档。
Here is what solved the same problem for me.
I have an App Target, and an iMessage Extension Target.
Then I had 2 SDKs (my own), which the App Target links against.
The problem was: my iMessage target was also using the 2 SDKs of mine (separate projects), but it wasn't linking against them in Build Phases --> Link Binary With Libraries. I had to add my 2 SDKs to the iMessage Target there, to match my App target, and now it archives.
So the moral of the story is: If you have multiple targets, such as extensions, make sure that all of your targets are linking against the libraries they need. It was able to Build and Deploy to Simulator and Device, but not Archive.
更新:Xcode 9
上述答案对使用 Xcode 9 的我不起作用,但是这个答案非常适合我。我已将
$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include
添加到我的“标头搜索路径”中,并且 Xcode 确实链接了我的静态库的标头,没有任何问题。Update: Xcode 9
The above answers did not work for me using Xcode 9, but this answer worked perfectly for me. I have added
$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include
to my "Header Search Paths" and Xcode did link the header of my static library with no problems.当您创建静态库
.modulemap
时,除了.a
库之外还会生成umbrella.h
要使用 Objective-C 静态库,您应该
[示例]
When you create static library
.modulemap
andumbrella.h
is generated additionally to.a
libraryTo use objective-C static library you should
[Example]
省去麻烦,这样做 = 在 Mac 上创建新用户帐户 - 在新用户帐户下打开项目 - 所有问题都会消失。节省您的时间并保持理智。所有这些书呆子的回复都没有帮助!
祝你好运
Save yourself the trouble and do this = create new user account on your Mac -- open the project under the new user account-- all problems disappear. Save your time and keep your sanity. all of those nerdy replies don't help!!
Good Luck