Cmake使用教程-交叉編譯

Cmake Cross Compile UserGuide

1. 設置系統和工具鏈

對於交叉編譯,CMake並不知道目標系統是什麼,所以需要設置一些CMake變量來告知CMake,

  • CMAKE_SYSTEM_NAME:即目標系統名,這裏是Linux
  • CMAKE_SYSTEM_PROCESSOR :目標系統的處理器名,這裏是arm

對於工具鏈,則是通過下面2個變量來定位,

  • CMAKE_C_COMPILER:C編譯器的可執行文件名稱
  • CMAKE_CXX_COMPILER:C++編譯器的可執行文件名稱

這些變量可以在調用CMake時通過命令行傳遞,但是這種做法容易出錯,而且用起來不方便,所以CMake提供了工具鏈文件的方式來傳遞這些變量信息。

2. 工具鏈文件

我們在工程裏新建一個文件叫arm_linux_setup.cmake,放置位置如下(也可以放在別的地方),

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(tools /home/wh/work/cross_compile/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)

注意:

  • 上述命令必須寫入腳本中,使用 -DCMAKE_TOOLCHAIN_FILE=xxx.cmake 的方式使用。不能直接寫入 CMakeLists.txt 或使用 include(xx.cmake) 。
  • set(CMAKE_SYSTEM_NAME Linux):該指令必須存在,其目的是設置目標機使用的操作系統名稱,支持Linux,QNX,WindowsCE,Android等。如果沒有操作系統,那麼就寫 Generic。執行該指令後,cmake 變量CMAKE_CROSSCOMPILING 會自動被設置爲 TRUE,此時 cmake 就會“知道“現在執行的是交叉編譯;

tools是本人使用的交叉工具鏈路徑,可以根據自己的實際文件來做修改。

3. 編譯

使用CMake的變量CMAKE_TOOLCHAIN_FILE來指定工具鏈文件,cd到build目錄,然後執行下面的命令,

# 注意,工具鏈文件的指定一定要緊跟cmake命令之後,不能放到 .. 後面
cmake -DCMAKE_TOOLCHAIN_FILE=../arm_linux_setup.cmake -DCMAKE_INSTALL_PREFIX=/XXX/XXX ..

使用make開始安裝編譯源代碼

make  # 編譯源代碼
make DESTDIR=/install/directory install # 配置安裝路徑爲指定路徑

使用file命令去查看這個文件,可以看到其運行平臺是32位ARM處理器上的Linux系統,

file executable

使用工具鏈文件的好處就是隻要編寫一遍,然後在任意地方只需要使用CMAKE_TOOLCHAIN_FILE去指定其位置就可以了,非常方便。

4. 其他說明

     通常,我們在開發時,需要使用系統庫或第三方庫的功能,在生成可執行文件時,將其進行鏈接。cmake 提供了 FIND_PROGRAM(),FIND_LIBRARY(), FIND_FILE(), FIND_PATH()FIND_PACKAGE() 實現相應的查找功能。如果我們在進行交叉編譯時使用了上述指令,那麼並不能生成可執行文件。因爲默認情況下,上述指令查找的是主機上的相關文件,其並不適用於目標機器。還好,cmake 爲我們提供了相應的變量:

     CMAKE_FIND_ROOT_PATH設置其值爲一系列的目錄set(CMAKE_FIND_ROOT_PATH path1 path2 path3 ...),這樣在執行 FIND_XXX() 指令時就會從這一系列的目錄中進行查找。

     跟隨該變量的有下述 3 個變量,它們的值爲 NEVER 、 ONLY 或 BOTH:

     CMAKE_FIND_ROOT_PATH_MODE_PROGRAM:如果設置爲 NEVER,那麼 CMAKE_FIND_ROOT_PATH 就不會對 FIND_PROGRAM() 產生影響, FIND_PROGRAM() 不會在 CMAKE_FIND_ROOT_PATH 指定的目錄中尋找;如果設置爲 ONLY,那麼 FIND_PROGRAM() 只會從CMAKE_FIND_ROOT_PATH 指定的目錄中尋找;如果設置爲 BOTH,那麼 FIND_PROGRAM() 會優先從 CMAKE_FIND_ROOT_PATH 指定的目錄中尋找,再從默認的目錄中尋找。

     因爲 FIND_PROGRAM() 大部分情況下用於尋找可執行程序,給後續的 EXECUTE_PROCESS()ADD_CUSTOM_COMMAND() 指令使用。並且,只有主機在生成編譯文件時使用該可執行程序。因此通常設置 CMAKE_FIND_ROOT_PATH_MODE_PROGRAM 爲 NEVER,set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

     CMAKE_FIND_ROOT_PATH_MODE_LIBRARY:由於在進行交叉編譯,所以只能使用 FIND_LIBRARY() 查找符合目標機器的庫文件,因此設置該變量值爲ONLY(set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)),表示只從 CMAKE_FIND_ROOT_PATH 指定的目錄中查找;

     CMAKE_FIND_ROOT_PATH_MODE_INCLUDE:同上,將其值設置爲 ONLY。

Reference

cmake:交叉編譯
Cmake Cross Compile Office Doc
CrossCompile for Raspiberry
CMake交叉編譯Arm Linux程序

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