2017-02-09 492 views
1

我正在编写一个跨平台的C++库,它依赖于OpenSSL,我将静态链接&包与我的库链接以便于使用。我想为我的库有一个#include目录,它显然包含一个“openssl”子目录。为什么每个体系结构的opensslconf.h都有所不同?

不幸的是,每个平台的OpenSSL #include目录的内容每个架构都不相同。因此,例如,iOS(最低限度)有三种不同版本的OpenSSL头文件。添加更多TV-OS支持和模拟器版本。 Android上的Windows &存在不同程度的相同问题。

仔细研究之后,唯一在所有平台体系结构中通用但不同的文件是“opensslconf.h”,它通常只相差几行,有时甚至只有一行。

例如, “opensslconf.h” 的tvOS版本包含:

#ifndef OPENSSL_NO_ASYNC 
# define OPENSSL_NO_ASYNC 
#endif 

而iOS版本则没有。

更为频繁的区别在于RC4_INT的定义:

// 64-bit architectures? 
#define RC4_INT unsigned int 

// 32-bit architectures? 
#define RC4_INT unsigned char 

我想只有一组的OpenSSL的#includes的适用于所有架构&平台。我不想为每个拱门/平台重复所有这些文件,特别是因为有太多的变化。

我的第一个问题是,如果我可能只有一个OpenSSL #include目录?如果是这样,我应该选择哪个版本的“opensslconf.h”,我如何知道它会起作用?

我的第二个问题是为什么这是所有问题。为什么OpenSSL不能封装这些平台差异?它是否已经记录了许多其他变量和类型,这些变量和类型会随着您针对不同架构而变化?

回答

2

作为一种变通方法,您可以生成的opensslconf.h(每个你打算支持archs)的多个版本,叫他们opensslconf-win.hopensslconf-tvos.h等 然后写这将仅包含包括基于生成的文件的opensslconf在平台:

#ifdef WIN32 
#include opensslconf-win.h 
#endif 
// and so for every arch 
+0

这是一个好主意。事实上,这是我在所有跨平台库中所做的。而那些恕我直言OpenSSL代码应该已经做到了。 – Bungles

0

为什么每个建筑opensslconf.h不同?

opensslconf.h保存平台特定的配置和安装信息。如您所述,平台配置数据的一个示例是RC4_INT

平台配置信息的其他例子包括定义OPENSSL_NO_SSL2 if ./Configure no-ssl2;和OPENSSL_NO_SSL3如果./Configure no-ssl3。的安装信息的例子是OPENSSLDIR,它保存的OpenSSL's configuration file openssl.conf位置(在其他位置信息)

最后实施例中,no-ssl2no-ssl3OPENSSLDIR,由用户指定。他们不是固定的平台。

(一个相关的问题涉及OPENSSLDIR在沙箱和围墙花园中的用处,但我从未见过它的答案,另请参阅OpenSSL邮件列表上的CONF-less OpenSSL configuration?)。


不幸的是,在OpenSSL的#include目录的内容是每个体系结构的不同,每个平台...经仔细检查,这是常见的,但在所有平台上&架构是“opensslconf.h”唯一不同的文件。

这并不完全正确。 bn.h也不一样。


我想只有一组的OpenSSL的#includes的适用于所有架构&平台......我的第一个问题是,如果有可能只有一个OpenSSL的#包括目录,我想喜欢?如果是这样,我应该选择哪个版本的“opensslconf.h”,我如何知道它会起作用?

是的,它可能有只有一个opensslconf.h只有一个bh.h。但是你必须手工建立它,如果你勤勉地保护利益的定义并无误地转录它们,它就会起作用。你不能选择一个,并期望它适用于所有体系结构和平台。

我已经使用以下技术在OS X和iOS上为胖库合并它们。详细步骤在Build Multiarch OpenSSL on OS X,但我猜你知道发生了什么事看着它。

$ 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 */ 

和:

$ 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 */ 

