Android studio关于Cmake的使用(第二章·编译库文件)

作为一个Android开发,最近在工作中需要频繁的与底层交互,就避免不了与.c/.cpp/so/.a打交道。通过不停的学习,总算摸出来了点门道,跟大家交流交流,也把自己踩过的坑列出来,避免后人上当。

目录

一丶工程以及文件夹的创建。

二 丶配置文件编写。

1.配置子Cmake文件。

2.配置Project级CmakeList.txt文件

3.配置module级build.gradle文件。

注意事项:


 

一丶工程以及文件夹的创建。

 

老一套,新建C++工程。红圈部分勾选是必须的,如下图。

Android studio关于Cmake的使用(第二章·编译库文件)_第1张图片

 

因为涉及刀一些路径操作,所以建议换成project模式进行操作。同时为了更清晰的描述创建库过程,在cpp文件夹下分别创建oneA和twoB文件夹,然后加一个cmake文件(复制粘贴自动生成的就好)分别对应创建静态库和动态库。然后随便在里面写点函数。

Android studio关于Cmake的使用(第二章·编译库文件)_第2张图片

 

然后为了方便寻找,建一个文件夹专门放置生成的库文件。

Android studio关于Cmake的使用(第二章·编译库文件)_第3张图片

 

这里再次声明:请大家注意一下工程结构,你所创建的文件夹路径跟你下面需要配置的文件信息有很大关系!!!本人因为已经因为路径跳了无数次坑了!!! 

1.注意3个CmakeList.txt的路径。原工程生成的CmakeList.txt在app下,跟module级build.gradle同一个父目录。另外俩个在app/src/main/自己新建的文件夹下。

2.我新建的存放库文件跟头文件的libBuild文件夹,在project文件夹下,跟app文件夹同级目录

 

二 丶配置文件编写。

准备工作做好了,下面进入重点。重点在俩方面,Cmake文件和gradle文件配置。

1.配置子Cmake文件。

注释加代码,我相信已经可以很清晰的描述过程了。

步骤概括为以下三点:

1编译库文件

2修改输出路径

3复制头文件到制定路径(可以忽略)


静态库配置

cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)


#指定用到的系统库或者NDK库或者第三方库的搜索路径。
#link_directories(../lib)

#头文件引用路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)

#编译出一个静态库 源文件是 src/main/cpp/one/src/one.c
add_library( # Sets the name of the library.
             lib_a
             # Sets the library as a shared library.
             STATIC
             # Provides a relative path to your source file(s).
             ${CMAKE_CURRENT_SOURCE_DIR}/src/one.c )

# 设置库文件存放路径
set(lib_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../libBuild)

set_target_properties(lib_a
                      PROPERTIES
                      ARCHIVE_OUTPUT_DIRECTORY
                      "${lib_DIR}/one/lib/${ANDROID_ABI}")

# copy out lib header file... TARGET 库名 POST_BUILD
add_custom_command(TARGET lib_a POST_BUILD
                   COMMAND "${CMAKE_COMMAND}" -E
                    #复制路径(头文件地址)
                   copy "${CMAKE_CURRENT_SOURCE_DIR}/include/one.h"
                    #目标路径
                   "${lib_DIR}/one/include/one.h"
                   COMMENT "Copying one to output directory")
 

 

 动态库配置

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_VERBOSE_MAKEFILE on)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(lib_so SHARED src/two.c)

set(distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../libBuild)
set_target_properties(lib_so
                      PROPERTIES
                      LIBRARY_OUTPUT_DIRECTORY
                      "${distribution_DIR}/two/lib/${ANDROID_ABI}")
add_custom_command(TARGET lib_so POST_BUILD
                   COMMAND "${CMAKE_COMMAND}" -E
                   copy "${CMAKE_CURRENT_SOURCE_DIR}/include/two.h"
                   "${distribution_DIR}/two/include/two.h"
                   COMMENT "Copying two to output directory")

2.配置Project级CmakeList.txt文件

核心在于通过配置启动俩个子模块的cmakelist.txt分别构建不同的库。project级别的Cmake.txt在你的project级别的build.gradle(APP文件夹同一个父级 )引用。当然你也可以选择直接构件库,只需要一个cmakelist.txt就OK了~

cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)

#lib_src_DIR设置路径(全局变量) 指向环境变量HOME/tmp(临时)目录
set(lib_src_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp)
set(lib_build_DIR $ENV{HOME}/tmp)

#创建lib_build_DIR目录(打包临时目录)
file(MAKE_DIRECTORY ${lib_build_DIR})

#add_subdirectory构建添加一个子路径。子路径中的 CMakeLists.txt 也会被执行
#注意2个参数,第一个为子路径cmake的位置,第二个为引入的外部路径(用来放编译中间文件夹)
#add_subdirectory(${lib_src_DIR}/one ${lib_build_DIR}/one)
add_subdirectory(${lib_src_DIR}/two ${lib_build_DIR}/two)

 

3.配置module级build.gradle文件。

注意俩个cmake{}的位置,上面一个控制编译信息,下面一个主要说明文件的位置。基本上就这2个改动点

下面附上我module级build.gradle的配置信息。注意俩个配置信息cmke{}的位置,跳坑欲哭无泪的我~~~

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.heima.buildlib"
        minSdkVersion 23
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                /* DANDROID_PLATFORM android 编译平台-minSdkVersion
                * targets 编译库名称  */
                arguments '-DANDROID_PLATFORM=android-23'
                targets 'lib_so'
                cppFlags "-frtti -fexceptions"
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            //cmake文件引用路径
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

注意事项:

1.project级别的build.gradle在使用tagets‘库名称’,一定注意是生成库的名称,而不是文件夹的名称。这个需要与子cmke脚本构建库的名称一致。

2.tagets不配置的话,默认全部构建。但是经过本工程试验,发现.a跟.so只能同时构建一个,所以这里要选择自己需要构建的库名!

3.顺便提示一下,有时候编译不通过可能是犹豫你的cmake文件路径或者文件名没有写对,耐心一些,并且仔细观察Android studio的Gradle Control窗口,有时候
会提示你具体的错误信息。

 

Android studio关于Cmake的使用(第二章·编译库文件)_第4张图片

 

通过Cake的方式,我们可以轻松引用c/c++源代码编译库文件,通过本人一步一步跳坑教学,有了源码的支持,是不是感觉简单多了。

以上都搞好了话,build就OK了~在目标路径(buildLib文件夹)就会找到头文件和俩种库文件了。至此,库文件的编译过程全部完毕。

PS:完事开头难,本人不知道这个破玩意陆陆续续坑了多少次,不是库文件没创建成功就是头文件根本没有复制,要了干脆了编译失败,痛苦啊痛苦,但是迈出了第一次,
后面的就水到渠成了。

附上资源地址:CSDN资源

                         GitHUb传送门

你可能感兴趣的:(#,ndk)