如何根據自己的開發板型號下載和配置交叉編譯鏈

来源:https://www.cnblogs.com/zqingyang/p/18252594
-Advertisement-
Play Games

本文介紹瞭如何根據所使用的不同開發板配置不同的交叉編譯環境. 由於在移植LVGL到不同開發板上時遇到了一些問題, 故在問題解決後整理和總結和該文章. ...


V1.0 2024年6月17日 發佈於博客園

目錄

目錄

基本概念

本地編譯

  • 編譯器運行在X86_64架構平臺上,編譯生成X86_64架構的可執行程式

這種編譯器和目標程式都是相同架構的編譯過程,被稱為 本地編譯

交叉編譯

而當前我們希望的是編譯器運行在x86架構平臺上,編譯生成ARM架構的可執行程式,這種編譯器和目標程式運行在不同架構的編譯過程,被稱為 交叉編譯

既然已經有本地編譯,為什麼需要交叉編譯?這是因為通常編譯工具鏈對編譯環境有較高的要求,編譯複雜的程式時,可能需要巨大的存儲空間以及強大的CPU運算能力加快編譯速度。常見的ARM 架構平臺資源有限,無論是存儲空間還是CPU運算能力,都與X86平臺相去甚遠,特別是對於MCU平臺,安裝編譯器根本無從談起。有了交叉編譯,我們就可以在PC上快速編譯出針對其他架構的可執行程式。

相對的,能進行架構“交叉”編譯過程的編譯器,就被稱為 交叉編譯器(Cross compiler)。 交叉編譯器聽起來是個新概念,但在MCU開發中一直使用的就是交叉編譯器, 例如開發STM32、RT1052所使用的IDE軟體Keil(MDK)或IAR,就是在Windows x86架構編譯,生成MCU平臺的應用程式,最後下載到板子執行。

如何選擇編譯器

除了我們安裝的arm-linux-gnueabihf-gcc外,編譯器還有很多版本,如arm-linux-gnueabi-gcc,《GCC和Hello World》章節中使用的本地編譯器gcc全名為x86_64-linux-gnu-gcc。

目前大部分ARM開發者使用的都是由Linaro組織提供的交叉編譯器,包括前面使用APT安裝的ARM-GCC工具鏈,它的來源也是Linaro。Linaro是由ARM發起,與其它ARM SOC公司共同投資的非盈利組織。我們可以在它官網的如下地址找到它提供的ARM交叉編譯器:Linaro Releases ,如下圖所示,在它提供的編譯器列表中首先選擇版本號,然後可選擇ARM架構類型,最後是具體的編譯器平臺。

image

image

編譯器的命名沒有嚴格的規則,但它們的名字中一般包含我們最關心的內容,可根據它們的名字選擇要使用的編譯器:

arch [-os] [-(gnu)eabi(hf)] -gcc

其中的各欄位如下表所示。

GCC編譯器命名格式

欄位 含義
arch 目標晶元架構
os 操作系統
gnu C標準庫類型
eabi 應用二進位介面
hf 浮點模式

以我們安裝的arm-linux-gnueabihf-gcc編譯器為例,表示它的目標晶元架構為ARM,目標操作系統為Linux,使用GNU的C標準庫即glibc,使用嵌入式應用二進位介面(eabi),編譯器的浮點模式為硬浮點hard-float。而另一種名為arm-linux-gnueabi- gcc的編譯器與它的差別就在於是否帶“hf”,不帶“hf”表示它使用soft-float模式。

關於編譯器的各個欄位詳細說明如下:

目標晶元架構

目標晶元架構就是指交叉編譯器生成的程式運行的平臺,如ARM、MIPS,其中ARM交叉編譯器又分為ARMv7、ARMv8及aarch64架構。本書使用的i.MX 6ULL的內核為Cortex-A7,它使用的是ARMv7架構。 arm-linux-gnueabihf-gcc直接以arm表示ARMv7架構。

大小端

指目標晶元的大小端模式,i.MX 6ULL使用的是小端模式。若是大端模式(big edian),編譯器名字中會帶“be”或“eb”欄位進行標標註。

目標操作系統

目標操作系統表示編譯後的程式運行的系統,主要有Linux或bare-metal(無操作系統)兩種,arm-linux-gnueabi-gcc 表示它目標程式的運行環境為Linux系統,程式可以使用Linux下的C標準庫或Linux內核提供的API,如fork等進程函數。而arm- eabi-gcc或arm-none-eabi-gcc表示它們的目標程式運行在無操作系統的環境中。

所以嚴格來說,我們編譯Linux應用程式時應該使用帶“linux”的編譯器,而編譯uboot、裸機程式時,應該使用“bare-metal”類型的裸機編譯器,但很多開發者常常把它們混用也沒有出現問題,這一般是因為開發者編寫的裸機程式本身就沒有使用到Linux系統提供的API,所以才不會出錯。

