在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

【Makefile】通用模板

_light ? 來源:_light ? 作者:_light ? 2023-04-15 12:47 ? 次閱讀

工程目錄

假如我們有以下目錄結構:

.
├── inc
│   ├── add.h
│   └── sub.h
├── main.c
└── src
    ├── add.c
    └── sub.c

文件中的內容如下:

//main.c
#include 
#include "add.h"
#include "sub.h"

int main()
{
    int x = 9;
    printf("x = %d\\\\\\\\\\\\\\\\n", add_one(x));
    printf("x = %d\\\\\\\\\\\\\\\\n", sub_one(x));
    return 0;
}

//add.h
int add_one(int x);

//add.c
int add_one(int x)
{
    return x + 1;
}

//sub.h
int sub_one(int x);

//sub.c
int sub_one(int x)
{
    return x - 1;
}

對于上述這樣的多.c文件,又不在同一個目錄下的大型工程中,借助makefile可以來減輕工作任務

(上述是一個很小很小的工程)

準備工作

在使用gcc 將 源文件 main.c編譯成 可執行目標程序 總共需要4步:

在這里插入圖片描述

平常在編譯項目時,預處理與編譯器這兩步會省略,是先將源文件 .c 編譯成 .o 文件,然后再鏈接 .o 文件

gcc -c main.c -o main.o
gcc main.o -o main.exe/main.out

編寫Makefile

接下來會一步一步的編寫一個Makefile文件,這個文件可以適配于大部分C/C++工程,讓我們開始吧!

1. 定義可執行文件名、GCC類型

先定義一個最終可執行文件名的變量:

TARGET = main

變量值可以隨意定義。

gcc分為很多種,常見的有:gcc、arm-linux-gcc、arm-none-eabi-gcc等等,所以為了Makefile適配更多的C/C++項目,可以將編譯器定義一個變量,這后續更改起來很方便。我這里使用的gcc:

CC = gcc

2. 中間文件的路徑的變量

由前文可知,在編譯過程中會編譯出很多的 .o 文件,一般將這些編譯過程中產生的文件單獨放到一個文件夾下,文件夾的名字大多叫做 build ,定義一個變量 BUILD_DIR 該變量的值就是build,用來存放中間產物,在后續編譯過程中會用到:

BUILD_DIR = build

3、.c 源文件的路徑

事先需要將工程中所用到的源文件 .c 的路徑,這樣在后續中就可直接得到 .c 文件,定義一個變量 SRC_DIR 來存放源文件 .c 的路徑

SRC_DIR =     \\\\\\\\\\\\\\\\
	./    \\\\\\\\\\\\\\\\
	./src

4、 頭文件的路徑

接著得到所有用到的頭文件路徑:

INC_DIR = \\\\\\\\\\\\\\\\
	./inc

這gcc選項中有這個參數 -I 是告訴編譯器頭文件的路徑,在后續中會使用Makefile的一個函數為每個頭文件路徑添加 -I

5、為頭文件路徑添加 -I

當所引用的頭文件與源文件不在同一級目錄下時需要添加 -I 選項指定頭文件路徑,在第四步中已經獲取到頭文件的路徑,下面借助一個Makefile中的一個函數在每個頭文件前面添加 -I

首先看一下函數 patsubst 的介紹。

$(patsubst ,,)
  • 名稱:模式字符串替換函數。

  • 功能:查找 中的單詞(單詞以“空格”、“Tab”或“回車”“換行”分隔)是否符合模式 ,如果匹配的話,則以 替換。這里, 可以包括通配符 % ,表示任意長度的字串。如果 中也包含 % ,那么, 中的這個 % 將是 中的那個 % 所代表的字串。(可以用 **** 來轉義,以 % 來表示真實含義的 % 字符)

  • 返回:函數返回被替換過后的字符串。

  • 示例:

    $(patsubst %.c, %.o, x.c.c bar.c)
    

    把字串 x.c.c、bar.c 符合模式 %.c 的單詞替換成 %.o ,返回結果是 x.c.o bar.o-

定義一個變量 INCLUDE

INCLUDE	= $(patsubst %, -I %, $(INC_DIR))

這樣就會在每個頭文件路徑前加入 -I 了。

6、得到帶路徑的源文件

在第三步中,我們得到了 .c 文件的存放路徑,這一步我們得到帶有路徑的 .c 文件,簡單來說就是,假如在src目錄下有一個foo.c的文件,在第3步中只得到了 src 這個目錄,這一步得到的是 src/foo.c 。

