今天不是来讲lldb ,因为用的是android studio 3.0,只能用CMake 才能调试(3.0 以下可以配合 gradle-experimental
,不过也要有改动,这里不再细说),所以需要把原来的 Android.mk 转成CMake,
前提,自己去下载 lldb,cmake,ndk,这个在sdk 管理中,见下图:
这里主要讲一下,怎么手机编写CMakeList.txt
只要在Android中有使用过jni的应该都了解我们要编译写的c/c++文件都需要配置编译用的配置文件,在eclipse中要写mk文件;在Android Studio中要写CMakeList.txt这个配置文件。
只有写好了这个配置文件我们才正确编译出我们想要的so动态库,今天就讲讲Android Studio中的CMakeList.txt这个文件怎么写,eclispe的mk文件的写法在这就不讲了,如果不了解的可以到ndk安装路径中打中doc文档中查看Android.mk的写法,文档中详细的介绍
。
要了解CMakeList这个东西,那就应该要知道CMake干嘛用的,CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。
太详细的用法在此就不讲了,下我会以ffmpeg的配置,来讲解在Android Studio中CMakeList.txt的常用写法。
在此附上CMake官方学习文档:
英文文档:https://cmake.org/documentation/
中文文档:https://www.zybuluo.com/khan-lau/note/254724
在CMakeList.txt开头时应该设置好我们的jni文件夹目录,这样才能让gcc在编译时找到对应的文件,具体的写法如下:
set(distribution_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs)
反斜线的后面是固定的格式,前面的你的jni文件夹所在的路径;后面的写法一般不建议修改。
写好这个后,如里我们有需要引入的第三方头文件,在这时应该要配置头文件的路径,具体的写法如下:
include_directories(src/main/jniLibs/include/ffmpeg)
如里有多个, 也是一样的依次往一加上就可以了,如里有要引用第三方编译好的.so库,在这时应该要配置进来编译;引入第三方的.so库具体写法如下:
add_library(
avcodec-lib
SHARED
IMPORTED)
set_target_properties( avcodec-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavcodec-56.so)
首先要添加库,也就是:add_library函数,里面要传入三个参数;第一个是要引入的库别名,第二个是库的类型,是静态库还是动态库。在Android中是不能引用静态库的也就是.dll后缀的库,所以第二个参数只要是引入第三方的.so库都是写“SHARED”,第三个是通过什么样方式引入进来,第三方的一般都是通过包含进来,所以第三个参数基本也是固定的都是写“IMPORTED”。
add_library后,就要设置.so的详细路径了,通过set_target_properties()函数来设置;该函数也是要传入三参数来指定.so库的路径。第一个参数和add_library的第一个参数一样,不过这里的库别名要和add_library的库别名要一致,要不然在编译时会报找不到库的错误。第二个参数是固定的,都是写“ PROPERTIES IMPORTED_LOCATION”主要用来指定库的引入方式。都是通过本地引入。第三个就是库的具体路径,这个不能写错,如果写错了,编译时也同样会找不到库的。只要是引入第三方的库使用add_library就要使用set_target_propeties这个组合,所以它们是成对出现的。
add_library还有一种写法那就是CMakeList.txt中默认写法
add_library( # Sets the name of the library.
playController
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/playController.c)
这样是就是编译我们自己在项目中写的c/c++文件。这里就不用set_target_propeties()。
下面就到find_library()了;看到这个名字相信都会知道它是干嘛用的,查找库用的,用在哪里呢,这个主要是查找系统库用的,如果项目里面有用到系统的.so库就是要把库名写到这个函数里面去找到相对应的为。
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 )
比如上面用了日志库,那就要把日志库加进来。
最后一个函数target_link_libraries()这个是函数是干嘛用的呢,讲到这个函数就要讲到c/c++的编译原理了,在linux中c/c++的编译一般都是用gcc来编译的,c/c++编译时会产生.o文件要通过make工具来把这些.o文件链接起来,这样才能得一个可执行程序。所以.so在编译时要把所有库链接起来才能编译。target_link_libraries()就是干这个事的。
target_link_libraries( # Specifies the target library.
playController
avcodec-lib
avdevice-lib
avfilter-lib
avformat-lib
avutil-lib
postproc-lib
swresample-lib
swscale-lib
yuv-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
把要链接的库别名都写到这里就可以了,如果是系统的库要用这个格式${库的名字}。
好了,CMakeList.txt的基本写法就讲到这里,如里有发现写错了,小伙伴可以留言给我,及时改正大家一起进步。
最后附上ffmpeg的CMakeList.txt全部写法
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
set(distribution_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs)
add_library(
avcodec-lib
SHARED
IMPORTED)
set_target_properties( avcodec-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavcodec-56.so)
add_library( avdevice-lib
SHARED
IMPORTED)
set_target_properties( avdevice-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavdevice-56.so)
add_library(
avfilter-lib
SHARED
IMPORTED)
set_target_properties( avfilter-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavfilter-5.so)
add_library(
avformat-lib
SHARED
IMPORTED)
set_target_properties( avformat-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavformat-56.so)
add_library(
avutil-lib
SHARED
IMPORTED)
set_target_properties(
avutil-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavutil-54.so)
add_library(
postproc-lib
SHARED
IMPORTED)
set_target_properties(
postproc-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libpostproc-53.so)
add_library(
swresample-lib
SHARED
IMPORTED)
set_target_properties(
swresample-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libswresample-1.so)
add_library(
swscale-lib
SHARED
IMPORTED)
set_target_properties(
swscale-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libswcale-3.so)
add_library(
yuv-lib
SHARED
IMPORTED)
set_target_properties(
yuv-lib
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libyvu.so)
#支持-std=gnu++11
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
#判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
message(STATUS "optional:-std=c++11")
endif(CMAKE_COMPILER_IS_GNUCXX)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
playController
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/playController.c)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
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 )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
include_directories(src/main/jniLibs/include/ffmpeg)
include_directories(src/main/jniLibs/include/libyuv)
target_link_libraries( # Specifies the target library.
playController
avcodec-lib
avdevice-lib
avfilter-lib
avformat-lib
avutil-lib
postproc-lib
swresample-lib
swscale-lib
yuv-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )