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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/194485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 02:55:54  来源:igfitidea点击:

How do I create a dynamic library (dylib) with Xcode?

xcodelinkershared-librariesdylibmach-o

提问by Kornel

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 .dylibwith them).

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

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

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

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

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

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?

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



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_PATHenvironmental variable is neccessary for loading .dylibs from application bundle.

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

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

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

采纳答案by Chris Hanson

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 nameembedded 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_PATHin the dyld(1)man page.

此外,当您的动态库构建时,它会在其中嵌入一个安装名称,默认情况下,它是构建它的路径。随后任何反对的链接将寻找它在指定的路径第一个也是唯一搜索之后的下描述默认路径(小)组DYLD_FALLBACK_LIBRARY_PATHdyld(1)男子页

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.

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

回答by denis

Dynamic linking on Mac OS X, a tiny example

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

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
  1. 创建一个包含 mymod.o 的库 libmylib.dylib
  2. 编译并链接一个调用它的“callmymod”
  3. 使用 DYLD_LIBRARY_PATH 和 DYLD_PRINT_LIBRARIES 从 callmymod 调用 mymod

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.

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

(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).

(理解最重要的是给自己做一个简化的OVERVIEW:画一些图,运行一些小例子,给别人解释)。

Background: apple OverviewOfDynamicLibraries, Wikipedia Dynamic_library

背景:apple OverviewOfDynamicLibraries维基百科 Dynamic_library



Step 1, create libmylib.dylib --

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

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

第 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

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

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

回答by Brock Woolf

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

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

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.

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

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

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

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:

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

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

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

Hope this helps.

希望这可以帮助。

回答by Jonathan Leffler

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.

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