《CMake實踐》筆記+實踐記錄,包括一些書中的坑

這本教程很短,總共只有47頁,然而下來共花費約8個小時。其中,閱讀+例程實踐共花費(3.4日 - 3.10日)共花費5小時21分鐘;整理筆記+發博客(3.11日和3.29日)共花費2小時25分鐘 。

放一張閱讀時間記錄圖。
閱讀時間記錄
做筆記總結真的太耗時了,而且自己很抗拒。由上圖知,假如說只在文檔上做標記,確實很簡單,用5天的時間就看完了。然而起後便扔下不管了,直到今天快月底了纔不得不寫一篇總結,努力往上爬真他媽難啊。。。。

閱讀完的時候,自己的任務也就結束了,可這樣總感覺不是自己的東西,不如整理一下,吸收其中自己認爲最有用的東西,這樣也能極大的減輕自己的記憶負擔。

當然,與自己使用marddown語法不熟練和MarkdownPad 2這個軟件不好用也有關係,導致自己排版也花費了好多精力,下次直接在csdn裏的markdown記錄就行了,不要用MarkdownPad 2,別人覺得好用了不一定適合自己!!!

記筆記的教訓總結一下:

  1. 最後總結的時候,不要事無鉅細都想記錄下來。只記錄自己覺得最有用的就行了,想象如果只讓你記錄三點你會記錄哪些,以此來幫助自己篩選重要的東西。
  2. 工具用好,以後就在csdn裏面記錄了,統一工具也避免不必要的麻煩!

筆記從第三章開始,包括一些文檔裏的錯誤所造成的坑!

三 初試 cmake – cmake 的 helloworld

遇到的坑
不要直接複製原文中代碼,原文中代碼""用的是中文字符,所以編譯會出錯,而且不好發現

  1. cmake … 之後make

     首先注意的是,當你定義了工程名時,cmake會預定義一些帶有工程名的cmake變量。
     PROJECT (HELLO)  
     HELLO_BINARY_DIR   HELLO_SOURCE_DIR  PROJECT_BINARY_DIR    PROJECT_SOURCE_DIR  
     如果是內部編譯,就相當於 PROJECT_SOURCE_DIR 也就是
     工程代碼所在目錄,如果是外部編譯,**指的是外部編譯所在目錄**  
    
  2. 指令是大小寫無關的,參數和變量是大小寫相關的 ; IF中使用變量名,不需要${變量名}

  3. 清理工程 make clean

  4. 內部構建和外部構建,cmake強烈推薦的是外部構建(out-of-source build)

     內部構建就是在工程主目錄下,也就是CMakeLists.txt所在的文件夾下編譯;
    
     而外部構建不是在此目錄下編譯的。一般是新建一個build文件夾,在此文件夾下cmake ..,生成makefile文件,然後再make編譯。
    

四 更好一點的 Hello World

工程中多了src目錄存放源文件。

  1. 需要爲任何子目錄建立一個 CMakeLists.txt
    PROJECT(HELLO)
    ADD_SUBDIRECTORY(src bin)
    應該把這兩條指令寫在工程的 CMakeLists.txt 還是 src 目錄下的CMakeLists.txt?
    把握一個簡單的原則,在哪裏 ADD_EXECUTABLE 或 ADD_LIBRARY,
    如果需要改變目標存放路徑,就在哪裏加入上述的定義

  2. 如何安裝文件
    如果你希望使用 CMAKE_INSTALL_PREFIX 來定義安裝路徑,就要寫成相對路徑,即不要以/開頭,那麼安裝後的路徑就是
    ${CMAKE_INSTALL_PREFIX}/<DESTINATION 定義的路徑>。
    安裝的需要有兩種,一種是從代碼編譯後直接 make install 安裝,一種是打包時的指定目錄安裝。

     make和make install 的區別:  
     make是在本地編譯,編譯所產生的文件在編譯的文件夾裏;  
     make install則把編譯產生的文件(如庫文件,可執行文件,以及cmake指定的要安裝的文件)安裝到某個目錄(一般是系統目錄),這樣其他程序就可以調用編譯的這些東西了。  
    

    安裝需要這個變量:CMAKE_INSTALL_PREFIX ,格式如下:
    cmake -DCMAKE_INSTALL_PREFIX=/usr .
    即生成安裝到/usr目錄的make file

  3. INSTALL一共有如下幾種形式:

    1. 目標文件的安裝:
      INSTALL(TARGETS targets... [ARCHIVE|LIBRARY|RUNTIME] [DESTINATION dirname] [PERMISSIONS permissions...] [...])
      INSTALL(TARGETS myrun mylib mystaticlib RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION libstatic )
      可執行二進制 myrun 安裝到CMAKEINSTALLPREFIX/binlibmylib{CMAKE_INSTALL_PREFIX}/bin 目錄 動態庫 libmylib 安裝到{CMAKE_INSTALL_PREFIX}/lib 目錄
      靜態庫 libmystaticlib 安裝到${CMAKE_INSTALL_PREFIX}/libstatic 目錄
      特別注意的是你不需要關心 TARGETS 具體生成的路徑,只需要寫上 TARGETS 名稱就可以
      了。
    2. 普通文件的安裝
      INSTALL(FILES files... DESTINATION <dir> [PERMISSIONS permissions...])
      非目標文件的可執行程序安裝(比如腳本之類):
      INSTALL(PROGRAMS files... DESTINATION <dir> [PERMISSIONS permissions...])
      腳本安裝後注意設置權限爲:
      OWNER_EXECUTE, GROUP_EXECUTE, 和 WORLD_EXECUTE,即 755 權限
    3. 目錄的安裝
      INSTALL(DIRECTORY dirs... DESTINATION <dir> [FILE_PERMISSIONS permissions...])
      DIRECTORY 後面連接的是所在 Source 目錄的相對路徑,但務必注意:
      abc 和 abc/有很大的區別。
      如果目錄名不以/結尾,那麼這個目錄將被安裝爲目標路徑下的 abc,如果目錄名以/結尾,
      代表將這個目錄中的內容安裝到目標路徑,但不包括這個目錄本身。
    4. 安裝時CMAKE腳本的執行:
      INSTALL([[SCRIPT <file>] [CODE <code>]] [...])

