Linux編程基礎——Makefile

來源:互聯網
上載者:User

前面我們已經介紹過了如何通過gcc編譯代碼組建檔案,但是,當項目較多的時候,往往則需要一個自動化的編譯工具輔助我們完成這項操作。像Windows那樣通過Ctrl+F5即可一鍵完成項目所有編譯工作。

Makefile文法基礎

在Linux下,自動化編譯工具是通過make命令來完成的(一些工具廠商也提供了它們自己的make命令,如gmake等),make命令的基本格式如下:

    make [-f makefile] [label]

它可以通過-f參數指定輸入檔案,當省略-f參數時,預設輸入檔案名稱為Makefile,由於我們通常不用這個-f參數,往往就用預設的Makefile檔案名稱。

Makefile是一個文字檔,它是基於一定的文法規則的,它的基本執行規則定義如下:

    target : [prerequisites]
        command

  • target    標籤,用於標誌當前構建的規則,它也可以是檔案。
  • prerequisites    依賴項,在構建該標籤的時候先執行的規則
  • command make需要執行的命令。(任意的Shell命令)

注意:Makefile的target是頂格寫的,而Command需要加一個Tab鍵。我這裡為了排版看起來舒服點,每一行都多加了一個Tab鍵,如果要使用本文的Makefile樣本,請去掉各行的第一個Tab鍵,否則make的時候報錯。

例如,我們編寫一個簡單的Makefile:

    clean:
        @echo "clean"
    all:
        @echo "all"

當我們直接執行make命令的時候,輸出如下:

    tianfang > make
    clean
    tianfang > make all
    all
    tianfang > make clean
    clean

從中我們可以看到:預設情況下構建第一個標籤。可以通過在命令列參數中通過參數構建指定標籤。

然後我們再來看看依賴性是如何工作的,這次我們修改一下Makefile,讓all標籤依賴於clean標籤:

    clean :
        @echo "clean"
    all : clean
        @echo "all"

再次執行make all的時候,發現會先執行clean標籤:

tianfang > make all
clean
all

用Makefile來構建項目

通過對Makefile的文法有一個簡單的瞭解後,下面就可以用Makefile簡化我們的構建操作了。還是針對前面的那個stack的例子吧,首先我們來實現一個最簡單的例子:

all :
gcc -o run main.c stack.c

這樣直接通過make命令就可以實現對gcc -o run main.c stack.c整條命令的執行了。

更加一步,我們想實現增量編譯,則要實現如下規則:

  1. 如果這個工程沒有編譯過,那麼我們的所有C檔案都要編譯並被連結。
  2. 如果這個工程的某幾個C檔案被修改,那麼我們只編譯被修改的C檔案,並連結目標程式。

這個時候就需要前面的依賴性出馬了:

    run : stack.o main.o
        gcc -o run main.o stack.o

    stack.o : stack.c
        gcc -c stack.c

    main.o : main.c
        gcc -c main.c

這裡的target都是檔案,run預設依賴於stack.o和main.o,因此,當構建run的時候,就會先構建stack.o和main.o,輸出方式如下:

    tianfang > make
    gcc -c stack.c
    gcc -c main.c
    gcc -o run main.o stack.o

當我們只改了其中某個檔案的時候,例如stack.c,這是由於main.c沒有變化,因此不會重新編譯main.o,只會重新構建stack.o和run,從而實現我們的增量編譯的目的。(這個其實才是make比shell或指令碼語言編寫的批處理方式要強大的地方)

    tianfang > make
    gcc -c stack.c
    gcc -o run main.o stack.o

通過自動推導改進Makefile

通過上面的例子可以看到,雖然我們可以實現增量編譯,但是整個Makefile過程是非常複雜的,需要對每個.o檔案編寫編譯指令碼。如果專案檔較多,並且有增刪的話,則編寫Makefile檔案非常麻煩。

為了改進這個問題,makefile提供了一個自動推導的功能,通過它可以簡化我們的編寫過程。例如,前面的例子可以簡化如下:

    CC = gcc
    objs = stack.o main.o

    run : $(objs)
        $(CC) -o run $(objs)

這裡我們引入了兩個變數,第一個行的CC制定了編譯器為gcc(如果不指定則是預設的cc),第二行制定了我們的obj檔案。

這樣,只需要執行make命令即可生產我們的程式:

    tianfang > make
    gcc -c -o stack.o stack.c
    gcc -c -o main.o main.c
    gcc -o run stack.o main.o

可可以看到,make命令會自動推匯出如何根編出.o檔案來。如果我們的專案檔變化了,只需要改objs變數即可,非常方便。

不過,有的時候我們可能覺得這中自動推導的方式不夠用,需要手動控制編譯選項,這個時候我們可以自己指定推導規則:

    CC = gcc
    objs = stack.o main.o

    run : $(objs)
        $(CC) -o run $(objs)

    $(objs): %.o: %.c
        $(CC) -c -g $< -o $@

Makefile的功能非常強大,對應的文法也是非常複雜的,由於網上已經有人寫得很詳細了,因此我這裡並不打算系統的介紹Makefile的各種規則,如果想進一步的瞭解,可以參考跟我一起寫 Makefile這篇文章。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.