C標準庫類型

C標準庫類型通常有gnu、uclibc等,分別表示GNU的glibc庫和uclibc庫,這取決於目標操作系統提供的C庫類型,不過由於glibc和uclibc庫是相容的,所以開發者在編通常直接使用GNU類型的編譯器而不管目標系統中的C庫類型。 除了裸機編譯器不帶C庫之外,其它編譯器的C庫類型都是glibc庫的,如arm-linux-gnueabihf-gcc。

應用二進位介面

應用二進位介面(Application Binary Interface),描述了應用程式和操作系統之間或其他應用程式的低級介面。在編譯器選項中主要有“abi”和“eabi”兩種類型,abi通常用在x86架構上,而eabi表示embed abi,即嵌入式架構,如ARM、MIPS等。

浮點模式

部分ARM處理器帶浮點運算單元,代碼需要進行浮點運算時若交給fpu處理,可以加快運算速度。編譯器針對浮點運算的不同處理情況提供了以下幾種模式:

  • hard: 硬浮點類型(hard-float),採用fpu參與浮點運算。 arm-linux-gnueabihf-gcc、armeb-linux-gnueabihf-gcc都是硬浮點類型,即名字中帶“hf”。
  • soft:軟浮點類型(soft-float),即使有fpu浮點運算單元也不用,而是使用軟體模式,arm-linux-gnueabi-gcc、armeb-linux-gnueabi-gcc都是軟浮點類型,即名字中不帶“hf”。
  • softfp:允許使用浮點指令,但保持與軟浮點ABI的相容性。

i.MX6ULL帶有fpu,對於soft-float和hard-float模式都支持,不過本開發板中提供Linux文件系統中的庫都是使用hard模式編譯的,所以編寫應用程式時也需要使用相同類型的編譯器,否則會應用程式運行時會提示找不到庫文件。( 註意!不同板子的軟硬不相容!! )

編譯器版本號

通常來說高版本的編譯器是向後相容的,但開發特定程式時會使用固定的某個版本編譯器,所以程式可能會依賴該版本的編譯器,根據自己要編譯的程式的要求選擇即可。

編譯器類型對程式的影響

講解編譯器類型時提到,編譯器名字中帶hf和不帶hf的差異為硬浮點和軟浮點模式,此處通過小實驗來進行講解,對比兩種編譯器對同樣程式的影響。

安裝軟浮點編譯器

首先安裝浮點模式為soft-float類型的編譯器,即arm-linux-gnueabi-gcc,它與前面使用的arm-linux-gnueabihf-gcc差異為編譯器名字不帶“hf”:

#在主機上執行如下命令

sudo apt install gcc-arm-linux-gnueabi

#安裝完成後使用如下命令查看版本

arm-linux-gnueabi-gcc -v

image

運行軟浮點動態編譯的程式

安裝好arm-linux-gnueabi-gcc軟浮點編譯器後,繼續使用hello.c程式進行實驗。

切換至前面hello.c的目錄,使用不帶“hf”的軟浮點編譯器重新編譯:

#以下命令在主機上運行

#在hello.c程式所在的目錄執行如下命令,註意編譯器名字不帶hf

sudo arm-linux-gnueabi-gcc hello.c –o hello

此處我們使用的是同樣的hello.c代碼文件,只是編譯器的類型不同,再次通過readelf工具來查看具體的程式頭信息,在主機上執行以下命令:

#以下命令在主機上運行

readelf -h hello

image

可以看到結果與前面的差異在於此處的是soft-float類型,而前面的是hard-float類型,這正是編譯器類型不同導致的。

編譯好後,嘗試在開發板上運行該程式,在開發板的終端執行以下命令。

#以下命令在開發板上的終端上執行

#切換至共用的NFS目錄,下麵的目錄根據自己的配置修改

cd /mnt/example/hello_c

#查看是否有存在前面編譯生成的文件

ls

#執行主機編譯的ARM平臺程式,soft-float類型

./hello

image

很遺憾,使用arm-linux-gnueabi-gcc軟浮點編譯的程式無法正常執行,它提示找不到文件或目錄,這是因為程式內部調用了軟浮點的類庫(如glibc庫文件libc.so.6),而開發板配套的庫文件是硬浮點類型的。

開發板的glibc庫類型

關於庫文件的類型,同樣可以使用readelf工具查看,在開發板中執行以下命令

#使用readelf查看開發板的libc.so.6類型

readelf -h libc.so.6

image

表示開發板的glibc庫文件libc.so.6為ARM架構的hard-float類型庫,所以不帶hf編譯器生成的hello程式與它不相容,無法正常運行。

運行軟浮點靜態編譯的程式