五 靜態庫與動態庫構建

本章主要講了如何編譯動態庫/靜態庫,並安裝庫文件與頭文件(.h)到系統目錄中,以便其他程序調用這個庫.
動態庫是 .so文件,又叫共享庫,靜態庫是.a文件。

  • 如何通過 ADD_LIBRARY 指令構建動態庫和靜態庫;
  • 如何通過 SET_TARGET_PROPERTIES 同時構建同名的動態庫和靜態庫;
  • 如何通過 SET_TARGET_PROPERTIES 控制動態庫版本;
  • 最後將頭文件和共享庫安裝到系統目錄/usr/lib 和/usr/include/hello

所有的添加目錄操作ADD_SUBDIRECTORY(lib)都在最外層的CMakeLists.txt中添加,且目錄都是相對最外層的,不是絕對路徑。

六 如何使用外部共享庫和頭文件

main.c中包含頭文件hello.h會失敗,因爲hello.h 位於/usr/include/hello 目錄中,並沒有位於系統標準的頭文件路徑(系統標準頭文件路徑在/usr/include,其子目錄hello並不是)

#include <hello.h>
int main()
{
HelloFunc();
return 0;
}

所以需要引入頭文件搜索路徑
INCLUDE_DIRECTORIES(/usr/include/hello)
此時編譯還是會失敗,因爲沒有鏈接到hello庫文件。
所以需爲 target 添加共享庫
講了兩個指令
LINK_DIRECTORIES(directory1 directory2 ...)
添加非標準的共享庫搜索路徑,這個對應上面的INCLUDE_DIRECTORIES,本例沒有用到此指令。
TARGET_LINK_LIBRARIES(main hello)

七 cmake 常用變量和常用環境變量

需要注意cmake變量分爲隱式定義和顯式定義兩種。可以理解爲隱式變量就是cmake自動生成的,直接可以用的。
隱式定義如PROJECT 指令,他
會隱式的定義_BINARY_DIR 和_SOURCE_DIR 兩個變
量。顯式定義如 SET 指令,就可以構建一個自定義變量了。

八 cmake 常用指令

主要講了基本指令,INSTALL指令,FIND_指令(如FIND_FILE,FIND_LIBRARY,FIND_PATH,FIND_PACKAGE)

  1. 基本指令
    ADD_DEPENDENCIES,定義 target 依賴的其他 target,確保在編譯本 target 之前,其他的 target 已經被構建。
    CMAKE_MINIMUM_REQUIRED
    比如 CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR)
    如果 cmake 版本小與 2.5,則出現嚴重錯誤,整個過程中止。
  2. FIND指令
    找到目標之後都會存到VAR變量裏面。
    FIND_FILE( name1 path1 path2 …)
    FIND_LIBRARY( name1 path1 path2 …)
    FIND_PATH( name1 path1 path2 …)
    FIND_PROGRAM( name1 path1 path2 …)
    FIND_PACKAGE()

九 複雜的例子:模塊的使用和自定義模塊

FIND_PACKAGE(CURL)
這句指令會自動產生一些變量,如CURL_FOUND CURL_INCLUDE_DIR CURL_LIBRARY,每一個模塊都會定義以下幾個變量:

  • _FOUND
  • _INCLUDE_DIR or _INCLUDES
  • _LIBRARY or _LIBRARIES

FIND_PACKAGE([package name] REQUIRED) REQUIRED 參數,其含義是指這個共享庫是否是工程必須的,如果使用了這個參數,說明這個鏈接庫是必備庫,如果找不到這個鏈接庫,則工程不能編譯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章