LINUX下的make和makefile

轉載自:https://blog.csdn.net/wangqingchuan92/article/details/92832544

文章中的文字可能存在語法錯誤以及標點錯誤,請諒解;

如果在文章中發現代碼錯誤或其它問題請告知,感謝!

0x01make工具簡介

make工具是一個根據makefile文件內容,針對目標(可執行文件)進行依賴性檢測(要生成該可執行文件之前要有哪些中間文件)並執行相關動作(編譯等)的工具 。而這個makefile文件類似一個腳本,其中內容包含make所要進行的處理動作以及依賴關係。

另外make的一個好處就是當你對某個源文件進行了修改,你再次執行 make 命令,它將只編譯與該源文件相關的目標文件而不是整個代碼工程,因此,爲編譯完最終的目標(可執行文件)節省了大量的時間提高工作連貫性。比如一個工程下面有A.c 、B.c、 B.c三個文件,在make生成可執行目標文件之後,改動了A.c,則再次make時,只會執行有關A.c處理動作,其它的不處理。

學習make工具,需要明白三個概念:目標、依賴、處理動作。
makefile所要進行的主要內容是明確目標、明確目標所依賴的內容、明確依賴條件滿足時應該執行對應的處理動作。例如我們最終要實現a這個目標,但是需要依賴b,而b依賴於c的存在,則可以描述爲:

a:b
	cmdbtoa
b:c
	cmdctob
  • 1
  • 2
  • 3
  • 4

“:”代表依賴,另外每個處理動作之前都要用tab鍵分隔
上述四行的意思是:a依賴於b,而處理cmdbtoa;b依賴於c,而處理cmdctob。

0x02實例

首先準備三個文件,test1.c、test2.c、test2.h。

test1.c:

#include<stdio.h>
#include "test2.h"

int main()
{
printf(“This is test1!\n”);
PrintTest2();
return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

test2.c

    #include<stdio.h>
    #include "test2.h"
void PrintTest2t() 
{
    printf("This is test2!\n");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

test2.h

 #ifndef TEST2_H_
 #define TEST2_H_

void PrintTest2();

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用ls指令查看目錄內容:
在這裏插入圖片描述
有了上述三個代碼文件後,下面介紹使用三種makefie文件編寫方式
1.基礎版
新建一個文件,命名爲makefile,文件內容如下(注意要用tab來分隔處理動作指令):

test: test1.o test2.o 
	gcc -Wall test1.o test2.o -o test

test1.o: test1.c test2.h
gcc -c -Wall test1.c -o test1.o

test2.o: test2.c test2.h
gcc -c -Wall test2.c -o test2.o

clean:
rm -rf *.o test

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在這裏插入圖片描述
然後在終端內輸入make指令編譯工程:
在這裏插入圖片描述

再次使用ls查看目錄多了.o和可執行文件:
在這裏插入圖片描述
對makefile裏的指令進行解釋:
test: test1.o test2.o :test依賴於test1.o、test2.o兩個目標文件

gcc -Wall test1.o test2.o -o test:編譯出可執行文件test。-o表示指定的可執行文件名稱

test1.o: test1.c test2.h:test1.o依賴於test1.c、test2.h兩個文件

gcc -c -Wall test1.c -o test1.o:編譯出test1.o文件,-c表示只把給它的文件編譯成目標文件,用源碼文件的文件名命名,但把其後綴由“.c”變成“.o”。

make clean:刪除掉所有.o以及可執行文件,當修改了某一個源文件使用該指令清除舊的文件。在終端輸入“make clean”實現:
在這裏插入圖片描述

此時修改了test2.c中內容,在printf()下一行增加一個無意義的回車,然後使用make編譯會發現只有跟test2.c有關的部分進行了處理,這種自動化的進行依賴性檢測和選擇性執行必要的處理動作的工作,體現了make的特色:
在這裏插入圖片描述
2.使用變量版
makefile內容如下:

OBJS = test1.o test2.o
G = gcc
CFLAGS = -Wall -O -g

test:$(OBJS)
$(G) $(OBJS) -o test

test1.o:test1.c test2.h
$(G) $(CFLAGS) -c test1.c
test2.o:test2.c test2.h
$(G) $(CFLAGS) -c test2.c

clean:
rm -rf *.o test

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在這個makefile中使用了變量,變量的格式是“varName = content”;若要引用這個變量,只需要用$ 即可,$(varName)

CFLAGS = -Wall -O -g 配置編譯器設置,並把它賦值給CFLAGS變量

-Wall:輸出所有警告信息

-O:在編譯時進行優化

-g:表示編譯debug版本

使用make後生成文件同上:
在這裏插入圖片描述
這樣寫的Makefile比較簡單,但是缺點顯著,每添加一個.c文件,就需要修改Makefile文件。

3使用函數
makefile內容如下

C = gcc
G = g++
CFLAGS = -Wall -O -g
TARGET = ./test

%.o:%.c
$© $(CFLAGS) -c $< -o $@

%.o:%.cpp
$(G) $(CFLAGS) -c $< -o $@

SOURCES = $(wildcard *.c *.cpp)

OBJS = (patsubst(patsubst %.c,%.o,(patsubst %.cpp,%.o,$(SOURCES)))

(TARGET):(TARGET):(OBJS)
$(G) $(OBJS) -o $(TARGET)
chmod a+x $(TARGET)

clean:
rm -rf *.o test

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

%.o:%.c
$© $(CFLAGS) -c $< -o $@

%.o:%.cpp
$(G) $(CFLAGS) -c $< -o $@

表示把所有的.c、.cpp文件編譯成.o文件。

SOURCES = $(wildcard *.c *.cpp) 表示產生一個所有以.c、.cpp結尾的文件列表,然後存入變量SOURCES裏。

OBJS = $ (patsubst %.c,%.o,$ (patsubst %.cpp,%.o,$(SOURCES)))
把SOURCES文件列表中所有.cpp變成.o、.c變成.o,然後形成一個新的列表,存入OBJS變量。

$ @擴展成當前規則的目的文件名,$ <擴展成依靠列表中的第一個依靠文件,$^擴展成整個依靠的列表(除掉裏面所有重複的文件名)。

chmod a+x $(TARGET) 表示把firstTest強制變成可執行文件。

使用make後生成文件同上:
在這裏插入圖片描述

以上。
參考文檔:
1.https://blog.csdn.net/liangkaiming/article/details/6267357
2.https://blog.csdn.net/limanjihe/article/details/52231243
3.https://blog.csdn.net/jhgkjhg_ugtdk77/article/details/52023618
4.https://www.cnblogs.com/hazir/p/linux_make_examples.html
5.https://goodcandle.cnblogs.com/archive/2006/03/30/278702.html

                                </div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章