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

溫馨提示×

溫馨提示×

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

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

make 的隱式規則(十一)

發布時間:2020-02-28 15:16:13 來源:網絡 閱讀:550 作者:上帝之子521 欄目:系統運維

        如果我們將同一個目標的命令拆分的寫到不同地方,會發生什么呢?我們來看看下面的代碼

.PHONY : all

all :
    @echo "command-1"

VAR := test
        
all :
    @echo "all : $(VAR)"

        我們來分析下,這份代碼中有兩個目標 all,那么我們在執行 make 的時候。它到底是執行哪個呢?一個可能是兩個都執行,另一個就是執行第一個,因為默認的是執行第一個目標。下來我們來看看執行結果

make 的隱式規則(十一)

        我們看到它說 all 重復了,便忽略了前面的 all 命令。最終執行的是最后一個 all 命令。因此,當 makefile 中出現同名目標時,會將所有的依賴合并在一起,成為目標的最終依賴;當多處出現同一目標的命令時,make 發出警告,所有之前定義的命令被最后定義的命令取代注意:當使用 include 關鍵字包含其他文件時,需要確保被包含文件中的同名目標只要依賴,沒有命令;否則,同名目標的命令將被覆蓋!我們還是來看看,再建立一個新的 makefile.1


makefile.1 源碼

all :
    @echo "this is command from makefile.1"


makefile 源碼

.PHONY : all

VAR := test

all :
    @echo "all : $(VAR)"

include makefile.1

        我們來看看編譯結果,看看打印出的是不是 all : test

make 的隱式規則(十一)

        我們看到輸出的是 "this is command from makefile.1,并不是我們所期望的 all : test。其實也不難理解,因為我們包含的 makefile.1 中也包含了 all 命令,因此將上面的 all 給替換了。換句話說,這個現象有可能會給我們帶來意想不到的結果。那么這也就屬于 makefile 中的一條隱式規則了,什么是隱式規則呢?在 make 中,它提供了一些常用的,例行的規則實現;當相應目標的規則未提供時,make 嘗試使用隱式規則。那么我們來看看下面這個 makefile 能編譯成功嗎?

.PHONY : all

SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)

app.out : $(OBJS)
    $(CC) -o $@ $^
    $(RM) $^
    @echo "Target ==> $@"

        我們看看編譯的結果,是否會報錯?

make 的隱式規則(十一)

        我們看到已經正確的編譯了,而且結果也是對的。那么我們并沒有在里面定義相應的規則啊,為什么就能正確編譯呢?我們按照它的格式寫個規則,再將 cc 換成 gcc 試試,看看結果是否會相同?

.PHONY : all

CC := gcc

SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)

app.out : $(OBJS)
    $(CC) -o $@ $^
    $(RM) $^
    @echo "Target ==> $@"

%.o : %.c
    @echo "my rule"
    $(CC)   -c -o $@ $^

        編譯結果如下

make 的隱式規則(十一)

        結果和之前是一樣的,只不過是輸出了我們自定義的語句,將 cc 換成了 gcc。那么 cc 是什么呢?為何能編譯源文件呢?cc 第一個 c 是 C 語言,第二個是 compiler 編譯器的意思。那么這個 cc 編譯器是哪來的呢?在原來的 Unix 系統中是有 cc 編譯器的,因為它是商業版的,需要收費,因此在 Linux 系統中也是要支持 cc 的,不過此 cc 非彼 cc,我們來看看 cc 最后的原型是什么

make 的隱式規則(十一)

        我們看到 cc 最后指向的是 gcc,因此使用 cc 進行編譯工作其實也是和使用 gcc 進行編譯是一樣的。那么上面的模式規則是誰來實現的呢?這個便是 makefile 中的隱式規則了。make 提供了生成目標文件的隱式規則,隱式規則會使用預定義變量完成編譯工作;改變預定義變量將部分改變隱式規則的行為,當存在自定義規則時,不再使用隱式規則。當 make 發現目標的依賴不存在時,嘗試通過依賴名逐一查找隱式規則,并且通過依賴名推導可能需要的源文件,如下

make 的隱式規則(十一)

        既然隱式編譯這么強大,我們是不是就不用自己編寫相關規則了呢?其實不是的,根據前輩們的經驗總結。在實際的項目中,我們還是有必要禁止 makefile 中的隱式規則的,因為隱式規則有副作用。具體表現在:a> 編譯行為難以控制,大量使用隱式規則可能產生意想不到的編譯行為;b> 編譯效率低下,make 從隱式規則和自定義規則中選擇最終使用的規則。

        那么我們下來來看看隱式規則鏈。當依賴的目標不存在時,make 會極力組合各種隱式規則對目標進行創建,進而產生意料之外的編譯行為!如:需要名為 N.o 的目標:N.y --> N.c --> N.o。我們還是以代碼為例來進行分析說明


