2024-01-08 android studio CMakeLists.txt 把多个静态链接库打包成动态链接库so的方法

一、先看chatgpt 的回答。

       如果您希望把没有直接使用的静态链接库打包进动态链接库,那么您需要确保这些静态链接库中的符号在最终的动态库中被保留。

        通常情况下,如果您没有在您的代码中直接引用静态库的符号,编译器可能会在优化过程中丢弃这些符号。为了避免这种情况,您可以使用 -Wl,--whole-archive-Wl,--no-whole-archive 这两个链接器标志包围您的静态库,这会告诉链接器把静态库中的所有符号都包括进来,即使它们没有被显式使用。

二、需要配置CMakeLists.txt 文件

三、完整的配置,主要是add_library(opencv_so SHARED my_dynamic_lib.cpp)之后的代码,my_dynamic_lib.cpp是一个空文件,啥毛也不需要有。

cmake_minimum_required(VERSION 3.6)

set(target native-lib)
project(${target} CXX)

include_directories(${PROJECT_SOURCE_DIR}/../../../../sdk_so/native/jni/include)

get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
    message(WARNING "${_variableName}=${${_variableName}}")
endforeach()

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jni-libs/${ANDROID_ABI})

# 添加您的静态库
#add_library(libstatic_opencv STATIC IMPORTED)
#set_target_properties(libstatic_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../../../../sdk/native/staticlibs/${ANDROID_ABI}/libopencv_core.a)
#target_link_libraries(${target} libstatic_opencv)

file(GLOB srcs *.cpp *.c)
file(GLOB hdrs *.hpp *.h)

