双直接代码包含在 iOS 产品可能性中
Double direct code inclusion in iOS product possibility
我们工作中的项目依赖于一个名为 "LibraryAlpha" 的动态库。此外,我们工作中的项目依赖于一个名为 "LibraryBeta" 的动态库。而且,恰好 "LibraryBeta" 也依赖于 "LibraryAlpha".
我们的项目嵌入了不同构建的 .framework,即嵌入来自不同 .xcodeproj 的目标。
在以下情况下,"LibraryAlpha" 的符号和实现(函数和 类)以这种或另一种方式两次嵌入到我们项目的包中的可能性有多大:
- "LibraryAlpha" 的项目目标嵌入到项目的包中,"LibraryAlpha" 的项目目标嵌入到 "LibraryBeta" 的包中。
- "LibraryAlpha"的项目目标嵌入到项目的包中,"LibraryAlpha"的源代码与"LibraryBeta"
的源代码静态linked
- "LibraryAlpha" 的项目目标嵌入到项目的包中,只有 "LibraryBeta" link 反对,没有嵌入 "LibraryAlpha"
此外,通常期望使用 SPM 生成的 .xcodeproj 将依赖项模块作为项目中的单独目标,这些目标 link 反对并嵌入到主(声明其依赖项的那个)模块的捆。所以问题是,如果在我们的项目中我 link 和嵌入 "LibraryAlpha" 不是作为项目 "LibraryAlpha" 的目标,而是为 "LibraryAlpha" 生成的目标,会发生什么"LibraryBeta"?
项目中的文件
管理 .xcodeprojs 目标的复杂依赖关系的正确方法是,用问题的数字来说,根本不管理它们:
- 存档->导出->安装"LibraryAlpha"
- Archive->Export->Install "LibraryBeta",linking 对已安装 "LibraryAlpha"
- Archive->Export->Install arbitrary amount of other libraries that all dynamically link against "LibraryAlpha"
- Embed 和 link 反对安装 "LibraryAlpha"、"LibraryBeta" 和朋友。
为了简化Apple-targeted项目中的依赖管理,强烈建议您使用Carthage or CocoaPods等依赖管理器。它们不仅会使部署变得轻而易举,而且还有助于消除将框架全局安装到主机中的需要 OS。
旧的错误答案:
- 将 "LibraryAlpha" 作为一个单独的 .xcodeproj,它有自己的目标来构建自己
- "LibraryBeta" 动态 link 针对特定 "LibraryAlpha" 目标而不嵌入
- 让我们的项目动态地 link 到 "LibraryBeta" 和那个特定的 "LibraryAlpha" 目标,显然,嵌入两者。
这不是 Swift 包管理器在解析依赖项和生成 .xcodeproj 时所做的事情。 SPM 通常最终会将所有源代码放在一个项目中,并在其中为 "LibraryAlpha" 创建一个目标。
这样就没有代码被多次包含,一切都在运行时很好地解析。
这当然没有回答问题,问题只是出于兴趣。但记住这一点很重要。
题错了。里面的一些案例在现实生活中是无法重现的。
首先,"one framework linking against and embedding another framework" 问题中提到的概念甚至不是一回事——事实上,动态 linkage 的整个概念被提升以追求重用相同的共享多个用户之间的对象,无需使相同的代码多次可用(读取、嵌入)。
案例一
记住前面的陈述,第一个案例在现实生活中几乎不可能立即重现,因为案例陈述
"LibraryAlpha"'s project target embedded into "LibraryBeta"'s bundle.
"LibraryBeta" 可能会针对 "LibraryAlpha" 的项目目标进行 link 编辑,为了在运行时使用 "LibraryBeta",可执行文件需要嵌入 "LibraryAlpha".符号的重复在这里是无法实现的,因为 "LibraryAlpha" 只会出现在 bundle 中一次。
案例二
"LibraryAlpha"'s source code statically linked with the source code of "LibraryBeta"
这种情况会导致重复编译代码。一旦它将以动态库 "LibraryAlpha" 的形式出现在 bundle 中,一旦静态 linked 到 "LibraryBeta".
警告:
实际上,在这种情况下,您根本无法编译 "LibraryBeta",假设您的任何源代码文件都在顶部声明 import LibraryAlpha
。 Swift 中的模块不能手动声明,它们的源代码必须位于单独的目标中才能导入。该案例的源代码与 "LibraryBeta" 位于同一模块中,因此编译器将出现 No such module LibraryAlpha
.
错误
案例三
"LibraryBeta" only linking against, without embedding, "LibraryAlpha"
实际可行的解决方案,不会导致任何代码重复。
案例四
...link and embed "LibraryAlpha" not as a target from a project "LibraryAlpha", but that one generated target for "LibraryAlpha"'s files in the project of "LibraryBeta"
在这种情况下不会出现代码重复。
奖金回合:
对于第 4 种情况,除了你不会重用目标。
通过 linking "LibraryBeta" 针对一个动态库,但嵌入另一个动态库...有两种结果。
假设相同的源代码和相同的配置应该产生相同的动态库、具有相同目标代码的相同 .framework 文件夹、.swiftmodule、.swiftdoc、dSYM 和一切,即使它是不同项目中的两个不同目标。因此,如果生成的 .framework 恰好与 2 个不同项目中的 2 个不同编译完全相同,作为 2 个不同的目标,那么您的可执行文件,即我们的项目应该 link 到运行时存在的任何 .framework 就好了!
但是,如果 "LibraryAlpha" 自己的目标输出与 "LibraryBeta" 的 "LibraryAlpha" 目标有些不同,那么...模因...我没有麻烦检查在这种情况下会发生什么。但是逻辑提示,无论包含哪个 "LibraryAlpha",都不会 link 正确地指向相反的目标,并且动态 linkage 将失败。如果有人想自己检查此行为,请成为我的客人。
我们工作中的项目依赖于一个名为 "LibraryAlpha" 的动态库。此外,我们工作中的项目依赖于一个名为 "LibraryBeta" 的动态库。而且,恰好 "LibraryBeta" 也依赖于 "LibraryAlpha".
我们的项目嵌入了不同构建的 .framework,即嵌入来自不同 .xcodeproj 的目标。
在以下情况下,"LibraryAlpha" 的符号和实现(函数和 类)以这种或另一种方式两次嵌入到我们项目的包中的可能性有多大:
- "LibraryAlpha" 的项目目标嵌入到项目的包中,"LibraryAlpha" 的项目目标嵌入到 "LibraryBeta" 的包中。
- "LibraryAlpha"的项目目标嵌入到项目的包中,"LibraryAlpha"的源代码与"LibraryBeta" 的源代码静态linked
- "LibraryAlpha" 的项目目标嵌入到项目的包中,只有 "LibraryBeta" link 反对,没有嵌入 "LibraryAlpha"
此外,通常期望使用 SPM 生成的 .xcodeproj 将依赖项模块作为项目中的单独目标,这些目标 link 反对并嵌入到主(声明其依赖项的那个)模块的捆。所以问题是,如果在我们的项目中我 link 和嵌入 "LibraryAlpha" 不是作为项目 "LibraryAlpha" 的目标,而是为 "LibraryAlpha" 生成的目标,会发生什么"LibraryBeta"?
项目中的文件管理 .xcodeprojs 目标的复杂依赖关系的正确方法是,用问题的数字来说,根本不管理它们:
- 存档->导出->安装"LibraryAlpha"
- Archive->Export->Install "LibraryBeta",linking 对已安装 "LibraryAlpha"
- Archive->Export->Install arbitrary amount of other libraries that all dynamically link against "LibraryAlpha"
- Embed 和 link 反对安装 "LibraryAlpha"、"LibraryBeta" 和朋友。
为了简化Apple-targeted项目中的依赖管理,强烈建议您使用Carthage or CocoaPods等依赖管理器。它们不仅会使部署变得轻而易举,而且还有助于消除将框架全局安装到主机中的需要 OS。
旧的错误答案:
- 将 "LibraryAlpha" 作为一个单独的 .xcodeproj,它有自己的目标来构建自己
- "LibraryBeta" 动态 link 针对特定 "LibraryAlpha" 目标而不嵌入
- 让我们的项目动态地 link 到 "LibraryBeta" 和那个特定的 "LibraryAlpha" 目标,显然,嵌入两者。
这不是 Swift 包管理器在解析依赖项和生成 .xcodeproj 时所做的事情。 SPM 通常最终会将所有源代码放在一个项目中,并在其中为 "LibraryAlpha" 创建一个目标。
这样就没有代码被多次包含,一切都在运行时很好地解析。
这当然没有回答问题,问题只是出于兴趣。但记住这一点很重要。
题错了。里面的一些案例在现实生活中是无法重现的。
首先,"one framework linking against and embedding another framework" 问题中提到的概念甚至不是一回事——事实上,动态 linkage 的整个概念被提升以追求重用相同的共享多个用户之间的对象,无需使相同的代码多次可用(读取、嵌入)。
案例一
记住前面的陈述,第一个案例在现实生活中几乎不可能立即重现,因为案例陈述
"LibraryAlpha"'s project target embedded into "LibraryBeta"'s bundle.
"LibraryBeta" 可能会针对 "LibraryAlpha" 的项目目标进行 link 编辑,为了在运行时使用 "LibraryBeta",可执行文件需要嵌入 "LibraryAlpha".符号的重复在这里是无法实现的,因为 "LibraryAlpha" 只会出现在 bundle 中一次。
案例二
"LibraryAlpha"'s source code statically linked with the source code of "LibraryBeta"
这种情况会导致重复编译代码。一旦它将以动态库 "LibraryAlpha" 的形式出现在 bundle 中,一旦静态 linked 到 "LibraryBeta".
警告:
实际上,在这种情况下,您根本无法编译 "LibraryBeta",假设您的任何源代码文件都在顶部声明
错误import LibraryAlpha
。 Swift 中的模块不能手动声明,它们的源代码必须位于单独的目标中才能导入。该案例的源代码与 "LibraryBeta" 位于同一模块中,因此编译器将出现No such module LibraryAlpha
.
案例三
"LibraryBeta" only linking against, without embedding, "LibraryAlpha"
实际可行的解决方案,不会导致任何代码重复。
案例四
...link and embed "LibraryAlpha" not as a target from a project "LibraryAlpha", but that one generated target for "LibraryAlpha"'s files in the project of "LibraryBeta"
在这种情况下不会出现代码重复。
奖金回合:
对于第 4 种情况,除了你不会重用目标。
通过 linking "LibraryBeta" 针对一个动态库,但嵌入另一个动态库...有两种结果。 假设相同的源代码和相同的配置应该产生相同的动态库、具有相同目标代码的相同 .framework 文件夹、.swiftmodule、.swiftdoc、dSYM 和一切,即使它是不同项目中的两个不同目标。因此,如果生成的 .framework 恰好与 2 个不同项目中的 2 个不同编译完全相同,作为 2 个不同的目标,那么您的可执行文件,即我们的项目应该 link 到运行时存在的任何 .framework 就好了!
但是,如果 "LibraryAlpha" 自己的目标输出与 "LibraryBeta" 的 "LibraryAlpha" 目标有些不同,那么...模因...我没有麻烦检查在这种情况下会发生什么。但是逻辑提示,无论包含哪个 "LibraryAlpha",都不会 link 正确地指向相反的目标,并且动态 linkage 将失败。如果有人想自己检查此行为,请成为我的客人。