安装cmake以及ndk

工具栏: Tools–>SDK Manager–>Android SDK

选择SDK Tools,选中NDK 以及 CMake 下载安装

新建工程

修改build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
defaultConfig {
minSdk 28
targetSdk 32
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"

externalNativeBuild {
cmake {
// Passes optional arguments to CMake.
arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
// Sets a flag to enable format macro constants for the C compiler.
//cFlags "-D__STDC_FORMAT_MACROS"
// Sets optional flags for the C++ compiler.
cppFlags "-fexceptions", "-frtti"
//仅生成单个平台
//abiFilters "armeabi-v7a"//,"arm64-v8a" //"x86", "x86_64"
}
}
//生成多个平台共享库
ndk{
abiFilters "armeabi-v7a","arm64-v8a" //"x86", "x86_64"
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}

CMakeLists.txt 修改要点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# 设置本地库编译所需的最小cmake版本
cmake_minimum_required(VERSION 3.10.2)

# 本地native项目名
project("ffmpeg")

## 配置 ##
# 设置本地库根目录
set(native_root_dir ${CMAKE_CURRENT_LIST_DIR})
# 设置本地库源码路径
set(native_source_dir ${native_root_dir}/native)
# 设置第三方静态库ffmpeg路径
set(native_ffmpeg_dir ${native_root_dir}/ffmpeg/armeabi_v7a)
# 设置第三方库libyuv源码路径
set(native_yuv_dir ${native_root_dir}/libyuv)
# 设置第三方库libyuv编译资源路径
set(native_yuv_build_dir ${native_yuv_dir}/build)
# 设置第三方库libyuv头文件路径
set(native_yuv_inc_dir ${native_yuv_dir}/include)

# 设置本地库编译目标名称
set(native_lib_name "ffmpeg")
# 设置本地库编译输出路径
set(native_build_output_dir ${native_root_dir}/../../../build/intermediates/library_jni/debug/jni/${ANDROID_ABI})

## 第三方子目录libyuv配置 ##
# 构建编译文件依赖路径
file(MAKE_DIRECTORY ${native_yuv_build_dir})
# 构建添加一个子路径;添加libyuv子目录,执行子目录中的CMakeLists.txt
add_subdirectory( ${native_yuv_dir} ${native_yuv_build_dir} )
# 创建一个static库lib_yuv 直接引用${native_yuv_build_dir}/libyuv_static.a
add_library( lib_yuv STATIC IMPORTED )
set_target_properties( lib_yuv PROPERTIES IMPORTED_LOCATION
${native_yuv_build_dir}/libyuv_static.a )

# 指定native头文件路径
include_directories(${native_source_dir} )
# 指定libyuv头文件路径
include_directories( ${native_yuv_dir}/include )
# 指定ffmpeg静态库头文件路径
include_directories( ${native_ffmpeg_dir}/include )

# 设置native源码文件集合
set(native_source_files
${native_source_dir}/native_jni.cpp
)
# 用native_source_files源文件集合编译生成SHARED库
add_library(${native_lib_name} SHARED ${native_source_files} )
# 设置${native_lib_name}库编译输出路径
set_target_properties(${native_lib_name}
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY
"${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}")

## import ffmpeg static lib
# 创建一个static库avcodec 直接引用${native_ffmpeg_dir}/lib/libavcodec.a
add_library( avcodec STATIC IMPORTED )
set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION
${native_ffmpeg_dir}/lib/libavcodec.a )

# 创建一个static库avfilter 直接引用{native_ffmpeg_dir}/lib/libavfilter.a
add_library( avfilter STATIC IMPORTED )
set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION
${native_ffmpeg_dir}/lib/libavfilter.a )

add_library( avformat STATIC IMPORTED )
set_target_properties( avformat PROPERTIES IMPORTED_LOCATION
${native_ffmpeg_dir}/lib/libavformat.a )

add_library( avutil STATIC IMPORTED )
set_target_properties( avutil PROPERTIES IMPORTED_LOCATION
${native_ffmpeg_dir}/lib/libavutil.a )

add_library( swresample STATIC IMPORTED )
set_target_properties( swresample PROPERTIES IMPORTED_LOCATION
${native_ffmpeg_dir}/lib/libswresample.a )

add_library( swscale STATIC IMPORTED )
set_target_properties( swscale PROPERTIES IMPORTED_LOCATION
${native_ffmpeg_dir}/lib/libswscale.a )

