gpt4 book ai didi

ios - 从一个静态库导出“OBJC_CLASS”作为另一个库的一部分

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:00:01 24 4
gpt4 key购买 nike

我想创建一个静态库(实际上是一个框架,但是我知道该怎么做)将其他静态库中的代码捆绑在一起。但是,从原始库导出的OBJC_CLASS最终以未定义符号表示。

例如,在Xcode 5.1.1中(除非另有说明,否则在每个步骤中都使用默认设置/选择):

  • 创建一个名为LibA的新“iOS框架和库Cocoa Touch静态库”项目。
  • 构建(对于模拟器或真实设备,都没有关系)。
  • 创建另一个新的名为LibB的“iOS框架和库Cocoa Touch静态库”项目。
  • libLibA.a从LibA产品拖到LibB项目树中的Frameworks文件夹中。
  • 从静态库旁边的LibA目录中将include拖到LibB项目树的顶层。
  • 如下所示编辑LibB.h
  • 构建(与以前相同的目标)。
  • 创建一个名为AppC的新“iOS应用程序”(任何类型)项目。
  • libLibB.a从LibB产品拖到AppC项目树中的Frameworks文件夹中。
  • LibBinclude目录拖到顶层。
  • LibA从第一个项目的include目录拖到顶层。
  • 验证LibA是否出现在“使用库链接二进制文件”阶段。
  • 在向导生成的任何类的任何方法中(例如-[MasterViewController awakeFromNib]),添加(void)[[LibB alloc] init]
  • 在刚编辑的.m文件的顶部,添加#import "LibB.h"
  • 构建。

  • 这是上面 promise 的 LibB.h:
    #import <Foundation/Foundation.h>
    #import "LibA.h"
    @interface LibB: LibA
    @end

    我收到以下错误:
    Undefined symbols for architecture i386:
    "_OBJC_CLASS_$_LibA", referenced from:
    _OBJC_CLASS_$_LibB in libLibB.a(LibB.o)
    "_OBJC_METACLASS_$_LibA", referenced from:
    _OBJC_METACLASS_$_LibB in libLibB.a(LibB.o)
    ld: symbol(s) not found for architecture i386
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    查看文件,问题很明显:
    $ nm -g libLibB.a
    U _OBJC_CLASS_$_LibA
    0000031c S _OBJC_CLASS_$_LibB
    U _OBJC_METACLASS_$_LibA
    00000308 S _OBJC_METACLASS_$_LibB
    U _OBJC_METACLASS_$_NSObject
    U __objc_empty_cache
    _OBJC_CLASS_$_LibA_OBJC_METACLASS_$_LibA的符号被导出为未定义。

    我可以从LibA引用方法,C函数和结构,全局变量等。甚至是Foundation对象上的类别(只要我做category-dummy技巧)。只是我不知道如何导出的类和元类对象。

    这是我尝试解决的问题:
  • 关闭“死代码剥离”(在所有三个项目中)。
  • (在所有项目中)将-ObjC添加为额外的链接器标志。 (这对于静态库没有意义,它所做的只是给您一个警告错误,告诉您确切的信息,但每个人都向我建议。)
  • 创建一个“导出的符号文件”(对于LibB)。 (这也只对动态库有意义。)
  • ${PROJECT_DIR}/libLibA.a作为“其他链接器标志”(用于LibB)传递,而不是将libLibA作为框架添加(以防-lLibAlibLibA.a处理不同的情况)。

  • 我尝试过的方法仍然认为可能是正确的方法,但是我不确定:
  • 尝试找出适当的libtool选项,这些选项在Xcode中没有相应的设置。 (如有必要,我可以将其包装在Makefile或Xcode自定义构建步骤中。)
  • 启用“执行单对象预链接”,然后将${PROJECT_DIR}/libLibA.a添加到“预链接库”。我收到有关重复符号的警告,然后是成功,但带有一个空libLibB.a,因此显然我需要做其他事情。我已经在OS X上使用.dylibs和动态框架完成了此操作,而我不需要做其他任何事情了......但是从不使用静态库。

  • 我知道的解决方法(如果没有真正的解决方案,我将使用其中一种方法):
  • 要求任何想要使用LibB的人也必须将LibA添加到他们的项目中。特别是我们提供的LibA的预构建副本。
  • 分发LibB作为要包含在项目中的源,而不是静态的lib和标头。
  • 手动ar libLibA.aLibB.o,然后是ranlib,就像1999年一样(尽管文档说这行不通,但似乎如此)。

  • (对于我的简单测试项目而言,这些都不是太可怕了,但是在现实生活中,这不是一个开源项目,实际上LibA是来自3个不同项目的80个不同的库,并且一些LibA代码构建了胖的armv7 / armv7s(这意味着 ar无法使用它……),我们正计划对模拟器和本机构建进行lipo'ing的常规编程,从而使它们成为一个问题。

    最佳答案

    我想我可能已经通过单对象预链接解决了它(基本上这意味着它会执行ld -r来构建一个巨大的目标文件,然后将其传递给libtool),尽管我仍然不确定,而且我不喜欢这种解决方案。因此,我将发布我得到的答案,但希望其他人也能提供更好的答案。

    要使单对象预链接正常工作,您需要(在LibB中):

  • 添加libLibA.a作为框架。
  • 确保它没有出现在“使用库链接二进制文件”构建阶段中。
  • 将“死代码剥离”设置为
  • 将“Do n't Dead-Strip初始化和术语”设置为“是”。
  • 将“执行单个对象预链接”设置为“是”。
  • 将“预链接库”设置为${PROJECT_DIR}/libLibA.a
  • 将“保留专用外部符号”设置为“是”。

  • (第二步是我之前做错的事情……)

    不幸的是,这似乎完全打破了依赖规则,因此即使没有任何变化,每个构建都重新编译目标的每个.m(和.pch)。

    除此之外,这似乎对 AppC和我的真实项目都适用。
    AppC不需要“保留专用外部符号”;我的真实项目确实如此。我相信这是因为其中一个第三方库使用明确的空 ld -r来执行 -exported_symbols_list,以“将所有符号都转换为 private_extern。否则,类对象不会以这种方式结束。但是,我不确定100%是否确定了解这一点。

    关于ios - 从一个静态库导出“OBJC_CLASS”作为另一个库的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25275070/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com