一、CMake 介紹
CMake是一個跨平台的安裝/編譯工具,通過CMake我們可以通過簡單的語句來描述所有平台的安裝/編譯過程。它能輸出各種makefile或者project文件,能測試編譯器所支持的C++特性,類似UNIX下的automake。Cmake 並不直接建構出最終的軟件,而是產生標准的建構檔(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建構方式使用。這使得熟悉某個集成開發環境(IDE)的開發者可以用標准的方式建構他的軟件。
CMake的所有語句都寫在一個CMakeLists.txt文件中,CMakeLists.txt 文件編寫完成后,直接使用CMake命令進行運行即可 ,但是需要這個命令需要指向CMakeLists.txt 所在的目錄。在AndroidStudio中,IDE會幫我們執行命令,我們可以暫時不需要了解CMake和CmakeList.txt之間的關系,但是我們需要了解如何編寫CmakeList.txt 來配置我們的項目,以保證相關的庫能正常的加載和運行。
補充:在之前的Android NDK學習(二):編譯腳本語法Android.mk和Application.mk里面我們講述過makefile相關的內容,感興趣的可以自行查看。
二、CMakeLists 指令
在講CMakeLists相關指令之前,可以看一下常見的CMakeLists.txt文件的內容,下面是使用CameraX+Rtmp開發推流功能的時候,創建的CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.4.1) set(rtmp_lib_src_DIR ${PROJECT_SOURCE_DIR}/src/main/cpp) add_subdirectory(${rtmp_lib_src_DIR}/librtmp) include_directories( ${CMAKE_SOURCE_DIR}/src/main/cpp/include ) # build application's shared lib # For Java Call, the file of C/C++ Use UpperCase Name Space add_library(rtmp-push-lib SHARED ${CMAKE_SOURCE_DIR}/src/main/cpp/RtmpPushLib.cpp ...other cpps
) 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 ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${rtmp_lib_src_DIR}/libs/${ANDROID_ABI}") # Include libraries needed for MediaEditor lib target_link_libraries(rtmp-push-lib rtmp x264 android log ${log-lib} )
下面我們根據上面的配置文件,來逐步講解各個指令的使用方式和意義:
1. cmake_minimum_required(VERSION 3.4.1) 指令
此指令的作用就是規定cmake程序的最低版本,屬於可選的指令,但是一般情況下都會添加這個指令。如果CMakeLists.txt中使用了一些高版本cmake特有的命令的時候,是必須要加上的,這樣能夠提醒使用者升級到該版本之后再執行camke。
2. set 指令
set指令用於顯式的定義變量。使用方式為set(var [value] [cache type docstring] [force]). 其中定義時必須填寫的參數為:var 和 value。
3. add_subdirectory 指令
用於添加需要編譯的源文件的子目錄;語法為:add_subdirectory(source_dir [binary_dir][exclude_from_dir])。其中source_dir:向當前工程添加存放源文件的子目錄,[binary_dir]:指定目標文件存放的位置,[exclude_from_dir]:將該目錄從編譯過程中排除。
注意:子目錄也需要有CmakeLists.txt文件,以保證子目錄下的源文件能夠正常編譯。
4. add_library 指令
add_library():用於將一組源文件編譯生成一個庫文件,並保存為 libname.so (lib 前綴是生成文件時 CMake自動添加上去的)。可傳入多個源文件,其語法為:add_library(libname [SHARED | STATIC | MODULE] [EXCLUDE_FROM_ALL] [source])。
其中生成的有三種庫文件類型,不寫的話,默認為 STATIC。下面我們簡單的講解一下生成的庫文件類型:
- SHARED:表示生成的為動態庫,可以在Java代碼中使用System.loadLibaray(name)進行動態調用。
- STATIC:表示生成的為靜態庫,集成到代碼的時候,會在編譯時調用。
- MODULE:只有在dyld的系統有效,如果不支持dyld,則會被當作SHARED對待。
5. find_library 指令
這個指令是Android NDK開發提供的特有的Cmake指令,用於添加NDK API。語法為:find_library(<VAR> name1 path1 path2 ...)。例如上面的CMakeList.txt文件中,我們就添加了日志支持的API。
6. target_link_libraries 指令
target_link_libraries 指令用來為 target 添加需要鏈接的共享庫,同樣也可以用於為自己編寫的共享庫添加共享庫鏈接。語法為:target_link_libraries(target library <debug | optimized> library2…)
三、參考資料
Android NDK 開發:CMake 使用:https://www.jianshu.com/p/c71ec5d63f0d
CMakeLists入門學習筆記(一):https://blog.csdn.net/lisfaf/article/details/90639611
CMake 入門實戰:https://www.hahack.com/codes/cmake/
CMake 使用教程:https://www.jianshu.com/p/3078a4a195df
CMake使用簡介及CMakeList.txt編寫:https://www.pianshen.com/article/4159316635/