iOS   发布时间:2022-05-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了ios – 在构建时更改子例程名称以避免Xcode中的冲突大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
@H_874_0@

概述

背景 我正在构建一个iOS应用程序(我将从这里调用MyApp),它将依赖于几个独立的静态库(我称之为Lib1,Lib2,Lib3,…)的计算.每个库都在其自己的项目中构建,然后导入到单个工作区(因此工作区将包含MyApp,Lib1,Lib2,…).有关如何设置的详细信息here.这些库由其他独立于MyApp的产品使用,因此我希望尽可能减少库中的任何更改.这些库也是用(普通)C编写的,因此没有头文件
背景

我正在构建一个iOS应用程序(我将从这里@L_388_1@myApp),它将依赖于几个独立的静态库(我称之为Lib1,Lib2,Lib3,…)的计算.每个库都在其自己的项目中构建,然后导入到单个工作区(因此工作区将包含MyApp,Lib1,…).有关如何设置的详细信息here.这些库由其他独立于MyApp的产品使用,因此我希望尽可能减少库中的任何更改.这些库也是用(普通)C编写的,因此没有头文件.

某些函数名称由多个库使用(因此Lib1和Lib2都可能都有Dostuff@L_489_6@).具有相名称函数通常做同样的事情,但是有一些细节关于如何在库之间做出不同的事情,因此Lib1上的Dostuff中的实际代码可能与Lib2上的Dostuff中的代码完全不同.编写一个在每个库中完全相同的通用Dostuff是非常困难的.

问题

在应用程序运行时,它没有从正确的库中调用正确的Dostuff.我发现了这一点,因为在调试会话期间调用错误函数(由于Dostuff函数的细微差别,最终导致应用程序崩溃).

我在寻找什么

每个库只有一个来自MyApp的入口点,每个入口点都是唯一命名的.如果从Lib1的入口点@L_489_6@(或者Lib1上的任何其他@L_489_6@)调用Dostuff,那么我希望它在Lib1上调用Dostuff@L_489_6@.实现这一目标的最佳@L_489_6@是什么?

有没有办法(可能通过XCode中的某个设置)我可以这样做,以便每个库都是它自己的命名空间?这将是我解决问题的首选@L_489_6@.我想我可以通过重命名重复的函数,使它们都是唯一的(所以Lib1上的Dostuff@L_489_6@可以重命名为Lib1Dostuff,或类似的东西),但有数百个函数可能有重复的名称,我们是将要向项目中添加数百个库,因此必须手动重命名所有函数并修复所有调用它们需要花费大量时间,而我的老板并不认为这是一个可行的选择.

updatE

在查看Josh Caswell的评论以及他提供的一些链接之后,看起来可能在编译库时自动重命名所有函数,这将是尝试修复上述问题的最佳@L_489_6@.从我所看到的,在评论中的几个链接中提到的objcopy不支持iOs.我最终遇到了this博客文章,其中讨论了为Xcode目标创建自定义构建规则,以及this博客,其中讨论了自定义构建设置和构建阶段.

我是否正确地假设我可以在构建过程中的某个时刻使用脚本自动附加到我的每个库中的所有函数名称,而不是像我在what I’的最后一段中所描述的那样手动执行. M寻找以上部分?如果是这样,那么构建过程的正确部分是进行这些更改的?最后,做这样的事情的语法是什么样的?在构建过程的不同部分中使用的“脚本”当然看起来不像Obj-C.我之前从未使用过这些“剧本”,所以我完全不知道如何使用它们,这就是我正在寻求帮助的地方.

我试着尽可能地清楚,但如果对我要问的问题有任何疑问,请告诉我.

解决方法

为什么xcode没有调用正确的库函数

假设我提到了3个C库.假设它有以下代码.

库1 – test1lib.a,代码

#include <stdio.h>

void dostuff()
{
  printf("\nDoing stuff for lib1\n");
}

void uniqueEntryPoint1()
{
  printf("\nUnique entry point for lib1\n");
  dostuff();
}

库2 – test2lib.a,代码

#include <stdio.h>

void dostuff()
{
  printf("\nDoing stuff for lib2\n");
}

void uniqueEntryPoint2()
{
  printf("\nUnique entry point for lib2\n");
  dostuff();
}

库3 – test3lib.a,代码

#include <stdio.h>

void dostuff()
{
  printf("\nDoing stuff for lib3\n");
}

void uniqueEntryPoint3()
{
  printf("\nUnique entry point for lib3\n");
  dostuff();
}

这里每个库都有一个独特的函数一个常用函数dostuff()

当我们将这3个库添加到xcode并链接它们时. xcode链接但不加载所有对象文件.让我们说客观的C代码是这样的

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view,typically from a nib.
    uniqueEntryPoint1();

}

输出

Unique entry point for lib1

Doing stuff for lib1

在这种情况下,xcode将仅加载被引用的符号(库1对象).

如果您阅读了链接器标志/选项,例如-all_load,-force_load和-objC,您将更好地理解.

如果我们添加-all_load链接器选项,它将强制链接器加载库的所有对象,因此我们将在xcode中获得以下错误

ld: 2 duplicate symbols for architecture arm64
clang: error: linker command Failed with exit code 1 (use -v to see invocation)

是因链接器检测到多次重新定义dostuff()而失败的原因.

解决此问题的唯一@L_489_6@是更改​​链接器输入,即这3个库中存在的符号. Josh在评论中已经提到过这一点.我要加0.02美元.

可能的解决方

解决方案1:

最好的解决方案(自解释)是在有权访问源代码的情况下更改源代码.

解决方案2:

使用objcopy重命名添加函数前缀,如@L_607_97@的答案中所提供

现在你怀疑如何找到objcopy.

选项1:
你可以使用这个项目https://github.com/RodAtDISA/llvm-objcopy.这将与llvm一起构建时很难编译.您必须按照http://llvm.org/docs/GettingStarted.htmlhttp://llvm.org/docs/CMake.html的说明进行操作.

如果重写https://github.com/RodAtDISA/llvm-objcopy/blob/master/llvm-objcopy.cpp,则可以重用解析和对象重写逻辑,而不依赖于llvm.

选项2:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=binutils/objcopy.c;h=2636ab4bcb34cf1e1e54db9933018a805b366727;hb=HEAD编译并重用binutils objcopy

解决方案3:

您可以按照理查德在此链接Rewriting symbols in static iOS libraries中提供的答案进行操作.这更像是一个黑客,但如果使用十六进制编辑器,您可以重写符号,如果它们的长度保持不变.如果您有更多符号及其大型库,则可以虑使用https://sourceforge.net/projects/bbe-/和nm编写脚本.

所有这一切都是相当大的努力,但显然没有捷径.

大佬总结

以上是大佬教程为你收集整理的ios – 在构建时更改子例程名称以避免Xcode中的冲突全部内容,希望文章能够帮你解决ios – 在构建时更改子例程名称以避免Xcode中的冲突所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。