【问题标题】:How do I create a dynamic library (dylib) with Xcode?如何使用 Xcode 创建动态库 (dylib)?
【发布时间】:2010-09-16 16:58:01
【问题描述】:

我在 Xcode 中构建了一些命令行实用程序(纯 C,没有 Cocoa)。我希望他们所有人都使用我定制的 libpng 版本,并且我想通过在所有可执行文件之间共享一个库副本来节省空间(我不介意与他们重新分发 .dylib)。

我需要做一些魔术来获取 libpng 导出符号吗?

"Link Binary With Libraries" 是否静态构建阶段链接?

Apple 的文档提到在运行时使用 dlopen 加载库,但我如何才能让 Xcode 创建可执行文件而不抱怨缺少符号?


我想我已经明白了:

  • libpng 没有正确链接,因为我已经构建了 32/64 位可执行文件和 32 位库。库和可执行文件的构建设置必须匹配。

  • libpng 的 config.h 需要有大量的定义,例如 #define FEATURE_XXX_SUPPORTED

  • “Link Binary With Libraries” 构建阶段可以很好地处理动态库,DYLD_FALLBACK_LIBRARY_PATH 环境变量是从应用程序包加载 .dylibs 所必需的。

【问题讨论】:

  • 我想推荐 mach-o 标签,但我认为不值得删除任何现有标签来支持它。

标签: xcode linker shared-libraries dylib mach-o


【解决方案1】:

您知道 Apple 参考页 Dynamic Library Programming Topics 吗?它应该涵盖您需要的大部分内容。请注意,有一个在程序启动时无条件加载的共享库和按需加载的动态加载库(bundles、IIRC),这两者在 MacOS X 上与 Linux 或 Solaris 上的等效库有些不同。

【讨论】:

    【解决方案2】:

    您可能需要确保您构建的动态库有一个导出的符号文件,其中列出了应该从库中导出的内容。它只是要导出的符号的平面列表,每行一个。

    此外,当您的动态库被构建时,它会在其中嵌入一个 安装名称,默认情况下,它是构建它的路径。随后,任何链接到它的东西都会首先在指定的路径中查找它,然后才在dyld(1) man page 中的DYLD_FALLBACK_LIBRARY_PATH 下搜索一组(小)默认路径。

    如果您打算将此库放在可执行文件旁边,则应调整其安装名称以引用它。只需在 Google 上搜索“安装名称”就可以找到大量相关信息。

    【讨论】:

    • 如果我只有一个简单的纯 C 函数,我想将它公开为一个动态库。我该怎么做(我在 Windows 上使用 Visual Studio 轻松做到了)?
    【解决方案3】:

    不幸的是,根据我的经验,Apple 的文档已经过时、冗余并且缺少很多您通常需要的常见信息。

    我在我的网站上写了很多关于这个的东西,我必须让 FMOD(声音 API)与我们在 uni 开发的跨平台游戏一起工作。这是一个奇怪的过程,我很惊讶 Apple 没有在他们的开发者文档中添加更多信息。

    不幸的是,像微软一样“邪恶”,他们实际上在用文档照顾他们的开发人员方面做得更好(这来自苹果的传道者)。

    我认为基本上,你没有做的是在你编译你的 .app Bundle 之后。然后,您需要在可执行二进制文件 /MyApp.app/contents/MacOS/MyApp 上运行命令,以更改可执行文件查找其库文件的位置。您必须创建一个可以运行脚本的新构建阶段。这个过程我就不再解释了,这里已经深入做过了:

    http://brockwoolf.com/blog/how-to-use-dynamic-libraries-in-xcode-31-using-fmod

    希望这会有所帮助。

    【讨论】:

    【解决方案4】:

    Mac OS X 上的动态链接,一个小例子

    步骤:

    1. 创建一个包含 mymod.o 的库 libmylib.dylib
    2. 编译并链接调用它的“callmymod”
    3. 从 callmymod 调用 mymod,使用 DYLD_LIBRARY_PATH 和 DYLD_PRINT_LIBRARIES

    问题:您“只是”想创建一个库供其他模块使用。 然而,有一堆令人生畏的程序——gcc、ld、macosx libtool、dyld—— 有无数的选择,一些腐烂的堆肥,以及 MacOSX 和 Linux 之间的差异。 有大量的手册页(我在 10.4.11 ppc 中计算了 7679 + 1358 + 228 + 226 行) 但没有太多示例,或具有“告诉我你在做什么”模式的程序。

    (理解最重要的是做一个简化的 自己的概述:画一些图片,运行一些小例子, 向其他人解释)。

    背景:apple OverviewOfDynamicLibraries, Wikipedia Dynamic_library


    第一步,创建libmylib.dylib --

    mymod.c:
        #include <stdio.h>
        void mymod( int x )
        {
            printf( "mymod: %d\n", x );
        }
    gcc -c mymod.c  # -> mymod.o
    gcc -dynamiclib -current_version 1.0  mymod.o  -o libmylib.dylib
        # calls libtool with many options -- see man libtool
        # -compatibility_version is used by dyld, see also cmpdylib
    
    file libmylib.dylib  # Mach-O dynamically linked shared library ppc
    otool -L libmylib.dylib  # versions, refs /usr/lib/libgcc_s.1.dylib
    

    第二步,编译链接callmymod --

    callmymod.c:
        extern void mymod( int x );
        int main( int argc, char** argv )
        {
            mymod( 42 );
        }
    gcc -c callmymod.c
    gcc -v callmymod.o ./libmylib.dylib -o callmymod
        # == gcc callmymod.o -dynamic -L. -lmylib
    otool -L callmymod  # refs libmylib.dylib
    nm -gpv callmymod  # U undef _mymod: just a reference, not mymod itself
    

    第 3 步,运行 callmymod 链接到 libmylib.dylib --

    export DYLD_PRINT_LIBRARIES=1  # see what dyld does, for ALL programs
    ./callmymod
        dyld: loaded: libmylib.dylib ...
        mymod: 42
    
    mv libmylib.dylib /tmp
    export DYLD_LIBRARY_PATH=/tmp  # dir:dir:...
    ./callmymod
        dyld: loaded: /tmp/libmylib.dylib ...
        mymod: 42
    
    unset DYLD_PRINT_LIBRARIES
    unset DYLD_LIBRARY_PATH
    

    一个小例子到此结束;希望它有助于理解这些步骤。
    (如果您经常这样做,请参阅GNU Libtool 这是 Mac 上的 glibtool, 和SCons。)

    【讨论】:

    • 不错。如果您已经拥有 .o 文件,但在 3 个文件夹中有 9 个文件,但都是同一个“框架”的所有部分……这是对 lipo 的呼吁,还是什么?顺便说一句,我试图让 libg7221 “成为”“共享”“库”,在这种情况下......
    • @alex gray,不知道,抱歉;作为一个新问题提出这个问题?
    猜你喜欢
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    • 2018-08-25
    • 2011-11-10
    • 1970-01-01
    • 2011-06-05
    相关资源
    最近更新 更多