如何編寫一個工程文件夾下通用的Makefile

来源:https://www.cnblogs.com/cniot/archive/2019/12/14/12040665.html
-Advertisement-
Play Games

新建工程文件夾,在裡面新建 bsp、imx6ul、obj 和project 這 3 個文件夾,完成以後如圖所示: 新建的工程根目錄文件夾 其中 bsp 用來存放驅動文件;imx6ul 用來存放跟晶元有關的文件,比如 NXP 官方的 SDK庫文件;obj 用來存放編譯生成的.o 文件;project ...


 

新建工程文件夾,在裡面新建 bsp、imx6ul、obj 和project 這 3 個文件夾,完成以後如圖所示:

新建的工程根目錄文件夾

其中 bsp 用來存放驅動文件;imx6ul 用來存放跟晶元有關的文件,比如 NXP 官方的 SDK庫文件;obj 用來存放編譯生成的.o 文件;project 存放 start.S 和 main.c 文件,也就是應用文件;將十二章實驗中的 cc.h、fsl_common.h、fsl_iomuxc.h 和 MCIMX6Y2.h 這四個文件拷貝到文件夾 imx6ul 中;將 start.S 和 main.c 這兩個文件拷貝到文件夾 project 中。我們前面的實驗中所有的驅動相關的函數都寫到了 main.c 文件中,比如函數 clk_enable、led_init 和 delay,這三個函數可以分為三類:時鐘驅動、LED 驅動和延時驅動。因此我們可以在 bsp 文件夾下創建三個子文件夾:clk、delay 和 led,分別用來存放時鐘驅動文件、延時驅動文件和 LED 驅動文件,這樣main.c 函數就會清爽很多,程式功能模塊清晰。工程文件夾都創建好了,接下來就是編寫代碼了,其實就是將時鐘驅動、LED 驅動和延時驅動相關的函數從 main.c 中提取出來做成一個獨立的驅動文件 。

使用VScode 新建工程,工程名字為“ledc_bsp”。新建文件 imx6ul.h,然後保存到文件夾 imx6ul 中,新建 bsp_led.h 和 bsp_led.c 兩個文件,將這兩個文件存放到 bsp/led 中,bsp_led.c 裡面就兩個函數 led_init 和 led_switch,led_init 函數用來初始化LED 所使用的IO,led_switch 函數是控制 LED 燈的打開和關閉,這兩個函數都很簡單。

新建 bsp_clk.h 和 bsp_clk.c 兩個文件,將這兩個文件存放到 bsp/clk 中,bsp_delay.c 裡面就兩個函數,delay_short 和 delay。在 main.c 中我們僅僅留下了 main 函數,至此,本常式跟程式相關的內容就全部編寫好了。

在工程根目錄下新建 Makefile 和 imx6ul.lds 這兩個文件,創建完成以後的工程如圖所示:

最終的工程目錄

 

在文件 Makefile 中輸入如下所示內容:

1 CROSS_COMPILE ?= arm-linux-gnueabihf-

2 TARGET ?= bsp 

3

4 CC := $(CROSS_COMPILE)gcc

5 LD := $(CROSS_COMPILE)ld

6 OBJCOPY := $(CROSS_COMPILE)objcopy

7 OBJDUMP := $(CROSS_COMPILE)objdump 

8

9 INCDIRS := imx6ul \

10 bsp/clk \

11 bsp/led \

12 bsp/delay

13

14 SRCDIRS := project \

15 bsp/clk \

16 bsp/led \

17 bsp/delay

18

19 INCLUDE := $(patsubst %, -I %, $(INCDIRS))

20

21 SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))

22 CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c)) 

23

24 SFILENDIR := $(notdir $(SFILES))

25 CFILENDIR := $(notdir $(CFILES)) 26

27 SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))

28 COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))

29 OBJS := $(SOBJS) $(COBJS) 30

31 VPATH := $(SRCDIRS)

32

33 .PHONY: clean

34

35 $(TARGET).bin : $(OBJS)

36 $(LD) -Timx6ul.lds -o $(TARGET).elf $^

