這兩天需要把一個CDVS的工程代碼從Linux 平臺上移植到ARM平臺上,花了兩天才搞定,之前很早申請的博客,到現(xiàn)在還沒有技術(shù)文章會,以后決定凡是花兩三天才搞定的東西都會把解決過程發(fā)到這里,很多東西靠百度什么的不太好使,必要的時候確實Google更好用。想想也是,在百度上搜,很多都是迄今為止中國程序員碰到過的問題,在Google上搜就是全世界程序員碰到過的問題。廢話不多說了,切入正題。
由于原工程已經(jīng)在PC-Linux上跑通,所以只需要修改configure的配置參數(shù)即可。這里我通過linux下的build.sh來對configure傳入腳本。
下面試build.sh的腳本內(nèi)容:
1 #!/bin/sh 2 # build the CDVS Test Model 3 # with full optimizations and multithreading: 4 CFLAGS="-march=armv7-a -O2 -DNDEBUG -fopenmp -pipe" 5 export PATH=$PATH:/usr/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin 6 # run configure with optimization flags and PRepending "tm-" to all binaries (e.g. tm-extract, tm-match, etc.) 7 mkdir -p build 8 cd build 9 CC=arm-hik_v7a-linux-uclibcgnueabi-gcc CXX=arm-hik_v7a-linux-uclibcgnueabi-c++ LD=arm-hik_v7a-linux-uclibcgnueabi-ld AR=arm-hik_v7a-linux-uclibcgnueabi-ar AS=arm-hik_v7a-linux-uclibcgnueabi-as NM=arm-hik_v7a-linux-uclibcgnueabi-nm STRIP= RANLIB=arm-hik_v7a-linux-uclibcgnueabi-strip OBJDUMP=arm-hik_v7a-linux-uclibcgnueabi-objdump ../configure --build=i386-pc-linux-gnu --host=arm-hik_v7a-linux-uclibcgnueabi --target=arm-hik_v7a-linux-uclibcgnueabi --cache-file=arm-hik_v7a-linux-uclibcgnueabi.cache prefix=$HOME/cdvs_bin_for_arm --program-prefix="tm-" CFLAGS="${CFLAGS}" CXXFLAGS="${CFLAGS}" 10 # build all binaries11 make12 # install all binaries in $HOME/bin (no need of admin priviledges)13 make install對腳本的內(nèi)容進(jìn)行分析:
首先是CFLAGS,里面定義了需要傳入到configure的參數(shù)這里的-march變量是目標(biāo)機(jī)的系統(tǒng)架構(gòu)也就是architecture,由于我們的目標(biāo)機(jī)上平臺是armv7-a,所以此處賦值armv7-a。此處要留心,我一開始沒有改,依然是native,那么configure會自動的用本機(jī)的arch值傳入,這樣就會編譯失敗。我一開始也不清楚這個地方具體應(yīng)該填什么。這樣我們可以查看編譯器支持的芯片類型。
我的編譯器的前綴是arm-hik_v7a-linux-uclibcgnueabi,所以這是這個編譯器下所有工具的前綴。
由于交叉編譯器已經(jīng)安裝在/usr/local/arm目錄下,并且已經(jīng)把/uar/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin目錄添加到/etc/profile文件中,所以在控制臺中可以直接調(diào)用編譯器。
在控制臺中我們輸入arm-hik_v7a-linux-uclibcgnueabi-gcc -v 此命令會輸出該編譯器的版本信息

