交叉编译sqlcipher
1. 小心预编译宏SQLITE_HAS_CODEC
2. openssl在不同License下,导出的符号不对等。(错了,1.1.0后api发生变化,小心选用openssl版本)
3, ac使用了libtool,但sysroot却在链接时失效。
一如往常,所有GNU Make like的项目在linux平台下configure+make顺利编译安装,但交叉编译到android linux平台时,过程总是问题不断,要一个一个去手动解决。
1. 小心预编译宏SQLITE_HAS_CODEC
sqlcipher是sqlite3的加强版,提供加密。也就是sqlite3的修改版,里面修改添加了代码,并以一些预编译宏来进行分支选路。所有修改过的代码片段都包含在预编译宏SQLITE_HAS_CODEC保护下。如果你没有加入这个预编译宏SQLITE_HAS_CODEC,这部分代码就不会包含在源文件中。必须要清楚,这部分代码是修改,不是新添加。对于不包含新添加还晓幸编译出一个原版,但是不包含修改在代码,就连原本必要定义的结构或代码都不包含了,所以编译就会报错N多东西没有定义。而这些东西却在源文件文本中。
2. openssl在不同License下,导出的符号不对等。(错了,1.1.0后api发生变化)
在你的linux操作系统,你使用的openssl-devel包都在[GNU Public License]下,几乎所有依赖openssl的项目都可以很好地兼容编译。但是你要清楚,当你下载openssl代码包编译出来的库,却是[OpenSSL license]。这两个License有什么不同,就不深入了,但却影响我们的编译兼容。
左图是[OpenSSL License]下的hmac.h。(错了,不是License问题,这个是openssl 1.1.0f)
右图是[GNU Public License]下的hmac.h,也就是我们在linux操作系统常用的openssl-devel包。(错了,不是License问题,这个是openssl 1.0.1e)
在[GNU Public License]下的hmac.h中,结构体hmac_ctx_st导出到头文件。
而[OpenSSL License]下的hmac.h中, 结构体hmac_ctx_st却要隐藏定义,用户必须通过HMAC_CTX_new()来动态分配空间。
这有什么大影响呢?问题是一些项目在它们的结构体直接聚合hmac_ctx_st结构体,使得你编译这些项目时不兼容。
例如sqlcipher项目这样的代码段
这就让你闷,在[GNU Public License]的openssl包可以编译过,在[OpenSSL License]的openssl库就编译不过。
这个结构体的定义在
又要手动在这添加在那添加了。
evp_cipher_st: ./crypto/include/internal/evp_int.h (openssl 1.1.0之后版本)
hmac_ctx_st: ./crypto/hmac/hmac_lcl.h (openssl 1.1.0之后版本)
openssl 1.1.0之后HMAC_CTX_Init以及HMAC_cleanup函数没有了,如果你使用的第三方库依赖旧的openssl,就要小心选用版本。
openssl 1.1.0对android平台编译比较友好,也就容易编译。openssl 1.0.1之前进行android平台编译十分麻烦。并且有几个地方会闷死你。
1. 不同目录的源文件,包含同一项目其它目录的头文件,并没有指定项目目录的根点,用相对路径,而是一个直接#include "xxx.h",你必须根据每次编译错误去补全所有包含路径。crypto目录下的子目录的源文件随便依赖其它目录的头文件。所以你必须添加这个项目内多个目录到包含路径。
2. 编译参数AR,一般指定为host平台的ar程序路径,但是在这个项目中,AR=ar r,不要漏了后面的r,不然在make过程总报静态库链接命令语法错误。
3. 编译参数SHLIB_TARGET,你必须参考Makefile.shared去设置这个参数值,使你编译动态库时可以顺利完成。
3, ac使用了libtool,但sysroot却在链接时失效。
ac会生成Makefile以及libtool,Makefile会去调用libtool。虽然你在LTCFLAGS中设置了--sysroot,并且Makefile的确也使用到libtool --mode=link命令中,但是最后执行gcc链接的命令中却找不到--sysroot选项,导致crtbegin.o, crtend.o路径错误。这里必须自己去手动修改libtool对应的生成动态库的命令(archive_cmds),加入--sysroot选项。手动修改ac生成的文件去编译,最不好就是不通用,下次再编译就记不起了,这与ac自动化相悖。
4. 尽量静态链接到你自己编译的openssl库
4.1 openssl在各厂商的android系统/system/lib都会带有,而你编译的一定不完全相同,但是动态加载时一定会加载到/system/lib目录里的openssl库,而不是你编译的。
4.2 如果你的程序依赖了__gnu_thumb1_case_XXXX函数,说明你的-fPIC选项默认在使用jump tables,如果编译不过请使用-fno-jump-tables去除。