37 $(OBJCOPY) -O binary -S $(TARGET).elf $@

38 $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis 

39

40 $(SOBJS) : obj/%.o : %.S

41 $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ {#content}lt;

42

43 $(COBJS) : obj/%.o : %.c

44 $(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ {#content}lt;

45

46 clean:

47 rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)

可以看出本驗的 Makefile 文件要比前面的實驗複雜很多,因為代碼 中的 Makefile 代碼是一個通用 Makefile,我們以後所有的裸機常式都使用這個 Makefile。使用時候只要將所需要編譯的源文件所在的目錄添加到Makefile 中即可,我們接下來詳細分析一下 Makefile 源碼:

第 1~7 行定義了一些變數,除了第 2 行以外其它的都是跟編譯器有關的,如果使用其它編譯器的話只需要修改第 1 行即可。第 2 行的變數 TARGET 目標名字,不同的常式肯定名字不一一樣。

第 9 行的變數 INCDIRS 包含整個工程的.h 頭文件目錄,文件中的所有頭文件目錄都要添加到變數INCDIRS 中。比如本常式中包含.h 頭文件的目錄有imx6ul、bsp/clk、bsp/delay 和bsp/led,所以就需要在變數INCDIRS 中添加這些目錄,即:

INCDIRS := imx6ul bsp/clk bsp/led bsp/delay

仔細觀察的話會發現第 9~11 行後面都會有一個符號“\”,這個相當於“換行符”,表示本行和下一行屬於同一行,一般一行寫不下的時候就用符號“\”來換行。在後面的裸機常式中我們會根據實際情況來在變數 INCDIRS 中添加頭文件目錄。

第 14 行是變數 SRCDIRS,和變數 INCDIRS 一樣,只是 SRCDIRS 包含的是整個工程的所有.c 和.S 文件目錄。比如本常式包含有.c 和.S 的目錄有 bsp/clk、bsp/delay、bsp/led 和 project,即:

SRCDIRS := project bsp/clk bsp/led bsp/delay

同樣的,後面的裸機常式中我們也要根據實際情況在變數 SRCDIRS 中添加相應的文件目錄。

第 19 行的變數 INCLUDE 是用到了函數 patsubst,通過函數 patsubst 給變數 INCDIRS 添加一個“-I”,即:

INCLUDE := -I imx6ul -I bsp/clk -I bsp/led -I bsp/delay

加“-I”的目的是因為 Makefile 語法要求指明頭文件目錄的時候需要加上“-I”。

第 21 行變數 SFILES 保存工程中所有的.s 彙編文件(包含絕對路徑),變數 SRCDIRS 已經存放了工程中所有的.c 和.S 文件,所以我們只需要從裡面挑出所有的.S 彙編文件即可,這裡藉助了函數 foreach 和函數 wildcard,最終 SFILES 如下:

SFILES := project/start.S

第 22 行變數 CFILES 和變數 SFILES 一樣,只是 CFILES 保存工程中所有的.c 文件(包含絕對路徑),最終CFILES 如下:

CFILES = project/main.c bsp/clk/bsp_clk.c bsp/led/bsp_led.c bsp/delay/bsp_delay.c

第 24 和 25 行的變數 SFILENDIR 和CFILENDIR 包含所有的.S 彙編文件和.c 文件,相比變數 SFILES 和 CFILES,SFILENDIR 和 CFILNDIR 只是文件名,不包含文件的絕對路徑。使用函數 notdir 將 SFILES 和 CFILES 中的路徑去掉即可,SFILENDIR 和CFILENDIR 如下:

SFILENDIR = start.SCFILENDIR = main.c bsp_clk.c bsp_led.c bsp_delay.c

第 27 和 28 行的變數 SOBJS 和 COBJS 是.S 和.c 文件編譯以後對應的.o 文件目錄,預設所有的文件編譯出來的.o 文件和源文件在同一個目錄中,這裡我們將所有的.o 文件都放到 obj 文件夾下,SOBJS 和 COBJS 內容如下:

SOBJS = obj/start.o

COBJS = obj/main.o obj/bsp_clk.o obj/bsp_led.o obj/bsp_delay.o

第 29 行變數OBJS 是變數SOBJS 和 COBJS 的集合,如下:

OBJS = obj/start.o obj/main.o obj/bsp_clk.o obj/bsp_led.o obj/bsp_delay.o

編譯完成以後所有的.o 文件就全部存放到了 obj 目錄下,如圖所示:

編譯完成後的obj 文件夾

第 31 行的 VPATH 是指定搜索目錄的,這裡指定的搜素目錄就是變數 SRCDIRS 所保存的目錄,這樣當編譯的時候所需的.S 和.c 文件就會在SRCDIRS 中指定的目錄中查找。

第 34 行指定了一個偽目標 clean,偽目標前面文章 Makefile 的時候已經講解過了。

Makefile 文件內容重點工作是找到要編譯哪些文件?編譯的.o文件存放到哪裡?使用到的編譯命令和前面實驗使用的一樣,其實 Makefile 的重點工作就是解決“從哪裡來到哪裡去的”問題,也就是找到要編譯的源文件、編譯結果存放到哪裡?真正的編譯命令很簡潔。

鏈接腳本 imx6ul.lds 的內容和上一篇文章《通過結構體的方式來定義和使用寄存器地址》一樣,可以直接使用上一的鏈接腳本文件。

本文轉自小平頭電子技術社區:https://www.xiaopingtou.cn/article-104184.html


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

-Advertisement-
Play Games
更多相關文章
  • 前言 公司項目需要做個畫線縮放,我司稱之為瞳距縮放,簡而言之就是:2張圖,從第一張圖畫一條線,再從第二個圖畫一條線,第二條線以第一條為基準,延長到一致的長度,並同比縮放圖片;文字太枯燥,請先實例圖 例子1:以皮卡丘為例,我要把路飛的拳頭縮放到皮卡丘頭那麼大 例子2:以皮卡丘的基準,縮小路飛,與其身高 ...
  • 說明:在同一視窗打開鏈接,只要稍加改造就可以實現,這裡實現的是在新Tab頁打開鏈接,並且支持帶type="POST" target="_blank"的鏈接 github和bitbucket上相關問題: 1、WPF empty POST data when using custom popup htt ...
  • Spire.Cloud.Word.Sdk提供了介面SetBackgroudColor()、SetBackgroudImage()、DeleteBackground()、GetBackgroudColor()用於設置、刪除及讀取Word文檔背景。本文將以C#程式為例演示如何來調用API介面實現以上內容 ...
  • 使用NPOI操作Excel,無需Office COM組件 部分代碼來自於:https://docs.microsoft.com/zh-tw/previous-versions/ee818993(v=msdn.10)?redirectedfrom=MSDN using System.Data; usi ...
  • 在 EF 里有個 `ShadowProperty` (陰影屬性/影子屬性)的概念,你可以通過 FluentAPI 的方式來定義一個不在 .NET model 里定義的屬性,只能通過 EF 里的 `Change Tracker` 來操作這種屬性。 在導出 Excel 的時候,可能希望導出的列並不... ...
  • 前言 上一篇文章介紹IOptions的註冊,本章我們繼續往下看 IOptions IOptions是一個介面裡面只有一個Values屬性,該介面通過OptionsManager實現 OptionsManager OptionsManager實現了IOptions和IOptionsSnapshot,他 ...
  • 一、準備工作: 1、電腦(台式電腦、筆記本電腦); 2、U盤(記憶體大於4G); 3、軟碟通(UltraISO);下載地址:https://pan.baidu.com/s/1tpCiIyIwK_7LaLbyc6PMsQ 提取碼:11vb 4、Win10操作系統; 下載地址:https://pan.ba ...
  • IO測試工具,用於磁碟IO測試,下麵進行使用列表進行記錄: iozone fio dd ioping iotop iostat bonnie++ crystalDisk Atto as-ssd-benchmark hdtune 文件系統測試工具:https://www.cnblogs.com/xuy ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...