在 OS X 上构建多架构 OpenSSL
Posted
技术标签:
【中文标题】在 OS X 上构建多架构 OpenSSL【英文标题】:Build Multiarch OpenSSL on OS X 【发布时间】:2014-10-21 05:33:16 【问题描述】:我需要在 OS X 上为 32 位和 64 位架构构建 OpenSSL。我需要为./Configure
提供哪些选项,以便将两种架构都构建到同一个 .a 文件中?
【问题讨论】:
【参考方案1】:./配置以便我将它为两种架构构建到同一个 .a 文件中?
您必须小心使用 OpenSSL 和多架构库,因为该库不是多架构安全的。那是因为每个配置都有自己的<openssl/opensslconf.h>
文件,每个平台的BIGNUM
都不一样。
提供 -arch x86_64 -arch i386
将导致构建失败,因为 OpenSSL 的构建系统形成命令的方式。另见Getting libcrypto ar error while compiling OpenSSL for Mac。
下面详述的相同过程也适用于 ios。唯一改变的是-arch
。对于 iOS,您可能会使用 armv7
、armv7s
、arm64
和 i386
(用于 32 位模拟器调试)和 x86_64
(用于 64 位模拟器调试)。
还需要另一个不那么明显的技巧。 OpenSSL硬编码了一些基于--prefix
和--openssldir
的默认路径,所以安装目录要建32位,安装,然后移动;然后为安装目录建64位,安装,然后移动;然后在安装目录下创建fat库。另见How to determine the default location for openssl.cnf?
最后,不要替换 OS X 提供的 OpenSSL。 OpenSSL 1.0.x 和 1.1.x 与 Apple 的 0.9.8 版本的 OpenSSL 二进制不兼容。由于不兼容,以下过程使用$HOME/ssl
。您可以使用/usr/local/ssl
或任何其他适合您口味的位置。
在您开始之前,OpenSSL wiki 在Compilation and Installation 上有一个页面。有很多选项可以提供给config
。选择适合您口味的。我总是使用no-ssl2
,通常使用no-ssl3
、no-comp
。在移动设备上,我使用no-srp
、no-psk
、no-hw
、no-dso
和no-engines
。
以下是构建库的说明。您将为您在多架构构建中支持的每个架构进行配置、构建、安装然后迁移。
32 位
make clean && make dclean
KERNEL_BITS=32 ./config no-ssl2 no-ssl3 --prefix=$HOME/ssl
make depend
make
make install_sw
mv $HOME/ssl/include/openssl/opensslconf.h $HOME/ssl/include/openssl/opensslconf-x86.h
mv $HOME/ssl/include/openssl/bn.h $HOME/ssl/include/openssl/bn-x86.h
mv $HOME/ssl/ $HOME/ssl-x86
64 位
make clean && make dclean
KERNEL_BITS=64 ./config no-ssl2 no-ssl3 --prefix=$HOME/ssl
make depend
make
make install_sw
mv $HOME/ssl/include/openssl/opensslconf.h $HOME/ssl/include/openssl/opensslconf-x64.h
mv $HOME/ssl/include/openssl/bn.h $HOME/ssl/include/openssl/bn-x64.h
mv $HOME/ssl/ $HOME/ssl-x64
标题
您需要复制一组标头(哪个都无所谓),复制opensslconf-x86.h
、opensslconf-x64.h
、bn-x86.h
和bn-x64.h
,创建一个新的<openssl/opensslconf.h>
,创建一个新的<openssl/bn.h>
,以及最后创建多架构库。
rm -rf $HOME/ssl
mkdir -p $HOME/ssl/bin
mkdir -p $HOME/ssl/include/openssl
mkdir -p $HOME/ssl/lib
cp $HOME/ssl-x86/openssl.cnf $HOME/ssl/openssl.cnf
cp $HOME/ssl-x86/include/openssl/* $HOME/ssl/include/openssl
cp $HOME/ssl-x86/include/openssl/opensslconf-x86.h $HOME/ssl/include/openssl/opensslconf-x86.h
cp $HOME/ssl-x64/include/openssl/opensslconf-x64.h $HOME/ssl/include/openssl/opensslconf-x64.h
cp $HOME/ssl-x86/include/openssl/bn-x86.h $HOME/ssl/include/openssl/bn-x86.h
cp $HOME/ssl-x64/include/openssl/bn-x64.h $HOME/ssl/include/openssl/bn-x64.h
新的
如果您还没有这样做,请创建$HOME/ssl/include/openssl/opensslconf.h
。确保使用新的标头保护 (OPENSSL_MULTIARCH_CONF_HEADER
):
cat $HOME/ssl/include/openssl/opensslconf.h
#ifndef OPENSSL_MULTIARCH_CONF_HEADER
#define OPENSSL_MULTIARCH_CONF_HEADER
#if __i386 || __i386__
# include "opensslconf-x86.h"
#elif __x86_64 || __x86_64__ || __amd64 || __amd64__
# include "opensslconf-x64.h"
#else
# error Unknown architecture
#endif
#endif /* OPENSSL_MULTIARCH_CONF_HEADER */
新的
创建$HOME/ssl/include/openssl/bn.h
。确保使用新的标头保护 (OPENSSL_MULTIARCH_BN_HEADER
):
cat $HOME/ssl/include/openssl/bn.h
#ifndef OPENSSL_MULTIARCH_BN_HEADER
#define OPENSSL_MULTIARCH_BN_HEADER
#if __i386 || __i386__
# include "bn-x86.h"
#elif __x86_64 || __x86_64__ || __amd64 || __amd64__
# include "bn-x64.h"
#else
# error Unknown architecture
#endif
#endif /* OPENSSL_MULTIARCH_BN_HEADER */
库
此时,您拥有位于$HOME/ssl-x86
的库的x86 版本和位于$HOME/ssl-x64
的库的x64 版本。你将它们与lipo
结合到$HOME/ssl
。
lipo -create $HOME/ssl-x86/lib/libcrypto.a \
$HOME/ssl-x64/lib/libcrypto.a \
-output $HOME/ssl/lib/libcrypto.a
lipo -create $HOME/ssl-x86/lib/libssl.a \
$HOME/ssl-x64/lib/libssl.a \
-output $HOME/ssl/lib/libssl.a
lipo -create $HOME/ssl-x86/bin/openssl \
$HOME/ssl-x64/bin/openssl \
-output $HOME/ssl/bin/openssl
共享库
如果你配置了shared
,那么你需要执行:
lipo -create $HOME/ssl-x86/lib/libcrypto.1.0.0.dylib \
$HOME/ssl-x64/lib/libcrypto.1.0.0.dylib \
-output $HOME/ssl/lib/libcrypto.1.0.0.dylib
lipo -create $HOME/ssl-x86/lib/libssl.1.0.0.dylib \
$HOME/ssl-x64/lib/libssl.1.0.0.dylib \
-output $HOME/ssl/lib/libssl.1.0.0.dylib
然后,您需要重新创建软链接:
ln -s $HOME/ssl/lib/libcrypto.dylib $HOME/ssl/lib/libcrypto.1.0.0.dylib
ln -s $HOME/ssl/lib/libssl.dylib $HOME/ssl/lib/libssl.1.0.0.dylib
最后,测试一下。验证库是多架构的:
ls $HOME/ssl/lib/
libcrypto.a libssl.a
lipo -info $HOME/ssl/lib/libcrypto.a
Architectures in the fat file: $HOME/ssl/lib/libcrypto.a are: i386 x86_64
lipo -info $HOME/ssl/lib/libssl.a
Architectures in the fat file: $HOME/ssl/lib/libssl.a are: i386 x86_64
然后是一个测试程序:
#include <openssl/opensslconf.h>
#include <openssl/ssl.h>
int main(int argc, char* argv[])
SSL_library_init();
return 0;
还有:
$ clang -arch i386 -arch x86_64 -I $HOME/ssl/include test.c -o test.exe -L $HOME/ssl/lib -lssl -lcrypto
$ DYLD_LIBRARY_PATH=$HOME/ssl/lib; ./test.exe
$
DYLD_LIBRARY_PATH
用于在 OS X 上构建动态库的情况。
如果需要,您可以删除非多架构安装:
rm -rf $HOME/ssl-x86
rm -rf $HOME/ssl-x64
【讨论】:
OpenSSL 构建页面现在链接到这个答案。多年来,我一直想知道为什么他们不能拥有与所有平台匹配的标头,而不是他们拥有的那些废话,就像 opnessl 与所有其他项目一样。以上是关于在 OS X 上构建多架构 OpenSSL的主要内容,如果未能解决你的问题,请参考以下文章