2022年1月13日 星期四

cmake筆記

cmake編譯

cmake 的命令列使用方式為cmake -D<variable>="<value>" <CMakeLists.txt path>。

-D 選項可用來指定編譯時需要的變數內容 。

CMakeLists.txt path:頂層CMakeLists.txt 所在位置


EX

cmake -DCMAKE_CXX_COMPILER="clang++” -DCMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" ../source。


cmake 如何除錯:

透過使用 SET 語法, set(CMAKE_VERBOSE_MAKEFILE TRUE),可以在 CMakeLists.txt 中將 CMAKE_VERBOSE_MAKEFILE 屬性設為 TRUE 。一旦 CMAKE_VERBOSE_MAKEFILE 為 True,可以讓 make 在執行時是 verbose output。

在呼叫 cmake 命令時,一併使用 --trace / --trace-expand,這兩個參數會鉅細靡遺的紀錄 cmake 如何被呼叫,和處理 CMakeLists.txt 的設定



變數

CMAKE_SOURCE_DIR 即 CMake 進入 source tree 的起始目錄(頂層CMakeLists.txt)


自定義變數

SET(myVar  AAA) 

使用的時候直接用${myVar}就可以了


Project command

這類的命令都是屬於 project-scope 的命令,主要提供建立與專案編譯相關的指令。

project(<prjName>)

指定專案的名稱,指定專案名稱最主要的目的在於啟用幾個和環境相關的變數,另外也會在 makefile 增加對應的 target。


Add a library path in cmake

include_directories(${CMAKE_SOURCE_DIR}/inc)

link_directories(${CMAKE_SOURCE_DIR}/lib)


增加一個檔案夾到專案內

add_sub_directories(source code folder) 


生成專案目標執行檔

add_executable(<name> SOURCES):

<name> 目標執行檔的名稱,不一定要和前面的<prjName>同名。

SOURCES 可編譯成目標執行檔的來源檔,可以是多個檔案。

ex:

add_executable(example main.cpp main.h),在這個命令 SOURCES 包含兩個檔案“main.cpp main.h" 。

add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] <source1> <source2> <...>)


添加一個名為<name>的庫文件

  • STATIC:靜態程式庫。
  • SHARED:共享程式庫,例如 Unix like 系統上的 so 檔或 Windows 上的 dll 檔。在建置 dll 時也會連帶生成連結用的 .a 檔,例如建置 libcalc.dll 時也會生成 libcalc.dll.a。
  • MODULE:動態連結程式庫,不在編譯期進行連結,而是等到執行期才透過 dlopen() 或 LoadLibrary() 方式調用。一般情況下 MODULE 輸出的檔案類型也是 so 或 dll,但建立 dll 時不會順便產生 .a 檔。

如果沒有指定 target 之 STATIC、SHARED、MODULE 類型,則由全域變數 BUILD_SHARED_LIBS 來決定要建構何者,BUILD_SHARED_LIBS 預設為 off,亦即建立靜態程式庫。雖然可以直接在 CMakeLists 當中用 set() 指令指派 BUILD_SHARED_LIBS 的值,不過等到執行 CMake 再用 -D 指定通常會比較有彈性。


add_library(TARGET_NAME [STATIC | SHARED | MODULE | OBJECT| UNKNOWN] IMPORTED [GLOBAL])


導入已有的庫

利用 IMPORTED 關鍵字假設另外一個專案或 framework 編譯了一個 library,可以供此專案引用。

EX:

add_library(torch UNKNOWN IMPORTED)

引用 TorchConfig.cmake 增加名為 torch 的 target 

target_link_libraries(<TARGET_NAME> [PRIVATE|PUBLIC|INTERFACE] <LIBRARY1><LIBRARY2><...>)


將若干庫鏈接到目標庫文件

LIBRARY 可以是一個或多個 library 的名字,絕對路徑,library 名稱(也就是 lib<library_name>.so 中的 <library_name)或 -l<library_name>這樣的形式。例子:target_link_libraries(<name> lib1 lib2 lib3)。

target_include_directories(<TARGET_NAME> [INTERFACE|PUBLIC|PRIVATE] <DIR>)

編譯名為 TARGET_NAME 的 target 時,會增加 DIR 目錄到標頭檔的搜尋路徑中。

Scripting command:

OPTION(OPTION_NAME HELP_MESSAGE DEFAULT_VALUE):建立使用者選項參數,在例子中會建立一個使用者參數,名為 DOWNLOAD_MNIST,預設為 ON。

message([MODE] "message to display"):message 可以看做是 CMake 的 print。MODE 必須填入 CMake 提供的常數選項,比較常用的包括了 none(未給定), STATUS, WARNING 和 FATAL_ERROR。模式的不同會決定輸出的目的地,若是 STATUS 則會輸出於 stdout,其他則會輸出於 stderr。

find_package()

top-level 的 CMakeLists.txt,可以使用 find_package 載入在子資料內的CMakeLists.txt上所定義的 function 或執行結果。

CMake 所產生出來的 makefile 無法獨立運作,建置過程仍然必須依賴 CMake,因此無法直接將 makefile 搬移到沒有 CMake 的環境中使用。事實上,只要更換環境就應該重新執行 CMake,針對目前環境配置產生 makefile。

Macro

定義:

MACRO(HEADER_DIRECTORIES return_list dataFilter)

FILE(GLOB_RECURSE new_list ${dataFilter})

SET(dir_list "")

FOREACH(file_path ${new_list})

GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)

SET(dir_list ${dir_list} ${dir_path})

ENDFOREACH()

LIST(REMOVE_DUPLICATES dir_list)

SET(${return_list} ${dir_list})

ENDMACRO()


使用:

SET(search_filter "/home/user/Project/android/GStreamerSDK/x86_64/lib/glib-2.0/*.h")

HEADER_DIRECTORIES(glibcfg_include_dir ${search_filter})


cmake后make时若想打印编译过程,命令为: make VERBOSE=1

沒有留言:

張貼留言