中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C編譯: makefile基礎

發布時間:2020-08-10 15:11:36 來源:ITPUB博客 閱讀:153 作者:ii_chengzi 欄目:編程語言

教大家一個 makefile基礎教學

在編譯一個大型項目的時候,往往有很多目標文件、庫文件、頭文件以及最終的可執行文件。不同的文件之間存在依賴關系(dependency)。比如當我們使用下面命令編譯時:

$gcc -c -o test.o test.c

$gcc -o helloworld test.o

可執行文件helloworld依賴于test.o進行編譯的,而test.o依賴于test.c。

 依賴關系

在我們編譯一個大型項目時,我們往往要很多次的調用編譯器,來根據依賴關系,逐步編譯整個項目。這樣的方式是自下而上的,即先編譯下游文件,再編譯上游文件。

 

UNIX系統下的make工具用于自動記錄和處理文件之間的依賴關系。我們不用輸入大量的"gcc"命令,而只需調用make就可以完成整個編譯過程。所有的依賴關系都記錄在makefile文本文件中。我們只需要make helloworld,make會根據依賴關系,自上而下的找到編譯該文件所需的所有依賴關系,最后再自下而上的編譯。

(make有多個版本,本文將基于GNU make。make會自動搜索當前目錄下的makefile, Makefile或者GNUmakefile)

 

依賴

 
基本概念

我們使用一個示例C語言文件:
復制代碼

#include <stdio.h>

/*
 * By Vamei
 * test.c for makefile demo
 */
int main()
{
    printf("Hello world!\n");
    return 0;
}

復制代碼

 

下面是一個簡單的makefile
復制代碼

# helloworld is a binary file
helloworld: test.o
  echo "good"
  gcc -o helloworld test.o

test.o: test.c
  gcc -c -o test.o test.c

復制代碼

 

觀察上面的makefile

    #號起始的行是注釋行
    target: prerequisite為依賴關系,即目標文件(target)依賴于前提文件(prerequisite)。可以有多個前提文件,用空格分開。
    依賴關系后面的<Tab>縮進行是實現依賴關系進行的操作,即正常的UNIX命令。一個依賴關系可以附屬有多個操作。

用直白的話說,就是:

    想要helloworld嗎?那你必須有test.o,并執行附屬的操作。
    如果沒有test.o,那你必須搜索其他依賴關系,并創建test.o。

 

我們執行

$make helloworld

來創建helloworld。

 

make是一個遞歸創建的過程:

    Base Case 1: 如果當前依賴關系中沒有說明前提文件,那么直接執行操作。
    Base Case 2: 如果當前依賴關系說明了目標文件,而目標文件所需的前提文件已經存在,而且前提文件與上次make時沒有發生改變(根據最近寫入時間判斷),也直接執行該依賴關系的操作。
    如果當前目標文件依賴關系所需的前提文件不存在,或者前提文件發生改變,那么以前提文件為新的目標文件,尋找依賴關系,創建目標文件。

虛線: 依賴關系檢索

 

上面是make的核心功能。有了上面的功能,我們可以記錄項目中所有的依賴關系和相關操作,并使用make進行編譯。下面的內容都是在此核心內容上的拓展。

 


make中可以使用宏(MACRO)。宏類似于文本類型的變量。比如下面的CC:
復制代碼

CC = gcc

# helloworld is a binary file
helloworld: test.o
  echo "good"
  $(CC) -o helloworld test.o

test.o: test.c
  $(CC) -c -o test.o test.c

復制代碼

 

我們用CC來代表"gcc"。在makefile中,使用$(CC)的方式來調用宏的值。make會在運行時,使用宏的值(gcc)來替代$(CC)。

shell的環境變量可以直接作為宏調用。如果同一個自定義的宏同時也有同名環境環境變量,make將優先使用自定義宏。

(可以使用$make -e helloworld來優先使用環境變量)

 

類似于C語言的宏,makefile中的宏可以方便的管理一些固定出現的文本,并方便替換操作。比如我們未來使用ifort編譯器時,只需要更改宏定義為:

CC = ifort

就可以了

 
內部宏

make中有內部定義的宏,可以直接使用。$@中包含有當前依賴關系的目標文件名,而$^包含當前目標的前提文件:
復制代碼

CC = gcc

# helloworld is a binary file
helloworld: test.o
  echo $@
  $(CC) -o $@ $^

test.o: test.c
  $(CC) -c -o $@ $^

復制代碼

 

內部宏       功能

$*          當前依賴關系中的目標文件名,不包括后綴。

$*          當前依賴關系中,發生改變的前提文件

$$          字符"$"

 

如果目標或者前提文件是一個完整路徑,我們可以附加D和F來提取文件夾部分和文件名部分,比如$(@F)表示目標文件的文件名部分。

 
后綴依賴

在makefile中使用

.SUFFIXES: .c .o

來說明.c和.o是后綴。

 

我們可以使用后綴依賴的方式,比如:
復制代碼

CC = gcc

.SUFFIXES: .c .o

.c.o:
        $(CC) -c -o $@ $^

#--------------------------

# helloworld is a binary file
helloworld: test.o
        echo $@
        $(CC) -o $@ $^

test.o: test.c

復制代碼

我們定義.c和.o為后綴。并有后綴依賴關系.c.o:。前者為前提,后者為目標。(注意,與一般的依賴關系順序不同)

上面的test.o和test.c有依賴關系,但沒有操作。make會發現該依賴關系符合.c.o的后綴依賴,并執行該后綴依賴后面的操作。

 

如果項目很大型的時候,后綴依賴非常有用。符合后綴依賴的文件往往有類似的操作,我們可以將這些操作用后綴依賴表示,而避免重復輸入。

 
其他

makefile的續行符為\

 

makefile中經常會定義下面依賴關系:

all:

如果make后沒有跟隨文件名,那么將執行該依賴關系。

clean:

常用于清理歷史文件。

 

比如:
復制代碼

CC = gcc

.SUFFIXES: .c .o

.c.o:
        $(CC) -c -o $@ $^

#--------------------------

all: helloworld
        @echo "ALL"

# helloworld is a binary file
helloworld: test.o
        @echo $@
        $(CC) -o $@ $^

test.o: test.c

clean:
        -rm helloworld *.o

復制代碼

注意: echo前面的@和rm前面的-。@后的命令將不顯示命令本身。-后面的命令將忽略錯誤(比如刪除不存在的文件)。

 
總結

make的核心功能是根據依賴關系來實現編譯管理。

make的其他功能是讓用戶可以更加便捷的寫出makefile。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西华县| 台中县| 永靖县| 库车县| 临洮县| 黎川县| 房产| 永康市| 高密市| 武宁县| 河津市| 嘉善县| 祁东县| 全州县| 察隅县| 罗田县| 横山县| 凌云县| 南丹县| 太仓市| 无棣县| 化隆| 万山特区| 舞钢市| 合江县| 鄂尔多斯市| 施甸县| 望奎县| 措美县| 修武县| 西畴县| 安岳县| 岫岩| 和顺县| 沂南县| 托克托县| 海口市| 永城市| 涞源县| 青阳县| 佛山市|