在輸出圖片中我們可以看到變量--with-arch=armv7-a,一開始輸成了ARMv7-A,各種亂試,確實需要從根源下手,直接查看編譯器版本信息。OK,接下來進(jìn)入下一步。
可以看到腳本中還有一句PATH=$PATH:/usr/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin 這是對當(dāng)前腳本執(zhí)行的環(huán)境加上環(huán)境變量,不知道為什么在系統(tǒng)中添加環(huán)境變量后還是腳本運(yùn)行時不能檢索到編譯器位置,一直報錯,可以看config.log的輸出日志。
PATH: /usr/local/sbinPATH: /usr/local/binPATH: /usr/sbinPATH: /usr/binPATH: /sbinPATH: /bin
在這里并沒有將我們環(huán)境變量的值給讀進(jìn)來,
而我打開終端中直接打印PATH,發(fā)現(xiàn)值已經(jīng)在里面了。此處不太明白,所以我在build.sh里又中添加了export語句在臨時追加環(huán)境變量。
louyihang@Ubuntu:~$ echo $PATH/home/louyihang/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin:/usr/local/arm/arm-hik_v7a-linux-uclibcgnueabi/bin
接著我們在當(dāng)前目錄下用mkdir 創(chuàng)建build文件夾,整個編譯過程中的各種輸出文件都將會在這里除了最后的exe。
在下面可以看到我定義了一堆變量,用來指定編譯器
CC=arm-hik_v7a-linux-uclibcgnueabi-gcc CXX=arm-hik_v7a-linux-uclibcgnueabi-c++ LD=arm-hik_v7a-linux-uclibcgnueabi-ld AR=arm-hik_v7a-linux-uclibcgnueabi-ar AS=arm-hik_v7a-linux-uclibcgnueabi-as NM=arm-hik_v7a-linux-uclibcgnueabi-nm STRIP= RANLIB=arm-hik_v7a-linux-uclibcgnueabi-strip OBJDUMP=arm-hik_v7a-linux-uclibcgnueabi-objdump ../configure --build=i386-pc-linux-gnu --host=arm-hik_v7a-linux-uclibcgnueabi --target=arm-hik_v7a-linux-uclibcgnueabi --cache-file=arm-hik_v7a-linux-uclibcgnueabi.cache prefix=$HOME/cdvs_bin_for_arm --program-prefix="tm-" CFLAGS="${CFLAGS}" CXXFLAGS="${CFLAGS}" CC變量指定的是gcc編譯器,可以在configure文件中得知這個變量來告訴configure關(guān)于交叉編譯器gcc的信息,同理CXX 指的是C++,只要前綴不變,所以接下來依樣畫葫蘆把所需要用到的編譯器直接定義在 configure語句執(zhí)行之前。
CC=arm-hik_v7a-linux-uclibcgnueabi-gcc CXX=arm-hik_v7a-linux-uclibcgnueabi-c++ LD=arm-hik_v7a-linux-uclibcgnueabi-ld AR=arm-hik_v7a-linux-uclibcgnueabi-ar AS=arm-hik_v7a-linux-uclibcgnueabi-as NM=arm-hik_v7a-linux-uclibcgnueabi-nm STRIP= RANLIB=arm-hik_v7a-linux-uclibcgnueabi-strip OBJDUMP=arm-hik_v7a-linux-uclibcgnueabi-objdump
需要注意的是其實你這些語句總共是4行,其實這里是沒有回車的,因為這整個一長串都是一條語句,只不過在configure的的編譯器參數(shù)需要再configure之前被設(shè)置。
OK這里弄完。接著看我們configure之后的參數(shù)。
--build參數(shù)指定的是編譯器完成整個build的工程的機(jī)器結(jié)構(gòu)在這里我們輸入i386-pc-linux-gnu
--host參數(shù)指定最終生成可執(zhí)行文件的運(yùn)行環(huán)境 arm-hik_v7a-linux-uclibcgnueabi (也就是我們用的交叉編譯器工具的前綴——即編譯器的文件夾的名字 )這些都是一致的
--target參數(shù)目標(biāo)機(jī)的環(huán)境等同host。
--cache-file在這里指定緩存文件的名字,在該文件中我們可以看到編譯過程中的整個測試過程的結(jié)果和反饋。
--prefix=$Home/cdvs_bin_for_arm 這里是最終生成可執(zhí)行文件的安裝目錄也就是exe的存放目錄??梢愿鶕?jù)自己的需要調(diào)整。
后面的--program-prefix CFLAGS CXXFLAGS的參數(shù)與linux PC機(jī)上一樣不用調(diào)整。
OK最后在最后跟上make make install 完成整個configure的配置。
當(dāng)然什么事情都不會跟教程一樣順利,接下來的問題總是不斷。
在終端中輸入 sudo ./build.sh | more
看輸出內(nèi)容

可以看到出現(xiàn)了 checking whether the C compiler works ...no 后面還出現(xiàn)了error。
看來 交叉編譯器并沒有開始工作。所以轉(zhuǎn)入到build 文件夾下 打開config.log的輸出日志。

看到一條語句arm-hik_v7a-linux-uclibcgnueabi-gcc-raw: libgomp.spec: No such file or directory
很明顯這是由于庫里少了一個文件,沒有被編譯器找到,所以需要再庫里面添加進(jìn)liggomp.spec這個文件。
當(dāng)時把我迷糊了好久,上哪里去整個這個文件,上百度也百度不到,上google也不好使。
想到他畢竟是個gcc的編譯器,庫里面的東西大概都差不多吧,所以我去找了標(biāo)準(zhǔn)的arm-linux-gcc的庫文件,記得當(dāng)時的百度云里還有一份stm32的資料,整了一個下來。

打開這個arm-linux-gcc-4.4.3.tgz直接在壓縮包里面檢索關(guān)鍵字libgomp
果然在這個編譯器同樣的lib下有了一堆跟libgomp相關(guān)的文件,所以把這些文件拷入到我們所需要的arm-hik_v7a-linux-uclibcgnueabi的編譯器庫下面
OK再運(yùn)行一次configure

咦,居然還是不過,再次看config.log文件

看到中間有一句 lib/libgomp.so: file not recognized: treating as linker script 和下面 lib/libgomp.so:1: syntax error。 不識別,這文件應(yīng)該是不需要的被引入了,所以在Lib中將其刪除。再次運(yùn)行

OK 大功告成,可以看到whether the C compiler works .... yes 接下來一堆文件的測試,并且在指定目錄生成了exe。
整個過程花了差不多2天時間,第一次弄交叉編譯,確實是有點費勁的,也發(fā)現(xiàn)了一些自己的不足,之前沒有看log文件的習(xí)慣,后來發(fā)現(xiàn)這個東西是非常好的,非常有助于我們分析問題的原因。第一次寫blog,寫的比較亂,希望能幫到碰到同樣問題的你!
新聞熱點
疑難解答
圖片精選