概念性介紹
首先介紹一下cmake。本文是針對cmake菜鳥的,所以必須先對cmake有乙個大概的認識,知道這是什麼、怎麼用以後,才可以考慮交叉編譯不是?
cmake是乙個跨平台自動編譯工具,在kde等開源專案當中有很好的應用,從而證明了cmake的強大功能。cmake的作用是根據設定的配置自動生成編譯指令碼,在linux下就是生成makefile,在windows下就是生成vs的工程檔案,這也是cmake產生的初衷和優點,使用cmake就可以為工程只寫乙個cmake指令碼然後到各種平台上都能編譯。比如乙個跨平台的工程,可以在linux、windows和蘋果上編譯,那麼以前的做法就是提供三套編譯指令碼,linux下就是makefile,windows下就是vs的工程檔案,如果有修改要新增刪除檔案呢,也只能三個地方都修改(任何乙個程式設計師對會對這種做法嗤之以鼻,為什麼不統一到乙個地方呢?),而使用了cmake以後呢,就可以僅僅修改cmake的設定,然後執行cmake,cmake會根據當前的作業系統自動生成可用的的指令碼,然後該make就make該vs就vs吧。
使用cmake
在對cmake有了概念上的認識和能簡單的使用以後,我們就可以開始著手修改它來進行交叉編譯了。首先要明確兩個問題:cmake的大體工作流程是什麼?它是根據什麼指令碼來生成對應平台的編譯指令碼呢?是這樣的,在乙個使用cmake編譯的工程裡,你都會發現cmakelist.txt這樣乙個文字,cmake開始執行的時候,都會從這個檔案開始讀取資訊:要編譯哪些檔案、需要哪些庫、在**找這些庫、在**找對應的標頭檔案、編譯器是什麼等等。也就是說,cmakelist.txt就是cmake的入口函式,要修改cmake就從cmakelist.txt開始。
開啟cmakelist.txt以後,你會看到一堆用大寫字母寫的關鍵字堆出來的東西,不過沒關係,咱們只是要修改它進行交叉編譯,所以不用完全看懂(想完全看懂請參考上文鏈結,寫的比我強多了),只要了解了關鍵的幾個環節就可以了。必須知道的幾個關鍵字是:
set()
表示設定乙個變數,比如set(num 1),設定num的值為1。中間用空格分開,不需要後面加分號。
message("the value of num is $")
列印一條訊息到螢幕,這對你除錯很有幫助,如果要列印其中的變數,用${}引用。
find_package(zlib required)
查詢乙個庫,庫的名字是zlib,後面的required是可選項,表示這個包是必須的,如果找不到不能生成makefile。有了這句以後,一定有乙個對應的findzlib.cmake,在這個檔案裡面,會有具體的如何查詢zlib。
find_path(zlib_include_dir zlib.h 「/home/release/arm11/include」 no_cmake_system_path)
這句話應該出現在findzlib.cmake裡面,表示在目錄「/home/release/arm11/include」下查詢檔案zlib.h,找到以後,把路徑放到變數zlib_include_dir裡面。如果有多個目錄,用空格或者換行分開放在後面就可以了,最好用引號引起來。
find_library(zlib_library_release names $
paths
/home/release/vm_linux/arm11/zlib/lib
/home/release/vm_linux/arm11/zlib/static_lib
這句話也應該是出現在findzlib.cmake裡面,表示在目錄/home/release/vm_linux/arm11/zlib/lib和/home/release/vm_linux/arm11/zlib/static_lib裡查詢庫檔案,找到以後,把目錄放在zlib_library_release裡面。注意,這裡的庫檔案,沒有像上面那樣直接寫出來,而是放在了變數zlib_library_names_release裡面。也是完全可以直接寫出來,用zlib就可以,這裡不過就是提前用了set語句,吧zlib設定到了zlib_library_names_release而已。需要注意的是,這裡有個格式問題,必須把paths放在那裡,跟在paths後面的目錄,才會被查詢到。
這也是乙個多行書寫和在多個目錄裡查詢的例子。
開始交叉編譯
交叉編譯,比如linux x86 到 linux arm11,需要做的是:1、修改編譯器,不能用x86的gcc了,要事先搭建好工具環境(這個在這裡就不寫了,網上大把);2、把要交叉編譯的工程所有依賴的庫都統統替換成arm11編出來的,原來x86編譯出來的不能用;3、一般來說,對應的標頭檔案也需要換,當然理論上x86的標頭檔案也可以用在arm11上,但是保險起見,還是用工具環境裡面和庫一起提供的標頭檔案或者是你自己編庫時候對應的標頭檔案比較好。
設定交叉編譯之前,必須在cmakelist.txt前面加上這樣一句,這樣cmake才會認為你是要交叉編譯:
set(cmake_system_name linux)
其中linux是要編譯過去的平台,如果你是在linux下交叉編譯window的東西,就要寫成windows了。我是在linux x86編linux arm11,所以直接寫linux就可以了。
在通知cmake要交叉編譯以後,還要告訴cmake到哪個路徑下去找庫檔案,因為在交叉編譯的時候cmake是不會自動去系統預設的目錄找庫檔案和標頭檔案的:
set(cmake_find_root_path "/home/release/arm11/library/gnuarm-4.4.2/")
set(cmake_find_root_path_mode_program never)
set(cmake_find_root_path_mode_library only)
set(cmake_find_root_path_mode_include only)
其中的第一行,是告訴cmake查詢的根目錄是什麼。後面分別是告訴cmake怎麼查詢編譯時候的工具程式的位置、庫的位置和標頭檔案的位置。設定為never表示不查詢,設定為only表示只在cmake_find_root_path設定的目錄下查詢,設定為both(這是預設選項)表示既可以在系統目錄下查詢,也可以在cmake_find_root_path下查詢。因為咱們是交叉編譯,所以後兩項的設定了only,對於編譯時呼叫工具,一般來說是需要在系統目錄下查詢的,不過我不需要所以設定為never。
然後,設定編譯器:
set(cmake_c_compiler "/usr/local/cross-tools/arm11/bin/linux-gnueabi-gcc")
直接把編譯器的路徑設定過去就可以了,cmake_c_compiler是c語言編譯器,cmake_cxx_compile是c++語言編譯器。
設定完了這些以後,就要設定一下你的工程所依賴的庫和標頭檔案的位置了,這個很好辦。先在cmakelist.txt裡找find_package提到的庫,然後找這些庫對應的find***.cmake。一般來說,cmakelist.txt會通過include引用find***.cmake所在的目錄的,如果實在沒有線索,就用find -name *.cmake查詢一把好了。
找到find***.cmake以後,在find_path和find_library裡面的路徑上新增上你需要的庫的路徑就可以了。我在上面寫的,就是我自己進行arm11交叉編譯的路徑,原來的都是系統路徑,比如/usr/include等。
完成以後,cmake -> make,就可以了。當然,不會一帆風順,往往是你明明設定了路徑,標頭檔案和庫檔案分明在那裡,可是它偏偏要麼找不到,要麼又找回了系統目錄,那麼這時候可以用message列印一下,看看是不是沒有執行到find_path和find_library,也注意一下cmake_find_root_path_mode_library和cmake_find_root_path_mode_include的only never這些有沒有設定正確。最危險的錯誤是,找到是找到了,但是找到的是系統目錄下的庫,這樣cmake還是正常的,但是編譯是不能通過的,這就需要你認真檢視cmake的日誌和多列印訊息檢查了。
ok,祝你在交叉編譯的路上一路順風!
**:
cmake交叉編譯
1 設定交叉編譯之前,必須在 cmakelist.txt 前面加上這樣一句,這樣 cmake 才會認為你是要交叉編譯 set cmake system namelinux 其中linux 是要編譯過去的平台,如果你是在 linux 下交叉編譯 window 的東西,就要寫成 windows 了。我是...
CMAKE 交叉編譯
步驟需要include open source 的時候,有兩種常見的cross compile 的設定方式 cmake 有公開標準,比較容易自行擴充到不同的平台上 makefile configure all output bin lib 所有要編出來的產物與link方式 有一套cmake語法,與 ...
CMake的交叉編譯
概念性介紹 首先介紹一下cmake。本文是針對cmake菜鳥的,所以必須先對cmake有乙個大概的認識,知道這是什麼 怎麼用以後,才可以考慮交叉編譯不是?cmake是乙個跨平台自動編譯工具,在kde等開源專案當中有很好的應用,從而證明了cmake的強大功能。cmake的作用是根據設定的配置自動生成編...