|
makefile的功能太過(guò)強(qiáng)大,完全個(gè)人總結(jié),知 識(shí)有限,歡迎糾正錯(cuò)誤!
main.c
#include "main.h"
int main()
{
printf_hello();
printf_ok();
return ;
}
main.h
#ifndef _MAIN_H
#define _MAIN_H
#include "hello.h"
#include "ok.h"
#endif
printf_hello.c
#include "hello.h"
void printf_hello(void)
{
printf("hello!\n");
printf_thanks();
}
void printf_thanks(void)
{
printf("thanks!!!\n");
}
hello.h
#ifndef _HELLO_H
#define _HELLO_H
#include <stdio.h>
void printf_thanks(void);
void printf_hello(void);
#endif
printf_ok.c
#include "ok.h"
void printf_ok(void)
{
printf("ok!!!\n");
printf_thanks();
}
ok.h
#ifndef _OK_H_
#define _OK_H_
#include <stdio.h>
void printf_ok(void);
extern void printf_thanks(void);
#endif
在編譯六個(gè)文件組成的項(xiàng)目時(shí),可以不用寫(xiě)makefile文件因?yàn)槲募臄?shù)量比較的少所以
可以直接在linux系統(tǒng)下直接使用 gcc main.c printf_hello.c printf_ok.c -o main
編譯成執(zhí)行文件 main ,可以直接./main執(zhí)行此文件即可。(上面的所有的文件必須
在一個(gè)文件夾中,才可以編譯,否則 將會(huì)報(bào)錯(cuò)說(shuō)找不到目標(biāo)文件)。
當(dāng)項(xiàng)目比較大的時(shí)候,文件可能幾千甚至更多的時(shí)候,我們可以先創(chuàng)建一個(gè)工程文件名
為project的文件夾,之后在其中在創(chuàng)建兩個(gè)文件夾,一個(gè)取名為inc ,另一個(gè)取名為
src 。在inc中我們通常是放.h文件,而在src中我們通常放的是.c文件和makefile文件。
一般的makefile文件如下:
main:main.o printf_hello.o printf_ok.o
gcc main.o printf_hello.o printf_ok.o -o main
main.o:main.c
gcc -c -I ../inc/ main.c -o main.o
printf_hello.o:printf_hello.c
gcc -c -I ../inc/ printf_hello.c -o printf_hello.o
printf_ok.o:printf_ok.c
gcc -c -I ../inc/ printf_ok.c -o printf_ok.o
clean:
-rm -f *.o main //移除后綴為.o和目標(biāo)文件
每一個(gè)gcc命令的最后加上 -g 就可以使用 gdb 編譯。!
makefile 通常有三種寫(xiě)法 Makefile , makefile , GNU makefile
第一種使用較多,因?yàn)榇髮?xiě)的M的 ASCII 較小系統(tǒng)擺放文件時(shí)將其放在了前面。
調(diào)用make命令可輸入
target是Makefile文件中定義的目標(biāo)之一,如果省略target,make就將生成
Makefile文件中定義的第一個(gè)目標(biāo)。
例如:在上面的例子中我們可以輸入 make main.o 或 make printf_hello.o
等等 ,但是如果你輸入的是make main.o 那么他只會(huì)執(zhí)行g(shù)cc -c -I ../inc/ main.c
-o main.o 這一個(gè)命令!而單獨(dú)的一個(gè)“make”命令等價(jià)于make main命令,
由于依賴的關(guān)系所以下面的命令都執(zhí)行除了clean命令外(clean命令和他們沒(méi)有
依賴的關(guān)系)。
因?yàn)閙ain是Makefile文件中定義的第一個(gè)目標(biāo),make首先將其讀入,然后從第一行
開(kāi)始執(zhí)行,把第一個(gè)目標(biāo)main作為它的最終目標(biāo),所有后面的目標(biāo)的更新都會(huì)影響到
main的更新。
如果直接在linux系統(tǒng)下敲擊make命令,則系統(tǒng)執(zhí)行的命令是makefile,而
不是執(zhí)行的是Makefile文件的命令。如果文件夾中既有makefile 也有Makefile文
件,我們需要使用make的命令,make -f Makefile 就可以執(zhí)行Makefile的文
件的命令。而以上的makefile文件可以通過(guò)更改頭文件的路徑而更改,.h文件不必
改變。
make的執(zhí)行過(guò)程:
1.如果目標(biāo)文件的時(shí)問(wèn)戳比依賴文件還早,就按規(guī)則中定義的命令更新目標(biāo)文件。
2.如果該規(guī)則中的依賴文件又是其他規(guī)則中的目標(biāo)文件,那么依照規(guī)則鏈不斷執(zhí)行這
個(gè)過(guò)程,直到Makefile文件的結(jié)束,至少可以找到一個(gè)不是規(guī)則生成的最終依賴文
件,獲得此文件的時(shí)間戳
3.然后從下到上依照規(guī)則鏈執(zhí)行目標(biāo)文件的時(shí)間戳比此文件時(shí)間戳舊的規(guī)則,直到最
頂層的規(guī)則
#include "../inc/ok.h" //將相對(duì)路徑添加到頭文件中
void printf_ok(void)
{
printf("ok!!!\n");
printf_thanks();
}
#include "../inc/hello.h" //將相對(duì)路徑添加到頭文件中
void printf_hello(void)
{
printf("hello!\n");
printf_thanks();
}
void printf_thanks(void)
{
printf("thanks!!!\n");
}
#include "../inc/main.h" //將相對(duì)路徑添加到頭文件中
int main()
{
printf_hello();
printf_ok();
return ;
}
修改后的makefile文件:
main:main.o printf_hello.o printf_ok.o
gcc main.o printf_hello.o printf_ok.o -o main
main.o:main.c
gcc -c main.c -o main.o
printf_hello.o:printf_hello.c
gcc -c printf_hello.c -o printf_hello.o
printf_ok.o:printf_ok.c
gcc -c printf_ok.c -o printf_ok.o
clean:
-rm -f *.o main
Makefile的變量
(1)變量名不包括: “ :” 、“ # ” 、“ = ”
(2)變量名是大小寫(xiě)敏感的,“ foo ”與“ Foo ”代表不同的變量
(3)預(yù)留大寫(xiě)字母作為作為控制隱含規(guī)則參數(shù)或者用戶重載命令選項(xiàng)
Makefile中的變量分為:
用戶自定義變量
預(yù)定義變量、
自動(dòng)變量
1.用戶自定義的變量
例如將上面的makefile改變:
A=main.o printf_hello.o printf_ok.o
B=gcc
main:$(A)
$(B) $(A) -o main
main.o:main.c
$(B) -c main.c -o main.o
printf_hello.o:printf_hello.c
$(B) -c printf_hello.c -o printf_hello.o
printf_ok.o:printf_ok.c
$(B) -c printf_ok.c -o printf_ok.o
clean:
-rm -f *.o main
2.預(yù)定義變量
A=main.o printf_hello.o printf_ok.o
B=gcc
$@ 目標(biāo)文件的完整名稱
$< 第一個(gè)依賴的文件名稱
main:$(A)
$(B) $(A) -o $@
main.o:main.c
$(B) -c $< -o $@
printf_hello.o:printf_hello.c
$(B) -c $< -o $@
printf_ok.o:printf_ok.c
$(B) -c $< -o $@
clean:
-rm -f *.o main
也可以寫(xiě)成:
main:$(A)
$(B) -o $@ $(A)
main.o:main.c
$(B) -c -o $@ $<
printf_hello.o:printf_hello.c
$(B) -c -o $@ $<
printf_ok.o:printf_ok.c
$(B) -c -o $@ $<
clean:
-rm -f *.o main
3. 自動(dòng)變量
實(shí)際上,make可以使工作更加自動(dòng)化,也就是說(shuō),make知道一些默認(rèn)
的動(dòng)作,它有一些稱作隱含規(guī)則的內(nèi)置的規(guī)則。
如上例完全可以寫(xiě)成:
A=main.o printf_hello.o printf_ok.o
B=gcc
$@ 目標(biāo)文件的完整名稱
$< 第一個(gè)依賴的文件名稱
main:$(A)
$(B) $(A) -o $@
clean:
-rm -f *.o main
可以省略最后兩條,因?yàn)镸akefile的隱式規(guī)則指出都可由“ .c ”文件使用
以下命令生成:
$(B) $(CFLAGS) $(CPPFLAGS) -c –o file.o file.c
CFLAGS CPPFLAGS 是系統(tǒng)的默認(rèn)的變量為空 ,我們可以給他賦值,也
可以不理會(huì)。!
makefile還有一種模式規(guī)則可以將makefile變更為:
A=main.o printf_hello.o printf_ok.o
B=gcc
main:$(A)
$(B) -o $@ $(A)
%.o:%.c //代表了一系列這樣的文件
$(B) -c -o $@ $<
clean:
-rm -f *.o main
1.模式規(guī)則是用來(lái)定義相同處理規(guī)則的多個(gè)文件的,模式規(guī)則可以引入用戶自定義
變量,為多個(gè)文件建立相同的規(guī)則,從而簡(jiǎn)化Makefile的編寫(xiě)。
2.模式規(guī)則中相關(guān)文件前必須用“ % ”
|
|