安卓so下,cmake编译系统,如何仅导出指定符号
安卓下的so,由于需要链接第三方lib库,导出符号时,总是会将第三方的符号也导出了。
根据LD链接,可以指定相应的version_script,简化的version_script为如下格式:
{
global:
XXXXXXXXXXX;
YYYYYYYYYYYY;
local:*;
};
XXXXXXXXXXX与YYYYYYYYYYYY即需要导出的符号。
研究了一下,利用nm.exe与awk.exe,实现了在windows下交叉编译时,只导出指定符号
关键代码行:
add_custom_command(TARGET abcd PRE_LINK
COMMAND ${ANDROID_NDK}/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64/bin/aarch64-linux-android-nm.exe -g "\$(abcd_OBJECTS)" > ${CMAKE_CURRENT_BINARY_DIR}/cwCrypt_${ANDROID_ABI}.txt
COMMAND ..\\..\\..\\..\\awk.exe \"BEGIN{print(\\"{\\nglobal\:\\")} / T /{print $$NF,\\"\;\\"} END {print(\\"local\:\*\;}\\\;\\")}\" ${CMAKE_CURRENT_BINARY_DIR}/abcd_${ANDROID_ABI}.txt > ${CMAKE_CURRENT_BINARY_DIR}/abcd_${ANDROID_ABI}.def
COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_CURRENT_BINARY_DIR}/abcd_${ANDROID_ABI}.txt )
这儿的abcd,即将要链接出来的so文件,默认只导出编译abcd时指定的目标文件中的符号;
利用awk的/ T /过滤掉非导出的符号
这儿会生成一个abcd_armv8.txt及abcd_armv8.def
此命令后会删除txt文件,相应def文件则使用如下命令来删除
add_custom_command(TARGET abcd POST_BUILD COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_CURRENT_BINARY_DIR}/abcd_${ANDROID_ABI}.def)
使用相应的def文件可以有两种实现方式,如下:
#set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_BINARY_DIR}/abcd_${ANDROID_ABI}.def\" ${CMAKE_SHARED_LINKER_FLAGS}")
set_target_properties(abcd PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_BINARY_DIR}/abcd_${ANDROID_ABI}.def\"")
如此后,编译出来的so文件,将只剩下编译库时中指定导出的符号,其余符号均会被隐藏为内部符号