使用CMake交叉编译OpenSSL 1.1.1 for Android的两类问题求助
ld: unknown option: --sysroot错误并控制安装内容 问题描述
我正在为Android平台交叉编译OpenSSL 1.1.1作为应用依赖库,使用CMake的ExternalProject模块调用OpenSSL自身的构建系统,配置如下:
ExternalProject_Add(openssl SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/openssl BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} #INSTALL_DIR CONFIGURE_COMMAND ${CMAKE_COMMAND} -E echo "Starting custom configure" COMMAND export ANDROID_NDK_HOME=@CMAKE_ANDROID_NDK@ COMMAND CC=clang;AR=@CMAKE_AR@;RANLIB=@CMAKE_RANLIB@;PATH=${OPENSSL_COMPILER_PATH}:${PERL_PATH} COMMAND ANDROID_NDK_HOME=@CMAKE_ANDROID_NDK@;CC=clang;AR=@CMAKE_AR@;RANLIB=@CMAKE_RANLIB@;PATH=${OPENSSL_COMPILER_PATH}:${PERL_PATH};<SOURCE_DIR>/Configure ${ARCH} no-shared ${CONFIGURE_COMMAND_DEFINITIONS} -I${CMAKE_CURRENT_SOURCE_DIR}/openssl/ -I${CMAKE_CURRENT_SOURCE_DIR}/openssl/include -I@CMAKE_ANDROID_NDK@/sysroot/usr/include -I@CMAKE_ANDROID_NDK@/sysroot/usr/include/${ARCH_INCLUDE_DIR} --prefix=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ --openssldir=$@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ --libdir="" BUILD_COMMAND export ANDROID_NDK_HOME=@CMAKE_ANDROID_NDK@ COMMAND PATH=${OPENSSL_COMPILER_PATH}:${PERL_PATH}:/bin COMMAND ANDROID_NDK_HOME=@CMAKE_ANDROID_NDK@;PATH=${OPENSSL_COMPILER_PATH}:${PERL_PATH}:/bin;${MAKE_EXECUTABLE} -j8 build_libs INSTALL_COMMAND ${MAKE_EXECUTABLE} -j8 install_sw STEP_TARGETS build install )
构建过程正常,但执行install目标时出现错误:ld: unknown option: --sysroot=/platforms/android-21/arch-arm,该错误在生成libcrypto和libssl后链接OpenSSL应用时触发。我有两个问题需要求助:
- 如何解决这个链接错误?我推测这和Android SDK使用GNU ld而非Clang lld有关;
- 如何配置OpenSSL脚本,避免安装OpenSSL应用及其他无关内容?
问题1:解决ld: unknown option: --sysroot错误
你的推测完全正确——GNU ld不支持--sysroot这个Clang/LLVM链接器专属选项,OpenSSL的Android配置脚本在混合工具链环境下可能误将该选项传递给了GNU ld。这里有几个直接有效的解决办法:
方法1:强制指定使用Clang的LLD链接器
在OpenSSL的Configure命令的环境变量中添加LD=ld.lld,确保链接步骤使用Clang配套的LLD,而非系统的GNU ld。修改后的CONFIGURE_COMMAND关键部分如下:
COMMAND ANDROID_NDK_HOME=@CMAKE_ANDROID_NDK@;CC=clang;AR=@CMAKE_AR@;RANLIB=@CMAKE_RANLIB@;LD=ld.lld;PATH=${OPENSSL_COMPILER_PATH}:${PERL_PATH};<SOURCE_DIR>/Configure ${ARCH} no-shared ${CONFIGURE_COMMAND_DEFINITIONS} ...
方法2:使用完整的NDK Clang路径
直接在CC变量中指定NDK工具链里的完整Clang路径(比如@CMAKE_ANDROID_NDK@/toolchains/llvm/prebuilt/<你的主机架构>/bin/${ARCH}-linux-android21-clang),这样OpenSSL脚本会自动关联使用配套的LLD链接器,从根源避免工具链混合的问题。
方法3:修复脚本的--sysroot参数传递(可选)
如果你坚持使用GNU ld,可以修改OpenSSL的Configurations/15-android.conf配置脚本,将--sysroot相关参数替换为GNU ld支持的格式。不过这种方法需要修改OpenSSL源码,不如前两种方法简洁可靠。
问题2:避免安装OpenSSL应用及无关内容
你已经用到了install_sw目标(OpenSSL官方提供的仅安装库和头文件、跳过二进制应用的目标),但可以进一步优化配置来彻底清除无关内容:
1. 在Configure时添加no-apps选项
在Configure命令中加入no-apps参数,直接禁用所有OpenSSL应用程序的构建,从源头避免生成不必要的二进制文件:
<SOURCE_DIR>/Configure ${ARCH} no-shared no-apps ${CONFIGURE_COMMAND_DEFINITIONS} ...
2. 确认install_sw的行为
install_sw默认只会安装:
- OpenSSL头文件到
--prefix/include目录 - 静态库(因为你指定了
no-shared)到--prefix/lib目录 - 少量必要的配置模板(如果完全不需要,可以通过
no-ssl3、no-comp等额外选项进一步精简)
3. 自定义INSTALL_COMMAND(极致精简)
如果你想完全控制安装内容,跳过OpenSSL的安装脚本,直接复制需要的文件:
INSTALL_COMMAND # 创建头文件目录 ${CMAKE_COMMAND} -E make_directory @CMAKE_INSTALL_PREFIX@/include/openssl # 复制头文件 ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/include/openssl @CMAKE_INSTALL_PREFIX@/include/openssl # 复制静态库 ${CMAKE_COMMAND} -E copy <BINARY_DIR>/libcrypto.a @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/ ${CMAKE_COMMAND} -E copy <BINARY_DIR>/libssl.a @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/
这种方式完全避免了OpenSSL安装脚本可能带来的冗余内容,只保留你需要的依赖文件。
内容的提问来源于stack exchange,提问作者fabiop