得到目錄下的 .c 文件需要用到Makefile中的兩個函數,foreach函數 、wildcard 函數

1、wildcard 函數

$(wildcard PATTERN...)

在Makefile中,它被展開為已經存在的、使用空格分開的、匹配此模式的所有文件列表

2、foreach函數

$(foreach < var >,< list >,< text >)

這個函數的意思是,把參數 中的單詞逐一取出放到參數 所指定的變量中,然后再執行 所包含的表達式。每一次 會返回一個字符串,循環過程中, 的所返回的每個字符串會以空格分隔,最后當整個循環結束時, 所返回的每個字符串所組成的整個字符串(以空格分隔)將會是foreach函數的返回值。

所以, 最好是一個變量名,\\ 可以是一個表達式,而 中一般會使用 這個參數來依次枚舉 中的單詞。

舉個例子:

names := a b c d
files := $(foreach n,$(names),$(n).o)

上面的例子中, (name) 中的單詞會被挨個取出,并存到變量 n 中, (n).o 每次根據 **(n) 計算出一個值,這些值以空格分隔,最后作為foreach函數的返回,所以, **(files) 的值是 a.o b.o c.o d.o 。

使用這兩個函數得到帶路徑的 .c 文件

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

7. 得到不帶路徑的 .c 文件

在上一步中我們得到了帶路徑的 .c 文件,這步借助Makefile中的函數 notdir 將路勁去除,得到 "真正的.c"

notdir 函數