既然hello程式是因為庫不相容,那如果程式使用靜態編譯,即程式自帶相關庫的內容,是不是就可以正常運行呢?答案是可以的。我們繼續進行如下測試:

在主機執行如下命令,對hello.c進行靜態編譯生成hello_static程式:

#以下命令在主機上運行

#使用不帶hf的編譯器對hello.c進行靜態編譯,生成的程式名為hello_static

sudo arm-linux-gnueabi-gcc hello.c -o hello_static --static

#查看生成的程式大小

ls -lh

#查看hello_static文件頭

readelf -h hello_static

image

可看到使用靜態編譯得到的hello_static程式比動態編譯的hello大,這是因為它自身包含了庫文件,使用readelf也可以看到hello_static程式依然是soft-float類型的。

接著嘗試在開發板中執行生成的hello_static靜態程式:

#以下命令在開發板上的終端上執行

#切換至共用的NFS目錄,下麵的目錄根據自己的配置修改

cd /mnt/example/hello_c

#查看是否有存在前面編譯生成的文件

ls

#執行主機編譯的ARM平臺程式,soft-float類型,靜態可執行文件

./hello_static

如下圖:

image

hello_static程式正常運行,這就是編譯器及系統庫文件對程式運行的影響。

如何安裝ARM-GCC

安裝交叉編譯工具鏈有如下三種方式:

  • 直接在Ubuntu下使用APT包管理工具下載安裝,操作簡單。
  • 自行下載第三方製作好的工具鏈,如Linaro,好處是選擇豐富,能找到很多不同的版本。
  • 使用crosstool-ng根據需要自己製作,過程複雜,不推薦。

使用APT安裝ARM-GCC

在Ubuntu系統下使用APT包管理工具安裝。

使用的編譯器主要有兩種類型:

  • arm-linux-gnueabihf-gcc:名稱中的Linux表示目標應用程式是運行在Linux操作系統之上的,例如前面的hello.c程式。
  • arm-none-eabi-gcc,名稱中的none表示無操作系統,目標應用程式的運行環境是不帶操作系統的,例如裸機代碼、uboot、內核代碼本身。

不過在開發中比較多的開發者對所有程式都直接用arm-linux-gnueabihf-gcc來編譯,包括裸機代碼和uboot,雖然可能因為代碼本身沒有調用到Linux相關的內容而不會出錯,但這樣做不夠嚴謹,條件允許的話,我們還是嚴格區分開來。

通過APT包管理工具可直接執行以下命令安裝:

#在主機上執行如下命令
sudo apt install gcc-arm-linux-gnueabihf
#安裝完成後使用如下命令查看版本
arm-linux-gnueabihf-gcc –v

可以看到下圖的內容,它表明交叉編譯工具鏈安裝成功了,輸出信息表明瞭它是7.4.0版本的編譯器,其中的 “Target:arm-linux-gnueabihf”也表明瞭它的目標架構。

安裝完成後輸入“arm-linux-gnueabihf-”,再按兩下TAB鍵,終端會提示可用的相關命令,如下圖包含了ARM-GCC工具鏈Binutils的各種工具。

image

安裝後包含的Binutils工具集

交叉編譯Hello World程式

安裝好交叉編譯器後,直接使用它對Hello World程式進行交叉編譯即可。

交叉編譯器與本地編譯器使用起來並沒有多大區別。對於源文件的編譯過程,都是四個階段:預處理,編譯,彙編以及鏈接,區別隻在於編譯工具。

在主機上執行如下命令對Hello World程式進行交叉編譯:

#以下命令在主機上運行

#在hello.c程式所在的目錄執行如下命令

arm-linux-gnueabihf-gcc hello.c –o hello

同樣的C代碼文件,使用交叉編譯器編譯後,生成的hello已經變成了ARM平臺的可執行文件,可以通過readelf工具來查看具體的程式信息。

readelf工具在系統安裝GCC編譯工具鏈時一起被安裝了,我們可以直接使用。在主機上執行以下命令:

#以下命令在主機上運行

readelf -a hello

image

使有readelf查看交叉編譯器生成的hello程式

可看到hello程式的系統架構為ARM平臺,標誌中表明瞭它是hard-float類型的EABI介面。

編譯好後,即可嘗試在開發板上運行,在開發板的終端執行以下命令,執行結果如下圖所示。

#以下命令在開發板上的終端上執行

#切換至共用的NFS目錄,下麵的目錄根據自己的配置修改

cd /mnt/example/hello_c

#查看是否有存在前面編譯生成的文件

ls

#執行主機編譯的ARM平臺程式

./hello

image

下載第三方製作好的工具鏈

下載

Linaro Releases

image

正點原子的板子應該下載x86_64的版本, 因為開發平臺是64位的linux. 應該下載帶hf的, 表示硬浮點, 因為正點原子的板子的Linux文件系統中的庫都是使用hard模式編譯的.

