我能否在另一个框架中包含一个框架?

8

我正在编写一个框架(称为Lighthouse.framework),它使用另一个框架的代码(确切地说是RegexKit.framework)。我已经将RegexKit.framework复制到我的框架中,使其具有以下结构:

Lighthouse.framework/
  Versions/
    A/
      Frameworks/
        RegexKit.framework
      Lighthouse

然而,当我尝试运行使用Lighthouse.framework(我的框架)的应用程序时,出现以下错误:
dyld: 库未加载:@executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit 引用位置:/Users/mdippery/Developer/Projects/Current/lighthouse/build/Debug/Lighthouse.framework/Versions/A/Lighthouse 原因:找不到图像
显然,装载器找不到RegexKit。
这是装载器期望加载的路径,感谢otool提供支持:
build/Debug/Lighthouse.framework/Versions/A/Lighthouse:
    /Users/mdippery/Library/Frameworks/Lighthouse.framework/Versions/A/Lighthouse (compatibility version 1.0.0, current version 1.0.0)
    /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
    @executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit (compatibility version 0.4.0, current version 0.6.0)
    /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.4)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.19.0)
    /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 677.26.0)

我能将一个框架包含在另一个框架中吗?这是正确的做法吗?如何解决我的错误?


这里是如何将一个框架包含在另一个框架中的方法。https://dev59.com/wV4c5IYBdhLWcg3w1dLx#27638841 这被称为 umbrella framework。 - Mohd Iftekhar Qurashi
可能是重复的问题:如何在iOS SDK中创建一个Umbrella Framework? - Mohd Iftekhar Qurashi
3个回答

8
最简单的方法是使用@rpath。您的配置应该如下所示:
  1. 将RegExKit.framework的安装目录设置为@rpath
  2. 将Lighthouse.frameworks的安装目录设置为@rpath
  3. 将Lighthouse.framework的Runpath搜索路径设置为@loader_path/Frameworks
  4. 确保将RegExKit.framework复制到Lighthouse.framework的Framework子文件夹中(使用自定义构建阶段)
最后,任何链接到Lighthouse.framework的应用程序都应将Runpath搜索路径设置为@loader_path/../Frameworks。

我没有构建RegexKit.framework(我正在使用预编译的二进制文件)。我仍然可以为它设置安装目录吗(我没有看到如何做到这一点)? - mipadi
1
你可以使用install_name_tool来实现这个功能,类似于install_name_tool -change @executable_path/../Frameworks @rpath/Frameworks。 - sbooth

1
我发现了解决这个问题的方法。我结合了sbooth的答案中的一些想法,但是修复方法更简单。我运行了这个脚本:
install_name_tool -change @executable_path/../Frameworks/RegexKit.framework/Versions/A/RegexKit @loader_path/Frameworks/RegexKit.framework/Versions/A/RegexKit "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.framework/Versions/A/${PRODUCT_NAME}"

作为运行构建脚本阶段。
请注意,对于一般情况,您必须将@executable_path/../更改为@loader_path/,这样一切都很好。

你把这个构建脚本放在哪里了?是在框架产品还是聚合产品中? - Pablo Romeu

1

可以的。

但是,在构建时,您需要包含框架“知道”其安装位置; 否则,dyld在运行时将无法找到它,就像您看到的那样。

如果我没记错的话,XCode中相关的设置是“安装目录”和“框架安装名称”。后者可能对您的使用不重要,但您需要前者类似于:@executable_path/../Frameworks/Lighthouse.framework/Versions/A/Frameworks/RegexKit.framework/Versions/A/


我在构建 Lighthouse.framework(用于 Lighthouse.framework)时,需要设置安装目录吗?我尝试过了,但它并没有起作用(虽然也许是我做错了什么)。 - mipadi
@mipadi:如果你没有构建RegExKit.framework,你将无法做到这一点。为什么你想要将RegExKit包含在其他框架中?你所做的事情即使没有它也可以正常工作。 - Stephen Canon
如果使用我的框架的消费者只需要包含我的框架,而不需要包含我的框架依赖项,那就太好了。 - mipadi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接