2017-02-09 496 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__ 
相關問題