我的第二个问题是,为什么这是一个问题的。为什么OpenSSL不能封装这些平台差异?它是否已经记录了许多其他变量和类型,这些变量和类型会随着您针对不同架构而变化?

我从来没有见过关于这个问题的明确答案。也许你应该问一个OpenSSL邮件列表,比如openssl-dev。

我的猜测是,有太多的平台和配置选项将它们全部放在一个opensslconf.h(和一个bn.h)中。以下是内置目标的简短列表。 wc -l告诉我们,它们有144个。

该列表不包括各种配置选项,如某些处理器的enable-ec_nistp_64_gcc_128(与NIST或FIPS无关)。另请参阅OpenSSL wiki上的Compilation and Installation | Configure Options

$ ./Configure LIST 
Configuring OpenSSL version 1.1.1-dev (0x10101000L) 
BS2000-OSD 
BSD-generic32 
BSD-generic64 
BSD-ia64 
BSD-sparc64 
BSD-sparcv8 
BSD-x86 
BSD-x86-elf 
BSD-x86_64 
Cygwin 
Cygwin-i386 
Cygwin-i486 
Cygwin-i586 
Cygwin-i686 
Cygwin-x86 
Cygwin-x86_64 
DJGPP 
MPE/iX-gcc 
OS390-Unix 
QNX6 
QNX6-i386 
UEFI 
UWIN 
VC-CE 
VC-WIN32 
VC-WIN64A 
VC-WIN64A-masm 
VC-WIN64I 
aix-cc 
aix-gcc 
aix64-cc 
aix64-gcc 
android 
android-armeabi 
android-mips 
android-x86 
android64 
android64-aarch64 
android64-mips64 
android64-x86_64 
bsdi-elf-gcc 
cc 
darwin-i386-cc 
darwin-ppc-cc 
darwin64-debug-test-64-clang 
darwin64-ppc-cc 
darwin64-x86_64-cc 
debug 
debug-erbridge 
debug-linux-ia32-aes 
debug-linux-pentium 
debug-linux-ppro 
debug-test-64-clang 
dist 
gcc 
haiku-x86 
haiku-x86_64 
hpux-ia64-cc 
hpux-ia64-gcc 
hpux-parisc-cc 
hpux-parisc-gcc 
hpux-parisc1_1-cc 
hpux-parisc1_1-gcc 
hpux64-ia64-cc 
hpux64-ia64-gcc 
hpux64-parisc2-cc 
hpux64-parisc2-gcc 
hurd-x86 
ios-cross 
ios64-cross 
iphoneos-cross 
irix-mips3-cc 
irix-mips3-gcc 
irix64-mips4-cc 
irix64-mips4-gcc 
linux-aarch64 
linux-alpha-gcc 
linux-aout 
linux-arm64ilp32 
linux-armv4 
linux-c64xplus 
linux-elf 
linux-generic32 
linux-generic64 
linux-ia64 
linux-mips32 
linux-mips64 
linux-ppc 
linux-ppc64 
linux-ppc64le 
linux-sparcv8 
linux-sparcv9 
linux-x32 
linux-x86 
linux-x86-clang 
linux-x86_64 
linux-x86_64-clang 
linux32-s390x 
linux64-mips64 
linux64-s390x 
linux64-sparcv9 
mingw 
mingw64 
nextstep 
nextstep3.3 
purify 
qnx4 
sco5-cc 
sco5-gcc 
solaris-sparcv7-cc 
solaris-sparcv7-gcc 
solaris-sparcv8-cc 
solaris-sparcv8-gcc 
solaris-sparcv9-cc 
solaris-sparcv9-gcc 
solaris-x86-gcc 
solaris64-sparcv9-cc 
solaris64-sparcv9-gcc 
solaris64-x86_64-cc 
solaris64-x86_64-gcc 
tru64-alpha-cc 
tru64-alpha-gcc 
uClinux-dist 
uClinux-dist64 
unixware-2.0 
unixware-2.1 
unixware-7 
unixware-7-gcc 
vms-alpha 
vms-alpha-p32 
vms-alpha-p64 
vms-ia64 
vms-ia64-p32 
vms-ia64-p64 
vos-gcc 
vxworks-mips 
vxworks-ppc405 
vxworks-ppc60x 
vxworks-ppc750 
vxworks-ppc750-debug 
vxworks-ppc860 
vxworks-ppcgen 
vxworks-simlinux 

