我想在 osx、ios 和 android 中使用这个应用程序。实现这一目标的正确方法是什么?
Mac OS X 和 iOS 是问题儿童。苹果工具的问题是:1)链接器不支持rpath和-Bstatic之类的东西; 2) 链接编辑器不支持rpath 和LD_PRELOAD。
对于 (1),链接器将静默删除 rpath。此外,-Bstatic 将被忽略。因此,如果可用,您将始终链接到共享对象或 dylib,并且它可能会是错误的。
在 Mac OS X 上链接 OpenSSL 时,您很可能会获得系统 dylib 之一:
$ find /usr/ -iname libssl*
/usr//lib/libssl.0.9.7.dylib
/usr//lib/libssl.0.9.8.dylib
/usr//lib/libssl.dylib
对于 (2),链接编辑器没有 rpath 并且不支持 LD_PRELOAD,因此您将再次链接到系统库。
症状通常是模糊不清的故障,因为程序是针对例如 OpenSSL 1.0.1 编译的,而它在运行时链接到 0.9.8。数据结构有时会有所不同,因此您会遇到毫无意义的模糊崩溃。这是我所说的一个完美示例:Coredump when compiling python with a custom openssl version。
解决方法是省略-L、-lssl 和-lcrypto。相反,您应该指定档案的完整路径。例如,在 Mac OS X 上,我必须指定 /usr/local/ssl/lib/libssl.a 和 /usr/local/ssl/lib/libcrypto.a。
静态档案只是*.o 文件的集合。您应该尝试在“附加对象文件”中指定存档路径。如果不能,请尝试将它们添加到其他库中。在Makefile项目、Eclipse项目和Xcode项目中我都知道怎么做,但是在QtCreator下不知道怎么做。但是 Laszlo Papp 会在Adding object (.o) files to qtcreator project 告诉您如何操作。
下面是 Xcode 下的一个类似示例,我链接的是 Crypto++ 而不是 OpenSSL。但是,请注意我指定了存档的完整路径。 (这是一个 Xcode 项目,我在设备上遇到错误,因为它无法加载 Crypto++ 共享对象)。
您还必须确保根据您的 OpenSSL 版本编译和链接其他依赖于 OpenSSL 的库。我通常采用相同的方法 - 针对静态存档编译依赖库(即使这意味着代码膨胀)。例如,我有一个 libevent 项目,它链接到我的静态版本的 OpenSSL;我的项目链接到我的静态版本的 OpenSSL。这很糟糕,但在 Apple 修复损坏的链接器之前,您必须这样做。
Linux 的表现要好得多,您可以使用rpath 或LD_PRELOAD。但是,既然您是在为 Apple 跳槽,那么您不妨到处做同样的事情。
无论您做什么,请勿在 Apple 平台上使用 -L、-lssl 和 -lcrypto。 Xcode 永远不会正确,即使在您假设使用的唯一库是静态存档的 iOS 上也是如此。显然 Xcode 开发人员没有收到备忘录,Apple QA 也没有测试(什么是新的)。