一:常见指令及其解析
Cmake语法常见命令及作用
设置工程名字,message编译打印
set(LIB_NAME AudioJniEnv)
MESSAGE("load ${LIB_NAME}")
设置环境使用的环境是C++ 11
set(CMAKE_CXX_STANDARD 11)
#递归调用执行 test目录下的 cmakelist的文件进行编译
add_subdirectory(test)
将当前目录下面的文件全部添加到 某一个变量中,后续对此变量可以循环遍历或者直接增加到可执行文件中,但是注意如果目录线面有文件夹,不会到文件夹中进行进行遍历,如果需要对文件夹中也进行遍历,需要使用file命令
# 指定当前目录下面的文件到TEST_SRC_LIST 变量中
aux_source_directory(. TEST_SRC_LIST)
get_filename_component 此用法 后面的指令集有多种,具体如下
- DICECTORY:没有文件名的目录,路径返回时带有正斜杠,并且没有尾部斜杠。
- NAME:不带名录的文件名
- EXT:文件名的最长扩展名
- NAME_WE:不带目录或最长扩展名的文件名
- LAST_EXT:文件名的最后扩展名
- NAME_WLE:文件目录或最后扩展名的文件名
- PATH:DIRECTORY的就别名(cmake <= 2.8.11)
#获取文件TEST_SRC 代表的文件,并且重命名为 TEST_EXE,且对${TEST_SRC} 此文件进行截取能采用NAME_WE 的方式,即 获取文件的名字,不包括扩展名
get_filename_component(TEST_EXE ${TEST_SRC} NAME_WE)
#为当前指定的 target 添加编译选项
target_compile_options(${TEST_EXE}
PRIVATE ${COMPILE_OPTIONS_DEFAULT})
target_compile_definitions(${TEST_EXE} PRIVATE ${MK_COMPILE_DEFINITIONS})
设置头文件
include_directories(${FFMPEG_DIR}/include/)
//指定目录下的源文件设添加到指定目录下
aux_source_directory( . TEST_SRC_LIST)
#动态库地址, 会将目录下的so 加载进入当前项目依赖
link_directories(${FFMPEG_DIR}/lib)
MESSAGE("link_dir ${FFMPEG_DIR}/lib")
# 最后生成可执行文件时间 连接的动态库,用于本项目写的代码最后生成可执行文件时,连接使用
target_link_libraries(
${LIB_NAME}
avcodec
avfilter
avformat
avutil
swresample
swscale
)
编译结果:
C++文件编译结果只会有 动态库/静态库 和 可行行文件 2类,主要为以下的2个命令
#编译为动态库
add_library(
${LIB_NAME}
SHARED
${SOURCES}
${SOURCELIST}
)
#编译为可执行文件
add_executable(AudioJniEnv main.cpp)
在编译时会需要将源文件添加到可执行文件/静态库中 ,可使用下面命令
递归搜索全部文件夹,并将匹配到表达式的 文件 添加到变量 SOURCES 中
FILE(GLOB_RECURSE SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
)
#将 所有的源文件打包到 静态库中
add_library(
${LIB_NAME}
SHARED
${SOURCES}
${SOURCELIST}
)
循环foreach用法
#循环执行针对 ${TEST_SRC_LIST} 中的每一个文件进行
foreach(TEST_SRC ${TEST_SRC_LIST})
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
target_link_libraries( ${TEST_EXE} -Wl,--start-group ${MK_SELF_LINK_LIBRARIES} -Wl,--end-group )
else()
target_link_libraries(${TEST_EXE} ${MK_SELF_LINK_LIBRARIES})
endif()
endforeach()
list 功能 主要有
read 功能有
LENGTH
GET
JOIN
SUBLIST
Search 功能
find
modification
APPEND
FILTER
INSTERT
POP_BACK
等
ordering
reverse
Sort
# 将LIB_NAME 添加到 MK_SELF_LINK_LIBRARIES这个变量下面
list(APPEND MK_SELF_LINK_LIBRARIES ${LIB_NAME} )
message( STATUS "MK_SELF_LINK_LIBRARIES : ${MK_SELF_LINK_LIBRARIES}")
#在将 MK_SELF_LINK_LIBRARIES 连接到TEST_EXE这,相当于把外面主工程的依赖 增加到 test 文件夹下面
target_link_libraries(${TEST_EXE} ${MK_SELF_LINK_LIBRARIES})
Function 功能
#定义函数 update_cached_list 参数为 name
function(update_cached_list name)
set(_tmp_list "${${name}}")
list(APPEND _tmp_list "${ARGN}")
list(REMOVE_DUPLICATES _tmp_list)
update_cached(${name} "${_tmp_list}")
endfunction()
#使用函数
if(PKG_CONFIG_FOUND)
pkg_check_modules(AVUTIL QUIET IMPORTED_TARGET libavutil)
if(AVUTIL_FOUND)
update_cached_list(MK_LINK_LIBRARIES PkgConfig::AVUTIL)
message(STATUS "found library: ${AVUTIL_LIBRARIES}")
endif()
endif()
二:常见功能指令
代码中经常遇到需要ffmpeg功能,因此需要将ffmpeg 功能导入到系统依赖中,此处给出2种方式
#方式1:通过pkg_config配置
#指定通过pkgconfig 来执行寻找头文件和依赖的库文件 使用宏开关
option(ENABLE_FFMPEG_PKG_CONFIG "Enable FFmpeg" ON)
#指定2个函数,更新库文件和库的头文件
FUNCTION(update_cache name value)
set("${name}" "${value}" CACHE INTERNAL "*** Internal ***" FORCE)
endfunction()
FUNCTION(update_lib_path name)
set(_tem_list "${${name}}")
list(APPEND _tem_list "${ARGN}")
list(REMOVE_DUPLICATES _tem_list)
update_cache("${name}" "${_tem_list}")
endfunction()
#设置全局变量 MK_LINK_LIBRARIES
update_cache(MK_LINK_LIBRARIES "")
#查找ffmpeg的全局头文件和依赖库位置
if (ENABLE_FFMPEG_PKG_CONFIG)
message(STATUS "ENABLE_FFMPEG_PKG_CONFIG")
find_package(PkgConfig QUIET)
message(STATUS "PkConfig QUIET end")
if(PKG_CONFIG_FOUND)
pkg_check_modules(AVUTIL QUIET IMPORTED_TARGET libavutil)
message(STATUS "PKG_CONFIG_FOUND")
if (AVUTIL_FOUND)
update_lib_path(MK_LINK_LIBRARIES PkgConfig::AVUTIL)
message(STATUS "found library: ${AVUTIL_LIBRARIES}")
endif ()
endif()
# 查找 ffmpeg/libavcodec 是否安装
if(PKG_CONFIG_FOUND)
pkg_check_modules(AVCODEC QUIET IMPORTED_TARGET libavcodec)
message(STATUS "PKG_CONFIG_FOUND")
if(AVCODEC_FOUND)
update_lib_path(MK_LINK_LIBRARIES PkgConfig::AVCODEC)
message(STATUS "found library: ${AVCODEC_LIBRARIES}")
endif()
endif()
# 查找 ffmpeg/libswscale 是否安装
if(PKG_CONFIG_FOUND)
pkg_check_modules(SWSCALE QUIET IMPORTED_TARGET libswscale)
if(SWSCALE_FOUND)
# include_directories(SYSTEM ${SWSCALE_INCLUDE_DIR})
update_lib_path(MK_LINK_LIBRARIES PkgConfig::SWSCALE)
message(STATUS "found library: ${SWSCALE_LIBRARIES}")
endif()
endif()
# 查找 ffmpeg/libswresample 是否安装
if(PKG_CONFIG_FOUND)
pkg_check_modules(SWRESAMPLE QUIET IMPORTED_TARGET libswresample )
if(SWRESAMPLE_FOUND)
# include_directories(SYSTEM ${SWRESAMPLE_INCLUDE_DIRS})
update_lib_path(MK_LINK_LIBRARIES PkgConfig::SWRESAMPLE)
message(STATUS "found library: ${SWRESAMPLE_LIBRARIES}")
endif()
endif()
# 查找 ffmpeg/libavformat 是否安装
if(PKG_CONFIG_FOUND)
pkg_check_modules(AVFORMAT QUIET IMPORTED_TARGET libavformat)
if(AVFORMAT_FOUND)
update_lib_path(MK_LINK_LIBRARIES PkgConfig::AVFORMAT)
message(STATUS "found library: ${AVFORMAT_LIBRARIES}")
else ()
message(STATUS "not found library avformat")
endif()
endif()
endif ()
#指定连接库位置
if( ENABLE_FFMPEG_PKG_CONFIG)
message(STATUS "target_link_libraries MK_LINK_LIBRARIES IS ${MK_LINK_LIBRARIES}")
target_link_libraries( ${LIB_NAME}
${MK_LINK_LIBRARIES}
)
endif()
#方式2 直接指定系统中的ffmpeg的当前位置
#指定ffmpeg的绝对路径,并通过ENABLE_FFMPEG_FIXED_PATH宏开关控制
option(ENABLE_FFMPEG_FIXED_PATH "ENABLE_FFMPEG_FIXED_PATH" OFF)
if (ENABLE_FFMPEG_FIXED_PATH)
# FFmpeg的安装目录,可以通过命令"brew info ffmpeg"获取
set(FFMPEG_DIR /opt/homebrew/Cellar/ffmpeg/6.0_1)
MESSAGE("FFMPEG_DIR ${FFMPEG_DIR}")
#头文件
include_directories(${FFMPEG_DIR}/include/)
MESSAGE("include_dir ${FFMPEG_DIR}/include")
#动态库地址
link_directories(${FFMPEG_DIR}/lib)
MESSAGE("link_dir ${FFMPEG_DIR}/lib")
endif ()
#此处省略 add_library 或者 add_executable
# add_library(${LIB_NAME} SHARED ${SOURCES} )
#手动指定连接地址
if(ENABLE_FFMPEG_FIXED_PATH)
message(STATUS "target_link_libraries ")
target_link_libraries( ${LIB_NAME}
avcodec
avfilter
avformat
avutil
swresample
swscale
)
endif()
#判断当前CPU类型
if(${CMAKE_ANDROID_ARCH_ABI} MATCHES "armeabi-v7a")
include_directories(include/armeabi-v7a)
message("This is armeabi-v7a")
elseif(${CMAKE_ANDROID_ARCH_ABI} MATCHES "arm64-v8a")
include_directories(include/arm64-v8a)
message("This is arm64-v8a")
endif()
#将mp3lame库动态库导入,且指定库的位置 在Android中指定
add_library( mp3lame
SHARED
IMPORTED )
set_target_properties( mp3lame
PROPERTIES IMPORTED_LOCATION
../../../../libs/${CMAKE_ANDROID_ARCH_ABI}/libmp3lame.so )