include_directories("${CMAKE_CURRENT_LIST_DIR}")
add_library(${target} SHARED ${srcs} ${hdrs})
message(WARNING "target: ${target}")
message(WARNING "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
message(WARNING "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
message(WARNING "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
message(WARNING "CMAKE_PROJECT_NAME: ${CMAKE_PROJECT_NAME}")

#target_link_libraries(${target} lib_opencv)

#add_library(libshared_opencv SHARED IMPORTED )
#set_target_properties(libshared_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../../../../sdk/native/libs/${ANDROID_ABI}/libopencv_java4.so)
#target_link_libraries(${target} libshared_opencv)

# 设置静态库的路径
set(LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../sdk_so/native/libs/${ANDROID_ABI})
# 使用 file(GLOB ...) 获取所有的动态库文件列表
file(GLOB OPENCV_SHARED_LIBS "${LIB_DIR}/*.so")
# 设置目标属性,将找到的所有动态库链接到 native-lib
foreach(LIB_FILE ${OPENCV_SHARED_LIBS})
    # 获取不带路径的库文件名
    get_filename_component(LIB_NAME ${LIB_FILE} NAME_WE)
    # 添加库(这里每个库都是独立的 target)
    add_library(${LIB_NAME} SHARED IMPORTED)
    set_target_properties(${LIB_NAME} PROPERTIES IMPORTED_LOCATION ${LIB_FILE})

    message(WARNING "LIB_NAME:${LIB_NAME}  LIB_FILE: ${LIB_FILE}")
    # 链接库到 native-lib
    target_link_libraries(${target} ${LIB_NAME})
endforeach()

#https://blog.csdn.net/shulianghan/article/details/104349622
#可以不进行该配置, 直接在后面的 target_link_libraries 中链接 log 也不会出错
find_library( # Sets the name of the path variable.
    log-lib
    # Specifies the name of the NDK library that
    # you want CMake to locate.
    log )

find_library( # Sets the name of the path variable.
    z-lib
    # Specifies the name of the NDK library that
    # you want CMake to locate.
    z )

message(WARNING "log-lib:${log-lib}")
message(WARNING "z-lib:${z-lib}")
target_link_libraries(${target}  ${log-lib}  z)
#FATAL_ERROR STATIC WARNING
message(WARNING  "^_^ all done ^_^")


# 假设我们有两个静态库 libstatic1.a 和 libstatic2.a
# 并且我们想将它们链接到一个叫做 libcombined.so 的共享库中
# 创建一个新的共享库目标


#add_library(combined SHARED dummy.c )
#set_target_properties(combined PROPERTIES LINKER_LANGUAGE CXX)
#set(LIB_STATIC_NAME ${CMAKE_CURRENT_SOURCE_DIR}/../../../../sdk-static/native/staticlibs/${ANDROID_ABI}/libopencv_video.a)
#target_link_libraries(combined ${LIB_STATIC_NAME})

# 创建一个名为 "native-lib" 的库,将其设置为 SHARED 类型,并提供要编译的 C 源文件

add_library(opencv_so SHARED my_dynamic_lib.cpp)
project(opencv_so CXX)
#set_target_properties(opecv_so PROPERTIES LINKER_LANGUAGE CXX)
# 将日志库 (log-lib) 链接到你的 native-lib 库

set(LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../sdk-static/native/staticlibs/${ANDROID_ABI})
# 使用 file(GLOB ...) 获取所有的静态库文件列表
file(GLOB LIB_STATIC_FILES "${LIB_DIR}/*.a")
# 设置目标属性,将找到的所有静态库链接到 native-lib
foreach(LIB_STATIC_FILE ${LIB_STATIC_FILES})
    # 获取不带路径的库文件名
    get_filename_component(LIB_STATIC_NAME ${LIB_STATIC_FILE} NAME_WE)
    set(LIB_STATIC_NAME ${LIB_STATIC_NAME}test)
    # 添加库(这里每个库都是独立的 target)
    add_library(${LIB_STATIC_NAME} STATIC IMPORTED)
    set_target_properties(${LIB_STATIC_NAME} PROPERTIES IMPORTED_LOCATION ${LIB_STATIC_FILE})

    message(WARNING "LIB_STATIC_NAME:${LIB_STATIC_NAME}  LIB_STATIC_FILE: ${LIB_STATIC_FILE}")
    # 链接库到 native-lib  FATAL_ERROR
    target_link_libraries(opencv_so
            -Wl,-whole-archive
            -Wl,--allow-multiple-definition
            ${LIB_STATIC_NAME})
endforeach()


# 设置静态库的路径
set(LIB_3RDPARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../sdk-static/native/3rdparty/libs/${ANDROID_ABI})
file(GLOB LIB_3RDPARTY_FILES "${LIB_3RDPARTY_DIR}/*.a")
foreach(LIB_3RDPARTY_FILE ${LIB_3RDPARTY_FILES})
    # 获取不带路径的库文件名
    get_filename_component(LIB_3RDPARTY_NAME ${LIB_3RDPARTY_FILE} NAME_WE)
    # 添加库(这里每个库都是独立的 target)
    add_library(${LIB_3RDPARTY_NAME} STATIC IMPORTED)
    set_target_properties(${LIB_3RDPARTY_NAME} PROPERTIES IMPORTED_LOCATION ${LIB_3RDPARTY_FILE})

    message(WARNING "LIB_3RDPARTY_NAME:${LIB_3RDPARTY_NAME}  LIB_3RDPARTY_FILE: ${LIB_3RDPARTY_FILE}")
    # 链接库到 native-lib  FATAL_ERROR
    target_link_libraries(opencv_so
                          -Wl,-whole-archive
                          -Wl,--allow-multiple-definition
                          ${LIB_3RDPARTY_NAME})
endforeach()

target_link_libraries(opencv_so  log  z)

message(WARNING  "^_^ build a file to one so ^_^")

四、编译后就会生成libopencv_so.so,大功造成。

五、调用这个libopencv_so库的时候CMakeLists.txt 文件配置如下。

cmake_minimum_required(VERSION 3.6)

set(target test-lib)
project(${target} CXX)

include_directories(${PROJECT_SOURCE_DIR}/../../../../sdk_so/native/jni/include)

get_cmake_property(_variableNames VARIABLES)

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jni-libs/${ANDROID_ABI})

# 添加您的静态库
#add_library(libstatic_opencv STATIC IMPORTED)
#set_target_properties(libstatic_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../../../../sdk/native/staticlibs/${ANDROID_ABI}/libopencv_core.a)
#target_link_libraries(${target} libstatic_opencv)


include_directories("${CMAKE_CURRENT_LIST_DIR}")
add_library(${target} SHARED  dummy.cpp)


add_library(libshared_opencv SHARED IMPORTED )
set_target_properties(libshared_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../jni-libs/${ANDROID_ABI}/libopencv_so.so)
#set_target_properties(libshared_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../jni-libs/${ANDROID_ABI}/libopencv_java4.so)
target_link_libraries(${target} libshared_opencv)

target_link_libraries(${target}  log  z dl)

message(WARNING  "^_^ call my one so ^_^")

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用Android Studio时,CMakeLists.txt文件是用来配置C/C++项目的构建脚本。它指导Android Studio如何编译和构建项目中的C/C++源代码。 如果你想要在Android Studio中使用CMakeLists.txt,你需要将其放置在你的项目根目录或者是你的模块目录下。然后,你可以在build.gradle文件中引用该CMakeLists.txt文件,以便Android Studio能够正确地构建你的C/C++代码。 如果你在使用CMakeLists.txt编译时遇到了问题,比如出现了错误提示,你可以尝试删除CMakeLists.txt所在文件夹下的.externalNativeBuild文件夹,然后重新打包你的项目。这样做有时可以解决一些构建问题。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [C++版本使用CMakeLists.txt编译(同目录多个源文件)可执行文件](https://download.csdn.net/download/Zhangyanfeng1/12603209)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [AndroidStudio|CMakeLists.txt报错_该用户还没想到昵称_新浪博客](https://blog.csdn.net/weixin_39766005/article/details/109655117)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值