存在同样的问题在不同程度上的Windows &的Android ...

我在想“不是真的”。你不能在这些平台上建立胖库,所以这个问题并不存在。您仍然需要为特定于平台的库指定特定路径,因此what's the problem with headers

自从我回忆起在Linux中看到一些关于它的事情(我目前找不到参考资料),有些手忙脚乱,但Android没有它。


相关的,你可以看到平台和用户配置选项有一个全面的列表:

$ openssl version -a 
OpenSSL 1.0.2g 1 Mar 2016 
built on: reproducible build, date unspecified 
platform: debian-amd64 
options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx) 
compiler: cc -I. -I.. -I../include -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REE 
NTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -g -O2 -fstack-protector-stron 
g -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wl,-Bsymboli 
c-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DMD32_REG_T=int -DOPENSSL_IA32 
_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ 
ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIR 
LPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM 
OPENSSLDIR: "/usr/lib/ssl" 
+0

我在'bn.h'文件中没有看到跨平台的任何差异,尽管我没有编译所有平台。 – Bungles

+0

@Bungle - 我最后一次检查(OpenSSL 1.0.1或1.0.2),'bn.h'有一些依赖字大小的结构。你知道你使用的是什么版本的OpenSSL吗? – jww

+0

我在建设1.1.0d – Bungles

0

Alien_AV给出了答案,但我张贴这一点是为了遵循了一些代码,这只能在答案中正确显示。

下面是为我工作的解决方案。我仍然认为这应该是OpenSSL构建过程的一部分,而不是每个用户可能需要做的事情。

它应该相当容易实现,因为在这个文件中没有特定于平台的特性 - 只需要知道所有支持的平台。

#ifndef __OPENSSLCONF_H__ 
#define __OPENSSLCONF_H__ 

// ************************************************ ANDROID 
#if defined(__ANDROID__) 
    #if defined (__i386__) 
     #include <openssl/opensslconf-android-x86.h> 
    #elif defined (__arm__) 
     #include <openssl/opensslconf-android-arm.h> 
    #elif defined (_MIPS_ARCH) 
     // Unsupported 
    #endif 

// ************************************************ IOS 
// Reference:  http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system 
#elif defined(__APPLE__) && defined(__MACH__) 
    #include <TargetConditionals.h> 
    #ifdef TARGET_OS_WATCHOS 
     // Unsupported 
    #elif TARGET_OS_TV 
     #if TARGET_OS_SIMULATOR 
      #include <openssl/opensslconf-atv-sim64.h> 
     #elif 
      #include <openssl/opensslconf-atv-arm64.h> 
     #endif 
    #elif TARGET_OS_IOS 
     #if TARGET_OS_SIMULATOR 
      #include <openssl/opensslconf-ios-sim32.h> 
      #include <openssl/opensslconf-ios-sim64.h> 
     #else 
      #include <openssl/opensslconf-ios-arm32.h> 
      #include <openssl/opensslconf-ios-arm64.h> 
     #endif 
    #endif 

// ************************************************ WINDOWS 
// Reference: https://msdn.microsoft.com/en-us/library/b0084kay(v=vs.120).aspx 
#elif defined(_WIN32) 
    #if defined(_M_X64) 
     #include <openssl/opensslconf-win64.h> 
    #else 
     #include <openssl/opensslconf-win32.h> 
    #endif 
#endif 

#endif // __OPENSSLCONF_H__ 
相关问题