阅读前提
- 假设你有一定的NDK开发基础.
- 对CMake有一定的了解.
情景描述
- 当前有一个C++项目的源码,需要根据这个C++项目的源码生成Android平台下的静态库.
- 生成的静态库需要依赖第三方的静态库.a.
准备工作
生成第三方库(被依赖的库),以下以一个简单的pro1工程为例,根据以下pro1的源码以及对应的CMakeLists.txt,生成静态库libPro1.a,生成方案可参照:
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工程为例
- 将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开发源码调试配置.
有问题请留言或者:lijiayan_mail@163.com