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

发布于 2024-07-06 09:00:40 字数 642 浏览 14 评论 0 原文

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

我需要施展一些魔法才能获得 libpng 导出符号吗?

“将二进制文件与库链接”是否静态构建阶段链接?

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


我想我已经弄清楚了:

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

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

  • < p>“链接二进制文件与库”构建阶段可以很好地处理动态库,并且 DYLD_FALLBACK_LIBRARY_PATH 环境变量对于从应用程序加载 .dylib 是必需的

I'm building few command-line utilities in Xcode (plain C, no Cocoa). I want all of them to use my customized version of libpng, and I want to save space by sharing one copy of the library among all executables (I don't mind re-distributing .dylib with them).

Do I need to do some magic to get libpng export symbols?

Does "Link Binary With Libraries" build phase link statically?

Apple's docs mention loading of libraries at run time with dlopen, but how I can make Xcode create executable without complaining about missing symbols?


I think I've figured it out:

  • libpng wasn't linking properly, because I've built 32/64-bit executables and 32-bit library. Build settings of the library and executables must match.

  • libpng's config.h needs to have tons of defines like #define FEATURE_XXX_SUPPORTED

  • "Link Binary With Libraries" build phase handles dynamic libraries just fine, and DYLD_FALLBACK_LIBRARY_PATH environmental variable is neccessary for loading .dylibs from application bundle.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

二智少女猫性小仙女 2024-07-13 09:00:40

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


步骤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 步,运行链接到 libmylib.dylib 的 callmymod ——

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。)

Dynamic linking on Mac OS X, a tiny example

Steps:

  1. create a library libmylib.dylib containing mymod.o
  2. compile and link a "callmymod" which calls it
  3. call mymod from callmymod, using DYLD_LIBRARY_PATH and DYLD_PRINT_LIBRARIES

Problem: you "just" want to create a library for other modules to use.
However there's a daunting pile of programs -- gcc, ld, macosx libtool, dyld --
with zillions of options, some well-rotted compost, and differences between MacOSX and Linux.
There are tons of man pages (I count 7679 + 1358 + 228 + 226 lines in 10.4.11 ppc)
but not much in the way of examples, or programs with a "tell me what you're doing" mode.

(The most important thing in understanding is to make a simplified
OVERVIEW for yourself: draw some pictures, run some small examples,
explain it to someone else).

Background: apple OverviewOfDynamicLibraries,
Wikipedia Dynamic_library


Step 1, create 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

Step 2, compile and link 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

Step 3, run callmymod linking to 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

That ends one tiny example; hope it helps understand the steps.
(If you do this a lot, see GNU Libtool
which is glibtool on macs,
and SCons.)

恋你朝朝暮暮 2024-07-13 09:00:40

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

此外,当构建动态库时,它会嵌入一个安装名称,默认情况下,它是构建它的路径。 随后,任何链接到它的东西都会首先在指定的路径中查找它,然后才搜索 DYLD_FALLBACK_LIBRARY_PATH 下描述的一组(小)默认路径。 apple.com/documentation/Darwin/Reference/ManPages/man1/dyld.1.html" rel="noreferrer" title="dyld(1) 手册页">dyld(1) 手册页< /a>.

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

You probably need to ensure that the dynamic library you build has an exported symbols file that lists what should be exported from the library. It's just a flat list of the symbols, one per line, to export.

Also, when your dynamic library is built, it gets an install name embedded within it which is, by default, the path at which it is built. Subsequently anything that links against it will look for it at the specified path first and only afterwards search a (small) set of default paths described under DYLD_FALLBACK_LIBRARY_PATH in the dyld(1) man page.

If you're going to put this library next to your executables, you should adjust its install name to reference that. Just doing a Google search for "install name" should turn up a ton of information on doing that.

北座城市 2024-07-13 09:00:40

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

我在我的网站上写了很多关于此的内容,其中我必须获得 FMOD(声音 API)才能与我们在大学开发的跨平台游戏一起使用。 这是一个奇怪的过程,我很惊讶苹果没有在他们的开发人员文档中添加更多信息。

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

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

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

希望这有帮助。

Unfortunately, in my experience Apple's documentation is antiquated, redundant and missing a LOT of common information that you would normally need.

I wrote a bunch of stuff on this on my website where I had to get FMOD (Sound API) to work with my cross platform game that we developed at uni. Its a weird process and I'm surprised that Apple do not add more info on their developer docs.

Unfortunately, as "evil" as Microsoft are, they actually do a much better job of looking after their devs with documentation ( this is coming from an Apple evangelist ).

I think basically, what you are not doing is AFTER you have compiled your .app Bundle. You then need to run a command on the executable binary /MyApp.app/contents/MacOS/MyApp in order to change where the executable looks for its library file. You must create a new build phase that can run a script. I won't explain this process again, I have already done it in depth here:

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

Hope this helps.

幼儿园老大 2024-07-13 09:00:40

您是否知道 Apple 参考页 动态库编程主题? 它应该涵盖您需要的大部分内容。 请注意,共享库在程序启动时无条件加载,而动态加载库(捆绑包、IIRC)则按需加载,两者在 MacOS X 上与 Linux 或 Solaris 上的等效库有些不同。

Are you aware of the Apple reference page Dynamic Library Programming Topics? It should cover most of what you need. Be aware that there a shared libraries that get loaded unconditionally at program startup and dynamically loaded libraries (bundles, IIRC) that are loaded on demand, and the two are somewhat different on MacOS X from the equivalents on Linux or Solaris.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文