Android Studio新版使用了CMakeLists.txt来管理c/cpp文件,现在就不用写Android.mk来进行编译了。事实感觉cmake的语法更简洁易用,或许这也是谷歌采用的原因之一。
这里简单贴一些用法,复杂用法请参考官方文档https://cmake.org/cmake/help/v3.10/
“#”注释
变量:使用set命令显式定义及赋值,在非if语句中,使用${}引用,if中直接使用变量名引用;后续的set命令会清理变量原来的值;
command (args …) #命令不分大小写,参数使用空格分隔,使用双引号引起参数中空格
set(var a;b;c) <=> set(var a b c) #定义变量var并赋值为a;b;c这样一个string list
Add_executable(${var}) <=> Add_executable(a b c)
#变量使用${xxx}引用
条件语句:
if(var) #var 非empty 0 N No OFF FALSE… #非运算使用NOT
…
else()/elseif() … endif(var)
Set(VAR a b c)
Foreach(f ${VAR}) …Endforeach(f)
WHILE() … ENDWHILE()
CMAKE_C_COMPILER:指定C编译器
CMAKE_CXX_COMPILER:
CMAKE_C_FLAGS:编译C文件时的选项,如-g;也可以通过add_definitions添加编译选项
EXECUTABLE_OUTPUT_PATH:可执行文件的存放路径
LIBRARY_OUTPUT_PATH:库文件路径
CMAKE_BUILD_TYPE::build 类型(Debug, Release, …),CMAKE_BUILD_TYPE=Debug
BUILD_SHARED_LIBS:Switch between shared and static libraries
project (HELLO) #指定项目名称,生成的VC项目的名称;
使用${HELLO_SOURCE_DIR}表示项目根目录
include_directories:指定头文件的搜索路径,相当于指定gcc的-I参数
include_directories (${HELLO_SOURCE_DIR}/Hello) #增加Hello为include目录
link_directories:动态链接库或静态链接库的搜索路径,相当于gcc的-L参数
>> link_directories (${HELLO_BINARY_DIR}/Hello) #增加Hello为link目录
add_subdirectory:包含子目录
>> add_subdirectory (Hello)
add_executable:编译可执行程序,指定编译,好像也可以添加.o文件
>> add_executable (helloDemo demo.cxx demo_b.cxx) #将cxx编译成可执行文件——
add_definitions:添加编译参数
add_definitions(-DDEBUG)将在gcc命令行添加DEBUG宏定义;
target_link_libraries:添加链接库,相同于指定-l参数
target_link_libraries(demo Hello) #将可执行文件与Hello连接成最终文件demo
add_library:
add_library(Hello hello.cxx) #将hello.cxx编译成静态库如libHello.a
add_custom_target:
打印消息
message( status|fatal_error, “message”):
在指定目录下搜索一个库, 保存在变量MY_LIB中
find_ibrary(MY_LIB libmylib.a ./)
set_target_properties( … ): lots of properties… OUTPUT_NAME, VERSION, ….
link_libraries( lib1 lib2 …): All targets link with the same set of libs
现在使用Android Studio使用一下CMake,使用lame库将pcm编码生成Mp3文件。Android Studio如何配置CMake我就不细说了,如果还不太明白NDK开发流程的,建议先了解一下,后面可以参照源码配置。
项目结构
简单说明一下:
mp3_encoder.cpp 直接封装lame的功能;
audio_encoder.cpp 用来和java层对接,调用mp3_encoder.cpp;
test.cpp 纯属测试
我们先来看最外层的CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__STDC_CONSTANT_MACROS") #设置C文件的编译参数
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS")#设置cpp文件的编译参数
#add_compile_options(-std=c++11) #设置编译参数,包括上面两者
include_directories(libs/include)#包含.h文件include目录
add_subdirectory(src/main/cpp/libmp3_endocer)#添加下级目录,下级目录需包含CMakeLists.txt
add_subdirectory(src/main/cpp/test)
#添加cpp编译文件 这里会编译出来libaudio_encoider.so
add_library( audio_encoder
SHARED
src/main/cpp/audio_encoder.cpp )
#链接库
target_link_libraries(
audio_encoder
log#native 日志
mp3_encoder# mp3编码核心
tts#测试用
)
接下来是libmp3_endocer下的CMakeLists.txt
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_CONFIG_H -DFPM_ARM -ffast-math -O3" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_CONFIG_H -DFPM_ARM -ffast-math -O3")
set(distribution_DIR ../../../../libs)#内层或者外层都是四个点,这里应该是某个编译的路径计算
add_library( mp3_encoder
STATIC
mp3_encoder.cpp )
#这里导入外部库 静态库.a
add_library( mp3lame
STATIC
IMPORTED)
set_target_properties(mp3lame
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/armeabi-v7a/libmp3lame.a)
target_link_libraries(
mp3_encoder
mp3lame
)
test下的CMakeLists.txt
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLOGTEST")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLOGTEST")
add_library( tts
SHARED
test.cpp )
target_link_libraries(
tts
log
)
其实结构比较简单,直接编译就会生成带有两个.so的apk
这两个.so包含
这个项目的功能是使用lame库将PCM编码成MP3文件,需要实验的将根目录下的vocal.pcm放到手机指定的目录下,具体路径可以参照MainActivity。
源码下载