如何创建iOS的静态库,而不使所有符号公开 [英] How to create static library for iOS without making all symbols public

查看:639
本文介绍了如何创建iOS的静态库,而不使所有符号公开的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题之前已被问过,但是深入了解各种开发工具的文档,看起来像这样是可能的,只是不明显。



动机:
创建一个静态库供其他iOS开发人员使用。库中的一些符号将导致问题,如果导出,我希望将其作为内部符号。使用动态库这很容易,只需使用 -exported_symbols_list libtool ld )参数,并列出你想要的公共。 libtool 文档将不允许静态库的此参数。



库有几个ObjectiveC .m文件,彼此。



尝试 libtool -exported_symbols_list publicsymbols.exp ,但对于静态库, -static 不支持 libtool 的参数。 p>

不能使属性的符号私有(如果这甚至可以工作),因为它们是组中其他.m文件所需要的。



看起来像 ld 可以接受几个.o文件,并将它们链接到一个新的.o文件(通过 -r 参数),并且它对于 -exported_symbols_list 参数没有仅动态免责声明(这可能只是不清楚的文档。 。)。



就像测试我用Xcode构建我的项目,所以我有所有的.o文件,然后尝试调用 ld 在命令行上,如下所示:

  ld -r -x -all_load -static-arch armv6 -syslibroot {path} 
-filelist /Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCsdk.LinkFileList
-exported_symbols_list {exp file path} -o outputfile.o



但我会收到以下错误:


/ usr / bin / ld_classic:/Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCmain.o不兼容,文件在加载命令0(必须指定要使用的-dynamic)中包含不支持的第3部分类型(_ TEXT, _picsymbolstub4)


所以似乎有些东西出现了错误...



任何人都知道一个聪明的方法来使这项工作?谢谢。

解决方案

这真的不可能,对不起。它与静态库工作的方式有关。静态库只是一堆绑定在一起的对象 *。o ,但是动态库是一个可加载的二进制映像,就像可执行文件一样。



假设您有四个档案,




  • common.c定义 ,即私人

  • fn1.c定义 fn1 cn> cn> cn> 。 / code>。

  • other.c定义其他



在动态库中,链接器将所有内容捆绑成一个大块代码。库导出其他 fn1 fn2 。你必须加载整个库或没有它,但两个程序都可以加载它,而不将多个副本在内存中。 common 的入口点只是从符号表中丢失 - 您无法从库外调用它,因为链接器找不到它。



请注意,应用程序和共享库具有基本相同的格式:应用程序基本上是一个共享库,只导出一个符号 main 。 (这不完全是真的,但关闭。)



在静态库中,链接器从不运行。这些文件都被编译成* .o文件并放入* .a库文件中。内部引用将被解析。



假设您的应用程序调用 fn1 。链接器看到对 fn1 的未解析的调用,然后查看库。它在fn1.o中找到 fn1 的定义。然后链接器通知未解决的调用 common ,所以它在common.o中查找。这个程序不会从fn2.c或other.c中获取代码,因为它不使用这些文件中的定义。



静态库非常老,并且它们没有动态库的任何功能。你可以认为静态库基本上是一个完整的编译源代码的zip文件,不像链接在一起的动态库。没有人打扰扩展归档格式以添加符号可见性。当你链接到一个静态库,你得到的结果就像你已经将库的源代码添加到程序中一样。



strong>动态库具有所有导出符号的一个符号表,但不包含任何私有符号。以同样的方式,一个目标文件具有所有 extern 符号的列表,但是没有 static 符号的列表。但是静态库没有符号表,它只是一个归档。因此,没有机制使代码私有到一个静态库(除了定义对象 static ,但不适用于Objective-C类)。



如果我们知道你为什么试图这样做,也许我们可以给你一个建议。 (是为了安全吗?名称冲突?所有这些问题都有解决方案。)


This question has been asked before, but digging into the documentation for the various development tools it seems like this is possible, just not obvious.

Motivation: Making a static library for use by other iOS developers. Some symbols in the library will cause problems if exported so I wish to make them internal-only symbols. With a dynamic library this is easy, just use -exported_symbols_list libtool (ld) argument and list the ones you want public. libtool documentation will not allow this argument for static libraries.

Library has several ObjectiveC .m files that use code from each other. Only one class in the group needs to be made public to users of the final .a static library file.

Tried libtool -exported_symbols_list publicsymbols.exp but that argument to libtool is not supported with -static for static libraries.

Can't make the symbols private with attributes (if that'd even work) because they are needed by the other .m files in the group.

looks like ld can take several .o files and link them together into a new .o file (via the -r argument) and it doesn't have the "dynamic only" disclaimer for the -exported_symbols_list argument (which could just be unclear documentation...).

just as a test I build my project with Xcode so I have all the .o files made, and then try to call ld on the command line, like so:

ld -r -x -all_load -static -arch armv6 -syslibroot {path} 
   -filelist /Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCsdk.LinkFileList 
   -exported_symbols_list {exp file path} -o outputfile.o

where the {path} type things have long paths to the appropriate places in there.

but I get errors like the following:

/usr/bin/ld_classic: /Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCmain.o incompatible, file contains unsupported type of section 3 (_TEXT,_picsymbolstub4) in load command 0 (must specify "-dynamic" to be used)

so something seems wrong there...

Anyone know a clever way to make this work? Thanks.

解决方案

This is really not possible, I'm sorry to say. It has to do with the way static libraries work. A static library is little more than a bunch of object *.o files bundled together, but a dynamic library is a loadable binary image, just like an executable.

Suppose you have four files,

  • common.c defines common, which is "private"
  • fn1.c defines fn1, which calls common.
  • fn2.c defines fn2, which calls common.
  • other.c defines other.

In a dynamic library, the linker bundles everything up into one big chunk of code. The library exports other, fn1, and fn2. You have to load the entire library or none of it, but two programs can both load it without putting multiple copies in memory. The entry point to common is simply missing from the symbol table — you can't call it from outside the library because the linker can't find it.

Note that an application and a shared library have essentially the same format: an application is basically a shared library that only exports one symbol, main. (This is not exactly true, but close.)

In a static library, the linker never runs. The files all get compiled into *.o files and put into a *.a library archive. Internal references will be unresolved.

Suppose your application calls fn1. The linker sees an unresolved call to fn1, and then looks through the libraries. It finds a definition for fn1 in fn1.o. Then the linker notices an unresolved call to common, so it looks it up in common.o. This program won't get the code from fn2.c or other.c, because it doesn't use the definitions from those files.

Static libraries are very old, and they do not have any of the features of dynamic libraries. You can think of a static library as basically a zip file full of compiled source code, unlike a dynamic library which is linked together. Nobody ever bothered to extend the archive format to add symbol visibility. When you link with a static library, you get the same result as if you had added the library's source code to your program.

The short version: A dynamic library has one symbol table of all of the exported symbols, but none of the private symbols. In the same way, an object file has a list of all of its extern symbols but none of the static ones. But a static library has no symbol table, it is just an archive. So there is no mechanism to make code private to a static library (other than defining objects static, but that doesn't work for Objective-C classes).

If we knew why you were trying to do this, perhaps we could give you a suggestion. (Is it for security? Name clashes? All of these questions have solutions.)

这篇关于如何创建iOS的静态库,而不使所有符号公开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