1. 程式人生 > >Linux程式設計——Makefile 使用

Linux程式設計——Makefile 使用

    在先前的文章中,我們已經學習了 gcc 和 gdb 的使用。本節,我們將介紹 Makefile 的使用。Makefile帶來的好處就是——“自動化編譯”,一但寫好,只需要一個 make 命令,整個工程便可以完全編譯,極大的提高了軟體的開發效率(特別是對於那些專案較大、檔案較多的工程)。

    make是一個命令工具,最主要也是最基本的功能就是根據makefile檔案中描述的源程式至今的相互關係來完成自動編譯、維護多個原始檔工程。

    而makefile檔案需要按某種語法進行編寫,檔案中需要說明如何編譯各個原始檔並連結生成可執行檔案,要求定義原始檔之間的依賴關係。

    下面從一個簡單例項入手,介紹如何編寫Makefile。假設現在有一個簡單的專案由幾個檔案組成:prog.c、 code.c、 code.h。這些檔案的內容如下:

    prog.c

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

int main(void)
{
    int i = 1;      
    printf ("myfun(i) = %d\n", myfun(i));
}

    code.c

#include "code.h"

int myfun(int in)
{
    return in + 1;
}

    code.h

extern int myfun(int);

    這些程式都比較短,結構也很清晰,因此使用下面的命令進行編譯:

$ gcc -c code.c -o code.o
$ gcc -c prog.c -o prog.o
$ gcc prog.o code.o -o test
    如上所示,這樣就能生成可執行檔案test,由於程式比較簡單,而且數量也比較少,因此看不出來有多麻煩。但是,試想如果不只上面的3個檔案,而是幾十個或者是成百上千個甚至更多,那將是非常複雜的問題。


    那麼如何是好呢?這裡就是makefile的絕佳舞臺,下面是一個簡單的makefile的例子。

    首先  $ vim Makefile 

test: prog.o code.o
        gcc prog.o code.o -o test
prog.o: prog.c code.h
        gcc -c prog.c -o prog.o
code.o: code.c code.h
        gcc -c code.c -o code.o
clean:
        rm -f *.o test

  有了這個Makefile,不論什麼時候修改原始檔,只要執行一下make命令,所有必要的重新編譯將自動執行。make程式利用Makefile中的資料,生成並遍歷以test為根節點的樹;現在我們以上面的例項,來學習一下Makefile的一般寫法: 

test(目標檔案): prog.o code.o(依賴檔案列表)
tab(至少一個tab的位置) gcc prog.o code.o -o test(命令)
.......

  一個Makefile檔案主要含有一系列的規則,每條規則包含以下內容:一個目標,即make最終需要建立的檔案,如可執行檔案和目標檔案;目標也可以是要執行的動作,如‘clean’;一個或多個依賴檔案的列表,通常是編譯目標檔案所需要的其他檔案。之後的一系列命令,是make執行的動作,通常是把指定的相關檔案編譯成目標檔案的編譯命令,每個命令佔一行,並以tab開頭(務必注意:是tab,而不是空格) 執行以上Makefile後就會自動化編譯:

$ make
gcc -c prog.c -o prog.o
gcc -c code.c -o code.o
gcc prog.o code.o -o test

  最後就會多產生: porg.o code.o test這三個檔案,執行./test檢視結果

  還記得Makefile中的clean嗎? make clean就會去執行rm -f *.o test這條命令,完成 clean 操作。

  

  Makefile還可以定義和使用巨集(也稱做變數),從而使其更加自動化,更加靈活,在Makefile中定義巨集的格式為: 

macroname = macrotext

  使用巨集的格式為:

$(macroname)

  我們用 “巨集” 的方式,來改寫上面的 Makefile 例子。

OBJS = prog.o code.o
CC = gcc
test: $(BOJS)
        $(CC) $(OBJS) -o test
prog.o: prog.c code.h
        $(CC) -c prog.c -o prog.o
code.o: code.c code.h
        $(CC) -c code.c -o code.o
clean:
        rm -f *.o test