Android下使用CMake链接已有静态库.a生成新的静态库.a,以及动态库.so链接静态库生成新的动态库.so

阅读前提

  1. 假设你有一定的NDK开发基础.
  2. 对CMake有一定的了解.

情景描述

  1. 当前有一个C++项目的源码,需要根据这个C++项目的源码生成Android平台下的静态库.
  2. 生成的静态库需要依赖第三方的静态库.a.

准备工作

生成第三方库(被依赖的库),以下以一个简单的pro1工程为例,根据以下pro1的源码以及对应的CMakeLists.txt,生成静态库libPro1.a,生成方案可参照:

http://blog.csdn.net/LLJJYY001/article/details/77866049

pro1的目录结构:

├─include
│    Add.h      
└─src
     Add.cpp

Add.h

#ifndef _ADD_LJY_
#define _ADD_LJY_
int add(int a,int b);
#endif

Add.cpp

#include "Add.h"
int add(int a,int b){
    return a + b;
}

pro1的CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
set(NAME "Pro1")
set(PROJECT_NAME ${NAME})
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRCS "${PROJECT_SOURCE_DIR}/src/*.cpp")
add_library(${PROJECT_NAME} STATIC ${SRCS})

生成目标库,以下以一个简单的pro2工程为例

  1. 将pro的中生成的静态库文件拷贝到pro目录下的lib下面,请注意对应的Android架构目录,以下以armeabi为例
pro2的目录结构:
├─include
│      Add_B.h
│      
├─lib
│  └─armeabi
│          libPro1.a
│          
└─src
        Add_B.cpp

Add_B.h

#ifndef _ADD_B_
#define _ADD_B_
int add_b(int a);
#endif

Add_B.cpp

#include "Add_B.h"
#include "Add.h"
int add_b(int a){
    //调用Add.h中的方法
    return add(40,75)+a;
}

pro2的CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
set(NAME "Pro2")
set(PROJECT_NAME ${NAME})
include_directories(
    ${PROJECT_SOURCE_DIR}/include 
    ../pro1/include
)
file(GLOB SRCS "${PROJECT_SOURCE_DIR}/src/*.cpp")
#导入第三方依赖库
add_library(
    pro1 
    STATIC 
    MPORTED
)
#设置第三方依赖库的目录地址
set_target_properties(
    pro1 
    PROPERTIES IMPORTED_LOCATION 
    ${PROJECT_NAME}/lib/${ANDROID_ABI}/libPro1.a
)
add_library(
    ${PROJECT_NAME} 
    STATIC 
    ${SRCS}
)
#链接第三方静态库
target_link_libraries(${PROJECT_NAME} pro1)

在项目中使用

通过以上操作就可以完成完成链接已有静态库.a生成新的静态库.a,下面将在AndroidStudio中使用这个静态库.
AS中关于CMake开发jni的配置方式,请自行百度或google

我的Jni的cpp源码:

//
// Created by lijiayan on 2017/9/20.
//

#include "jni.h"
#include "Add_B.h"

extern "C" {
JNIEXPORT jint  JNICALL
Java_com_ljy_nlib_NativeLib_add(JNIEnv *env, jclass type, jint a_);
}

JNIEXPORT jint  JNICALL
Java_com_ljy_nlib_NativeLib_add(JNIEnv *env, jclass type, jint a_) {
    //调用Add_B.h中的方法
    //40 + 75 + a
    //由于在依赖库的pro2.a中,add()方法的参数写死成了40+75,所以这里是40 + 75 + a
    return add_b(a_);
}

我AS中的CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
set(LIBDIR ${CMAKE_SOURCE_DIR}/demo)
include_directories(${LIBDIR}/include)
add_library(libPro1
            SHARED
            IMPORTED
)
set_target_properties(
            libPro1
            PROPERTIES IMPORTED_LOCATION
            ${LIBDIR}/lib/${ANDROID_ABI}/libPro1.a
)
add_library(libPro2
            SHARED
            IMPORTED
)
set_target_properties(
            libPro2
            PROPERTIES IMPORTED_LOCATION
            ${LIBDIR}/lib/${ANDROID_ABI}/libPro2.a
)
find_library(
    log-lib
    log
)
file(GLOB SRCS "${LIBDIR}/src/*.cpp")
add_library(
    demolib
    #链接生成so库
    SHARED
    ${SRCS}
)
target_link_libraries(
      demolib
      ${log-lib}
)
#下面就是动态库链接生成静态库的关键(由于这两个库会有依赖关系,所以经过多次百度google无果后同事帮助问人才知道这么用)
#我之前由于不知道"-Wl,--whole-archive" 和 "-Wl,--no-whole-archive"的使用方式,使用的是google在Cmake开发ndk介绍(https://developer.android.com/studio/projects/add-native-code.html)那给出的方法,也就是直接写成:
#target_link_libraries(
#     demolib
#     ${log-lib}
#     libPro1
#     libPro2
#)
#应为这两个库有依赖关系,所以不能简单的这么写(如果没有依赖关系,而是独立的,那么可以按上面的那种方式),原因:
#ftp://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html
#全英文,我也看不懂,以至于为什么如下写我也不知道.@^_^

target_link_libraries(
   demolib
    "-Wl,--whole-archive"
    libPro1
    "-Wl,--no-whole-archive"
)
target_link_libraries(
    demolib
    "-Wl,--whole-archive"
    libPro2
    "-Wl,--no-whole-archive"
)

Android源码地址:https://github.com/lijiayan2015/NativeDemo
上面C++对应的项目源码:https://github.com/lijiayan2015/AndroidNativeLib
OK,一切就是这样咯.下一篇将会介绍NDK开发源码调试配置.
有问题请留言或者:[email protected]

猜你喜欢

转载自blog.csdn.net/lljjyy001/article/details/78041544