# 查找动态库log
find_library(log-lib log )
#链接所有动态库/静态库到工程ffmpeg
target_link_libraries(ffmpeg avcodec avfilter avformat avutil swresample swscale lib_yuv ${log-lib})

#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
#拷贝库文件.
add_custom_command(TARGET ${native_lib_name} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E
copy "${native_build_output_dir}/libffmpeg.so"
"${native_root_dir}/../../../../app/libs/libffmpeg.so"
COMMENT "Copying ${native_lib_name} to output directory")

CMake子目录库关联路径问题:

子目录CMakeLists.txt 匹配:

编译实际结果:

  1. so输出路径 CMAKE_LIBRARY_OUTPUT_DIRECTORY
  2. .a 静态库输出路径 CMAKE_ARCHIVE_OUTPUT_DIRECTORY
  3. 获取当前编译的abi , ANDROID_ABI
  4. 编译选项:
    CMAKE_C_FLAGS
    CMAKE_CXX_FLAGS
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wfatal-errors -fPIC")
    CMAKE_CXX_FLAGS_DEBUG/CMAKE_CXX_FLAGS_RELEASE
  5. 子目录编译: ADD_SUBDIRECTORY

关键语句

判断语句

1
2
3
4
5
6
7
8
9
10
11
set(BUDEG ON)

if(BUDEG )

//do something

else()

//do something

endif()

常用变量

  • CMAKE_SOURCE_DIR ( 相当于工程根目录 )
    this is the directory, from which cmake was started, i.e. the top level source directory

  • CMAKE_CURRENT_SOURCE_DIR
    this is the directory where the currently processed CMakeLists.txt is located in

  • PROJECT_SOURCE_DIR ( =CMAKE_SOURCE_DIR 相当于工程根目录 )
    contains the full path to the root of your project source directory, i.e. to the nearest directory where CMakeLists.txt contains the PROJECT() command

  • CMAKE_PREFIX_PATH (用于找 Findxxx.cmake文件,找 库 和 头文件)
    Path used for searching by FIND_XXX(), with appropriate suffixes added.

  • CMAKE_INSTALL_PREFIX ( 安装目录 )
    Install directory used by install.
    If “make install” is invoked or INSTALL is built, this directory is prepended onto all install directories. This variable defaults to /usr/local on UNIX and c:/Program Files on Windows.
    例如: cmake .. -DCMAKE_INSTALL_PREFIX=/my/paht/to/install

基本指令

  • PROJECT(HELLO)
    指定项目名称,生成的VC项目的名称,使用${HELLO_SOURCE_DIR}表示项目根目录。

  • INCLUDE_DIRECTORIES
    指定头文件的搜索路径,相当于指定gcc的-I参数
    INCLUDE_DIRECTORIES(${HELLO_SOURCE_DIR}/Hello) #增加Hello为include目录

  • TARGET_LINK_LIBRARIES
    添加链接库,相同于指定-l参数
    TARGET_LINK_LIBRARIES(demoHello) #将可执行文件与Hello连接成最终文件demo

  • LINK_DIRECTORIES
    动态链接库或静态链接库的搜索路径,相当于gcc的-L参数
    LINK_DIRECTORIES(${HELLO_BINARY_DIR}/Hello)#增加Hello为link目录

  • ADD_DEFINITIONS
    向C/C++编译器添加-D定义,比如:
    ADD_DEFINITIONS(-DENABLE_DEBUG-DABC)
    参数之间用空格分割。如果代码中定义了:
    这个代码块就会生效。如果要添加其他的编译器开关,可以通过CMAKE_C_FLAGS变量和CMAKE_CXX_FLAGS变量设置。

  • ADD_DEPENDENCIES
    定义target依赖的其它target,确保在编译本target之前,其它的target已经被构建。ADD_DEPENDENCIES(target-name depend-target1 depend-target2 …)

  • ADD_EXECUTABLE
    ADD_EXECUTABLE(helloDemo demo.cxx demo_b.cxx)
    指定编译,好像也可以添加.o文件,将cxx编译成可执行文件

  • ADD_LIBRARY
    ADD_LIBRARY(Hellohello.cxx) #将hello.cxx编译成静态库如libHello.a

  • ADD_SUBDIRECTORY
    ADD_SUBDIRECTORY(Hello) #包含子目录

参考链接:https://blog.csdn.net/liaochaoyun/article/details/122594901