前文我們講了如何使用 GCC 編譯器在 linux 進(jìn)行 C 語(yǔ)言編譯,通過在終端執(zhí)行 gcc 命令來(lái)完成C 文件的編譯,如果我們的工程只有一兩個(gè) C 文件還好,需要輸入的命令不多,當(dāng)文件有幾十、上百甚至上萬(wàn)個(gè)的時(shí)候用終端輸入 GCC命令的方法顯然是不現(xiàn)實(shí)的。如果我們能夠編寫一個(gè)文件,這個(gè)文件描述了編譯哪些源碼文件、如何編譯那就好了,每次需要編譯工程的時(shí)只需要使用這個(gè)文件就行了。這種問題怎么可能難倒聰明的程序員,為此提出了一個(gè)解決大工程編譯的工具:Make,描述哪些文件需要編譯、哪些需要重新編譯的文件就叫做 Makefile,Makefile 就跟腳本文件一樣,Makefile 里面還可以執(zhí)行系統(tǒng)命令。使用的時(shí)候只需要一個(gè) Make命令即可完成整個(gè)工程的自動(dòng)編譯,極大的提高了軟件開發(fā)的效率。如果大家以前一直使用 IDE來(lái)編寫 C 語(yǔ)言的話肯定沒有聽說(shuō)過 Makefile 這個(gè)東西,其實(shí)這些 IDE 是有的,只不過這些 IDE對(duì)其進(jìn)行了封裝,提供給大家的是已經(jīng)經(jīng)過封裝后的圖形界面了,我們?cè)?IDE 中添加要編譯的C 文件,然后點(diǎn)擊按鈕就完成了編譯。在 Linux 下用的最多的是 GCC 編譯器,這是個(gè)沒有 UI的編譯器,因此 Makefile 就需要我們自己來(lái)編寫了。作為一個(gè)專業(yè)的程序員,是一定要懂得Makefile 的,一是因?yàn)樵?Linux 下你不得不懂 Makefile,再就是通過 Makefile 你就能了解整個(gè)工程的處理過程。
我們完成這樣一個(gè)小工程,通過鍵盤輸入兩個(gè)整形數(shù)字,然后計(jì)算他們的和并將結(jié)果顯示在屏幕上,在這個(gè)工程中我們有 main.c、input.c 和 calcu.c 這三個(gè) C 文件和 input.h、calcu.h 這兩個(gè)頭文件。其中main.c 是主體,input.c 負(fù)責(zé)接收從鍵盤輸入的數(shù)值,calcu.h 進(jìn)行任意兩個(gè)數(shù)相加,其中main.c 文件內(nèi)容如下:
#include <stdio.h>
#include "input.h"
#include "calcu.h" 4
int main(int argc, char *argv[])
{
int a, b, num;
input_int(&a, &b);
num = calcu(a, b);
printf("%d + %d = %drn", a, b, num) ;
}
input.c 文件內(nèi)容如下
#include <stdio.h>
#include "input.h"
void input_int(int *a, int *b)
{
printf("input two num:");
scanf("%d %d", a, b);
printf("rn");
}
calcu.c 文件內(nèi)容如下:
#ifndef _INPUT_H #define _INPUT_H void input_int(int *a, int *b); #endif
文件 calcu.h 內(nèi)容如下:
#ifndef _CALCU_H #define _CALCU_H int calcu(int a, int b); #endif
以上就是我們這個(gè)小工程的所有源文件,我們接下來(lái)使用前面講的方法來(lái)對(duì)其進(jìn)行編譯,在終端輸入如下命令:
gcc main.c calcu.c input.c -o main
上面命令的意思就是使用gcc 編譯器對(duì) main.c、calcu.c 和 input.c 這三個(gè)文件進(jìn)行編譯,編譯生成的可執(zhí)行文件叫做 main。編譯完成以后執(zhí)行 main 這個(gè)程序,測(cè)試一下軟件是否工作正常,結(jié)果如圖所示:
程序測(cè)試
可以看出我們的代碼按照我們所設(shè)想的工作了,使用命令“gcc main.c calcu.c input.c -o main”看起來(lái)很簡(jiǎn)單是吧,只需要一行就可以完成編譯,但是我們這個(gè)工程只有三個(gè)文件啊!如果幾千個(gè)文件呢?再就是如果有一個(gè)文件被修改了以,使用上面的命令編譯的時(shí)候所有的文件都會(huì)重新編譯,如果工程有幾萬(wàn)個(gè)文件(Linux 源碼就有這么多文件!),想想這幾萬(wàn)個(gè)文件編譯一次所需要的時(shí)間就可怕。最好的辦法肯定是哪個(gè)文件被修改了,只編譯這個(gè)被修改的文件即可,其它沒有修改的文件就不需要再次重新編譯了,為此我們改變我們的編譯方法,如果第一次編譯工程,我們先將工程中的文件都編譯一遍,然后后面修改了哪個(gè)文件就編譯哪個(gè)文件,命令如下:
gcc -c main.c gcc -c input.c gcc -c calcu.c gcc main.o input.o calcu.o -o main
上述命令前三行分別是將 main.c、input.c 和 calcu.c 編譯成對(duì)應(yīng)的.o 文件,所以使用了“-c”選項(xiàng),“-c”選項(xiàng)我們上面說(shuō)了,是只編譯不鏈接。最后一行命令是將編譯出來(lái)的所有.o 文件鏈接成可執(zhí)行文件main。假如我們現(xiàn)在修改了 calcu.c 這個(gè)文件,只需要將 caclue.c 這一個(gè)文件重新編譯成.o 文件,然后在將所有的.o 文件鏈接成可執(zhí)行文件即,只需要下面兩條命令即可:
gcc -c calcu.c gcc main.o input.o calcu.o -o main
但是這樣就又有一個(gè)問題,如果修改的文件一多,我自己可能都不記得哪個(gè)文件修改過了,然后忘記編譯,然后……,為此我們需要這樣一個(gè)工具:
1、如果工程沒有編譯過,那么工程中的所有.c 文件都要被編譯并且鏈接成可執(zhí)行程序。
2、如果工程中只有個(gè)別C 文件被修改了,那么只編譯這些被修改的C 文件即可。
3、如果工程的頭文件被修改了,那么我們需要編譯所有引用這個(gè)頭文件的 C 文件,并且鏈接成可執(zhí)行文件。
很明顯,能夠完成這個(gè)功能的就是 Makefile 了,在工程目錄下創(chuàng)建名為“Makefile”的文件,文件名一定要叫做“Makefile”!!!區(qū)分大小寫的哦!如圖所示:
Makefile 文件
上述代碼中所有行首需要空出來(lái)的地方一定要使用“TAB”鍵!不要使用空格鍵!這是Makefile 的語(yǔ)法要求,編寫好得 Makefile 如圖所示:
Makefile源文件
Makefile 編寫好以后我們就可以使用 Make 命令來(lái)編譯我們的工程了,直接在命令行中輸入“Make”即可,Make 命令會(huì)在當(dāng)前目錄下查找是否存在“Makefile”這個(gè)文件,如果存在的話就會(huì)按照 Makefile 里面定義的編譯方式進(jìn)行編譯,如圖所示:
make命令編譯工程
在圖中,使用命令“Make”編譯完成以后就會(huì)在當(dāng)前工程目錄下生成各種.o 和可執(zhí)行文件,說(shuō)明我們編譯成功了。使用 Make 命令編譯工程的時(shí)候可能會(huì)提示如圖所示錯(cuò)誤:
make命令編譯失敗
圖中的錯(cuò)誤來(lái)源一般有兩點(diǎn):
1、Makefile 中命令縮進(jìn)沒有使用 TAB 鍵!
2、VI/VIM 編輯器使用空格代替了TAB 鍵,修改文件/etc/vim/vimrc,在文件最后面加上如下所示代碼:
set noexpandtab
我們修改一下 input.c 文件源碼,隨便加幾行空行就行了,保證 input.c 被修改過即可,修改完成以后再執(zhí)行一下“Make”命令重新編譯一下工程,結(jié)果如圖所示:
重新編譯工程
從圖中可以看出因?yàn)槲覀冃薷牧?input.c 這個(gè)文件,所以 input.c 和最后的可執(zhí)行文件 main 重新編譯了,其它沒有修改過的文件就沒有編譯。而且我們只需要輸入“make”這個(gè)命令即可,非常方便。






