安卓下的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文件,將只剩下編譯庫時中指定導出的符號,其余符號均會被隱藏為內部符號