如何使用Xcode创建动态库(dylib)?

时间:2008-10-11 19:30:47

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

我在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环境变量是从应用程序包加载.dylib所必需的。 / p>

4 个答案:

答案 0 :(得分:50)

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

步骤:

  1. 创建一个包含mymod.o
  2. 的库libmylib.dylib
  3. 编译并链接一个调用它的“callmymod”
  4. 使用DYLD_LIBRARY_PATH和DYLD_PRINT_LIBRARIES从callmymod调用mymod
  5. 问题:您“只是”想要为其他模块创建一个库来使用。 然而,有一堆令人生畏的程序 - gcc,ld,macosx libtool,dyld - 有数以万计的选项,一些腐烂的堆肥,以及MacOSX和Linux之间的差异。 有大量的手册页(我在10.4.11 ppc中计算7679 + 1358 + 228 + 226行) 但是没有太多的例子,或者有“告诉我你在做什么”模式的程序。

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

    背景:apple OverviewOfDynamicLibrariesWikipedia Dynamic_library


    第1步,创建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
    

    第2步,编译并链接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 这是macs上的glibtool, 和SCons。)
    欢呼声
       - 丹尼斯

答案 1 :(得分:7)

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

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

如果您要将此库放在可执行文件旁边,则应调整其安装名称以引用它。只是在谷歌搜索“安装名称”时,应该提供大量关于这样做的信息。

答案 2 :(得分:6)

不幸的是,根据我的经验,Apple的文档过时,冗余,缺少您通常需要的大量常用信息。

我在我的网站上写了一些东西,我必须得到FMOD(Sound API)才能使用我们在uni开发的跨平台游戏。这是一个奇怪的过程,我很惊讶Apple没有在他们的开发人员文档中添加更多信息。

不幸的是,作为微软的“邪恶”,他们实际上更好地用文档来管理他们的开发人员(这来自Apple传教士)。

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

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

希望这有帮助。

答案 3 :(得分:5)

您是否了解Apple参考页面Dynamic Library Programming Topics?它应该涵盖你需要的大部分内容。请注意,在程序启动时无条件加载的共享库和按需加载的动态加载库(bundle,IIRC),两者在MacOS X上与Linux或Solaris上的等价物略有不同。