官方給的4.9版本太老, 使用8.x的lvgl庫時會報錯! 要修改的有很多. 故推薦5.4

安裝

sudo apt-get install lsb-core lib32stdc++6 #安裝其它的庫

在電腦的Linux系統中切換為root用戶

su - #切換root
cd /
mkdir /DevelopmentTool/zdyz/gcc/ #創建文件夾
# 然後將 下載好的 gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabihf.tar.xz 上傳到其中
tar -vxf gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabihf.tar.xz #解壓
cd /etc/profile.d #進入全局腳本文件夾
touch IoT_development.sh #創建自定義腳本文件 
chmod 644 IoT_development.sh
vim IoT_development.sh
# 修改環境變數, 加入下麵的內容即可
export PATH=/DevelopmentTool/zdyz/gcc/gcc-linaro-5.4.1-2017.01-x86_64_arm-linux-gnueabihf/bin:$PATH
# 重啟系統或
source ./IoT_development.sh
# 查看版本號  如果交叉編譯器安裝正確的話就會顯示版本號,如圖
arm-linux-gnueabihf-gcc -v

使用

# 終端直接編譯
arm-linux-gnueabihf-gcc main.c -o demo.out
# Makefile編寫
CC = arm-linux-gnueabihf-gcc

image

可見編譯成功.

若有多個不同版本的交叉編譯鏈, 使用時使用完整的名稱即可.

參考資料

本文來自博客園,作者:舟清颺,轉載請註明原文鏈接:https://www.cnblogs.com/zqingyang/p/18252594


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在嵌入式Linux設備中,經常使用jffs2文件系統來作為參數區的文件系統格式。至於為什麼要使用jffs2來作為參數區的文件系統,我猜大部分人都沒有做過多的思考。 jffs2在2001年被設計出來,距今已過二十多年,現在在嵌入式設備中它還在被大量使用、說明這套設計本身是沒有問題。 但是,你是否有... ...
  • 為了更好的閱讀體驗,請點擊這裡 先學習一下 zsh 的配置吧~ 參考資料 從 0 開始:教你如何配置 zsh powerlevel10k 如何給 Xshell 配置呢 當我安裝完 oh-my-zsh、powerlevel10k、fast-syntax-highlighting、以及若幹(powerl ...
  • 腳本工具可以幫助我們完成一些需要重覆勞動的工作; 基礎語法: "#"為註釋符號 1:#指定腳本運行環境為 /bin/bash #! /bin/bash 2:輸入參數,xxx為變數名,多個變數名用空格隔開read xxx 輸出參數echo xxx 3: 變數和運算符的定義:這是每個編程語言必不缺少的部 ...
  • 在伺服器linux系統環境下,想要上傳和下載文件到本地PC通常是比較麻煩的, 在這個過程中,將層級複雜的文件夾壓縮成壓縮包再進行上傳/下載更為方便, 其中常用到的linux指令就是 zip / unzip, 文件壓縮指令 zip 個人認為,在日常科研中,常用的參數有兩個: -q 不顯示指令執行過程( ...
  • 0、思考與回答 0.1、思考一 為什麼要增加時間片輪詢? 目前的 RTOS 內核已經支持搶占優先順序,即高優先順序的任務會搶占低優先順序的任務得到執行,但是對於同等優先順序的任務,如果不支持時間片輪詢,則只能有一個任務運行,並且由於優先順序相同所以除延時阻塞到期外也不會發生任務調度,因此需要增加時間片輪詢保證 ...
  • 本文介紹在Linux Ubuntu操作系統的電腦中,安裝Anaconda環境與Python語言的方法。 在之前的文章Anaconda與Python環境在Windows中的部署中,我們介紹了在Win10電腦中,安裝Anaconda環境與Python語言的方法;而在本文中,我們就詳細介紹一下在Linux ...
  • 0、思考與回答 0.1、思考一 如何處理進入阻塞狀態的任務? 為了讓 RTOS 支持多優先順序,我們創建了多個就緒鏈表(數組形式),用每一個就緒鏈表表示一個優先順序,對於阻塞狀態的任務顯然要從就緒鏈表中移除,但是阻塞狀態的任務並不是永久阻塞了,等待一段時間後應該從阻塞狀態恢復,所以我們需要創建一個阻塞鏈 ...
  • liwen01 2024.06.16 前言 先提幾個問題:什麼是文件系統崩潰一致性?為什麼會出現文件系統崩潰一致性問題?有哪些方法可以解這個問題?它們各自又有哪些局限性? window系統電腦異常後會藍屏、手機死機卡頓後我們會手動給它重啟,大部分設備的系統在遇到不可修複的嚴重異常後都會嘗試通過重啟來 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...