main.c 源碼

#include <stdio.h>

extern void greeting();

int main()
{
    greeting();
    
    return 0;
}


func.p 源碼(這只是一個測試的代碼,用的是  Pascal 語言)

unit Func;

interface

procedure Greeting(); attribute (name = 'greeting');

implementation

procedure Greeting();
begin
  WriteLn('Hello, Pascal!');
end;

end.


makefile 源碼

app.out : main.o func.o
    $(CC) -lstdc++ -o $@ $^

        那么我們此時想要用 func.c 實現某個功能,但是現在沒有 func.c,所以編譯時肯定會出錯

make 的隱式規則(十一)

        我們看到 func.o 竟然會利用 func.p 來生成,不過最終還是出錯了。出現這樣的錯誤,我們是不是很納悶呢?明明是沒有對應的源文件,但是卻報的是沒有 pc 命令。這個便是 makefile 中的隱式規則了,那么 make 究竟提供了多少隱式規則?應如何查看查看隱式規則呢?查看隱式規則的方法是:查看所有的是 make -p;查看具體的規則是 make -p | grep "XXX"。下來我們來看看 make 中的隱式規則

make 的隱式規則(十一)

        因為所有的規則非常多,我們只截取了其中的一段,下來看看 %.o 對應的規則

make 的隱式規則(十一)

        我們看到它默認的是支持好多格式的,其中就包括 .c 和 .p 文件,因此它會將將我們之前的測試代碼當成源文件進行編譯了。那么我們應該如何避免它的隱式規則呢?在局部禁用的話,是直接在 makefile 中自定義規則或者在 makefile 中定義模式(如:%.o : %.p);全局禁用的話則使用 make -r。下來我們先來使用下局部禁用的方式,直接在 makefile 中定義模式,但是不做具體處理。

make 的隱式規則(十一)

        它直接就報錯了,說沒有相應的源文。我們再來看看使用全局禁用的方式

make 的隱式規則(十一)

        我們看到使用全局禁用的方式后,連 main.o 的文件也不能生成了。下來我們來說說后綴規則,它是舊式的“模式規則”,可以通過后綴描述的方式自定義規則。格式如下

make 的隱式規則(十一) 

        后綴規則分為雙后綴規則和單后綴規則。雙后綴規則是指定義一對文件后綴(依賴文件后綴和目標文件后綴),如:.cpp.o <==> %.o : %.cpp;單后綴規則是指定義單個文件后綴(源文件后綴),如:.c <==> % : %.c。后綴規則有這么幾個注意事項:1、后綴規則中不允許有依賴;2、后綴規則必須有命令,否則無意義;3、后綴規則將逐步被模式規則所取代。

        下來我們還是以代碼為例來進行分析說明,我們新建一個 func.c 文件用于說明問題


func.c 源碼

#include <stdio.h>

void greeting()
{
    printf("void greeting : %s\n", "hello makefile!");
}


makefile 源碼

app.out : main.o func.o
    $(CC) -lstdc++ -o $@ $^

.c.o :
    @echo "my suffix rule"
    $(CC) -o $@ -c $^

.c :
    @echo "my suffix rule"
    $(CC) -o $@ -c $^

        我們來看看編譯結果

make 的隱式規則(十一)

        我們看到已經正確實現了。不過在現在的工程項目中,我們一般都會摒棄掉后綴規則,采用的都是模式規則。通過對 makefile 中隱式規則的學習,總結如下:1、當多處出現同一目標的命令時,只有最后定義的命令才有效;2、make 提供了一系列的隱式規則可使用,當 makefile 中未定義相關規則時,將嘗試使用隱式規則;3、隱式規則中可能使用 make 中的預定義變量,改變預定義變量可部分改變預定義規則的行為;4、隱式規則可能造成意想不到的編譯行為,在實際工程項目中盡量不使用隱式規則;5、后綴規則是一種舊式的模式規則,它正逐步被模式規則所取代。


        歡迎大家一起來學習 makefile,可以加我QQ:243343083

向AI問一下細節

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

AI

阿合奇县| 名山县| 龙井市| 米易县| 阆中市| 雷山县| 大渡口区| 师宗县| 浙江省| 特克斯县| 湘阴县| 安新县| 南投市| 宜兴市| 长寿区| 亚东县| 瓦房店市| 湘潭县| 保山市| 石屏县| 镇原县| 略阳县| 小金县| 平利县| 靖西县| 民县| 南乐县| 邓州市| 阜宁县| 肇州县| 黄梅县| 鸡西市| 容城县| 阿瓦提县| 兴业县| 类乌齐县| 晋江市| 兴仁县| 上饶市| 石屏县| 克东县|