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程序