$(notdir
  • 名稱:取文件函數——notdir。
  • 功能:從文件名序列 中取出非目錄部分。非目錄部分是指最後一個反斜杠( / )之后的部分。
  • 返回:返回文件名序列 的非目錄部分。
  • 示例:
    $(notdir src/foo.c hacks)
    
返回值是 foo.c hacks 。

定義一個變量 CFILENDIR 來存放不帶路徑的 .c 文件:

CFILENDIR := $(notdir  $(CFILES))

8. 將工程中的.c 文件替換成 ./build 目錄下對應的目標文件 .o

這一步只是簡單的字符串進行替換,對原文件不進行任何操作。我們可以先寫一個偽目標,打印一下變量 CFILENDIR 的內容

# 打印結束后可以刪除
print:
	@echo $(CFILENDIR)

使用 make 查看一下輸出結果,會得到字符串:main.c add.c sub.c

在前面講過編譯時會在 build 目錄下得到.o文件,這個.o 文件就是由.c文件生成的,因此 main.c add.c sub.c 會對應于 build 目錄下的 main.o add.o sub.o

由于現在不是編譯階段,我們只對字符串進行個簡單的替換操作,定義一個變量 COBJS 用來存放目錄 build 下的 .o 文件

COBJS = $(patsubst %, ./$(BUILD_DIR)/%, $(patsubst %.c, %.o, $(CFILENDIR)))

此時變量 COBJS 的值就是:./build/main.o ./build/add.o ./build/sub.o

到目前為止已經得到了工程中的源文件 CFILENDIR 、可重定位目標文件 COBJS 以及帶有 -I 前綴的頭文件路徑 INCLUDE ,注意,到目前為止我們操作的只是字符串而已,還未對源文件做任何操作。

9、搜索源文件

在我們這個工程中,有兩個目錄下存放著 .c 文件,當make需要去找尋文件的依賴關系時,可以使用變量 VPATH 讓make在自動在這兩個目錄中去找依賴文件。

VPATH = $(SRC_DIR)

10、生成可重定位目標文件(編譯階段)

$(COBJS) : $(BUILD_DIR)/%.o : %.c
	@mkdir -p $(BUILD_DIR)
	$(CC) $(INCLUDE) -c -o $@ $

會將源文件 .c 編譯成可重定位目標文件 .o

11、鏈接 .o 文件

此步驟是最后一步,將所有的 .o 文件鏈接成可執行程序

可執行文件可以生成到指定的目錄下,我這里生成到了 build 目錄下

$(BUILD_DIR)/$(TARGET).exe : $(COBJS)
	$(CC) -o $@ $^

此時,Makefile 已經編寫完成。

當執行make 時,發現并不是預期的目標,只執行了一句指令:

gcc  -I ./inc -c -o build/main.o main.c

這是因為make會一層又一層地去找文件的依賴關系,直到最終編譯出第一個目標文件,如是依賴存在編譯成功后就會退出執行,若是沒有找到依賴,則會報錯并退出。

當想達到預期的目標,共有兩種辦法:

第一種:將目標**(BUILD_DIR)/**(TARGET).exe 寫在目標 $(COBJS) 的前面,這樣就可以達到預期的結果了。

第二種:使用關鍵字 all ,寫在關鍵字 all 后面的目標都會執行一次,直到所有目標執行完成,或者某個目標不成立。

此時,再執行make,就能得到預期的結果了

image.png

12、清理目標

make編譯之后會在工程中多出很多目標文件*.o,可以寫一個目標 clean 用來刪除工程中的目標文件

clean:
	rm -rf $(BUILD_DIR)

Makefile全部內容:

# 可執行文件名
TARGET = main

# gcc類型
CC = gcc

# 存放中間文件的路徑
BUILD_DIR = build

#存放.c 源文件的文件夾
SRC_DIR = \\\\\\\\\\\\\\\\
	./    \\\\\\\\\\\\\\\\
	./src

# 存放頭文件的文件夾
INC_DIR = \\\\\\\\\\\\\\\\
	./inc

# 在頭文件路徑前面加入-I
INCLUDE	= $(patsubst %, -I %, $(INC_DIR))

# 得到帶路徑的 .c 文件
CFILES := $(foreach dir, $(SRC_DIR), $(wildcard $(dir)/*.c))

# 得到不帶路徑的 .c 文件
CFILENDIR := $(notdir  $(CFILES))

# 將工程中的.c 文件替換成 ./build 目錄下對應的目標文件 .o
COBJS = $(patsubst %, ./$(BUILD_DIR)/%, $(patsubst %.c, %.o, $(CFILENDIR)))

# make 自動在源文件目錄下搜索 .c 文件
VPATH = $(SRC_DIR)

$(BUILD_DIR)/$(TARGET).exe : $(COBJS)
	$(CC) -o $@ $^

$(COBJS) : $(BUILD_DIR)/%.o : %.c
	@mkdir -p $(BUILD_DIR)
	$(CC) $(INCLUDE) -c -o $@ $ 

clean:
	rm -rf $(BUILD_DIR)

至此,Makefile通用模板已經編寫完成,文章中若有錯誤的地方請在評論區指出。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 文件
    +關注

    關注

    1

    文章

    569

    瀏覽量

    24775
  • Makefile
    +關注

    關注

    1

    文章

    125

    瀏覽量

    19193
  • make
    +關注

    關注

    0

    文章

    16

    瀏覽量

    12530
收藏 人收藏

    評論

    相關推薦

    Linux Makefile通用模板詳解

    對于Windows下開發,很多IDE都集成了編譯器,如Visual Studio,提供了“一鍵編譯”,編碼完成后只需一個操作即可完成編譯、鏈接、生成目標文件。
    發表于 08-08 09:48 ?936次閱讀
    Linux <b class='flag-5'>Makefile</b><b class='flag-5'>通用</b><b class='flag-5'>模板</b>詳解

    如何調整MPlab-ide生成的makefile

    你好!我試圖修改MPLAB IDE生成的makefile,以便在編譯每個文件之前執行代碼檢查器。我想修改makefile生成器或makefile模板,添加命令行來執行這個檢查器,如果檢
    發表于 09-02 13:15

    使用Makefile+gcc編譯STM32

    方式,那時已經使用Notepad++了,如今也一起在使用。Makefile模板如下:# STM32F103 Makefile模板# 參考來源:#
    發表于 11-22 08:10

    怎樣去編寫通用makefile文件的源碼呢

    怎樣去編寫通用makefile文件的源碼呢?其實驗結果有哪些?
    發表于 12-27 06:41

    基于模板通用文件對話框的可視化定制

    本文介紹了利用模板可視化定制通用文件對話框的實現方法。關鍵詞: 定制;通用文件對話框;模板;預覽在我們開發的CAD/CAM系統及其它應用軟件中,經常需要用戶進行一些
    發表于 08-21 10:08 ?14次下載

    駕馭Makefile

    駕馭Makefile在網上你能找到很多關于Makefile的學習資料,但絕大部分給你的只是一個知識點,與將Makefile運用到項目中(尤其是大型項目)的差距非常的大。因為,將Makefile
    發表于 01-05 17:05 ?9次下載

    linux makefile教程

     什么是makefile?或許很多Winodws的程序員都不知道這個東西,因為那些Windows的IDE都為你做了這個工作,但我覺得要作一個好的和professional的程序員,makefile
    發表于 11-12 09:11 ?5358次閱讀

    makefile的基本語法

     在Makefile中,最重要的三個概念是:目標(target)、依賴關系(dependency)和命令(command)。目標是指要干什么,即運行make后生成什么;依賴是指明目標所依賴的其他目標;命令則告訴make如何生成目標,這三個概念是通過Makefile中的規則
    發表于 11-12 10:15 ?1.1w次閱讀

    基于JasperReport通用的報表模板設計

    JasperReport是一個強大、靈活的開源報表生成工具,適用于各種Java應用程序,是當前Java開發者最常用的報表工具之一。利用JasperReport生成報表,首先需要設計報表模板,然后
    發表于 12-04 15:20 ?3次下載
    基于JasperReport<b class='flag-5'>通用</b>的報表<b class='flag-5'>模板</b>設計

    Makefile是什么?Makefile工作原理是怎樣的?Makefile經典教程免費下載

    Makefile的重要性 會不會寫makefile,從一個側面說明了一個人是否具備完成大型工程的能力 makefile帶來的好處就是——“自動化編譯”,一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟件
    發表于 09-12 17:19 ?0次下載
    <b class='flag-5'>Makefile</b>是什么?<b class='flag-5'>Makefile</b>工作原理是怎樣的?<b class='flag-5'>Makefile</b>經典教程免費下載

    Makefile的項目模板免費下載

    本文檔的主要內容詳細介紹的是Makefile的項目模板免費下載 可根據項目名稱修改。
    發表于 06-12 08:00 ?11次下載
    <b class='flag-5'>Makefile</b>的項目<b class='flag-5'>模板</b>免費下載

    一個STM32編譯Makefile模板

    一個STM32編譯Makefile模板
    發表于 11-13 20:06 ?10次下載
    一個STM32編譯<b class='flag-5'>Makefile</b><b class='flag-5'>模板</b>

    AVR-GCC Makefile 中文翻譯

    所有的想要的功能都可以實現。但是我是個愛鉆牛角尖人,呵呵。看了一下 WINAVR Makefile模板我覺得寫得很好,學習了一下,翻譯了一下,加上很多我的理解和注釋。把它共享給大家,共同進步。這個M...
    發表于 11-15 13:36 ?35次下載
    AVR-GCC <b class='flag-5'>Makefile</b> 中文翻譯

    Makefile】簡單實用的Makefile模板來了

    【Linux + Makefile】簡單實用的Makefile模板來了
    的頭像 發表于 08-31 12:46 ?1928次閱讀
    【<b class='flag-5'>Makefile</b>】簡單實用的<b class='flag-5'>Makefile</b><b class='flag-5'>模板</b>來了

    三個Makefile模板分享

    ????本文分享三個Makefile模板:編譯可執行程序、編譯靜態庫、編譯動態庫。 1 寫在前面 ????對于Windows下開發,很多IDE都集成了編譯器,如Visual Studio,提供了
    的頭像 發表于 07-10 09:07 ?1052次閱讀
    三個<b class='flag-5'>Makefile</b><b class='flag-5'>模板</b>分享
    主站蜘蛛池模板: 久久婷婷国产一区二区三区| 黄 色 片 在 线 看| 一区二区三区电影| 成人国产精品一级毛片了| 在线天堂bt种子资源| 亚洲开心激情网| 四虎影院黄色| 欧美一区二区三区在线观看| 成人国产一区二区| 大杳蕉伊人狼人久久一本线| 黄色网 在线播放| 国产精品午夜寂寞视频| 天天做夜夜爽| 99r8这里精品热视频免费看| 亚洲一级色片| 日本又粗又长一进一出抽搐| www夜夜操com| 中文字幕精品一区二区三区视频 | 国产毛片久久久久久国产毛片| 日本黄色大片在线播放视频免费观看| 欧美性狂猛xxxxxbbbbb| 国模视频在线| 天天天天天天干| 6080国产午夜精品| 久久久xxx| 日日噜噜噜夜夜爽爽狠狠视频| 六月婷婷久久| 夜夜福利| www.福利| 国产成人精品三级在线| 色香色香欲天天天影视综合网| 毛片a区| 黄色视屏免费看| 久久的色偷偷| 亚洲aa视频| www日| 一级做a爰片久久毛片图片| 欧美色视频网站| 夜夜操天天操| 欧美性猛交xxxx免费| 伊人草|