1. 程式人生 > >關於makefile中自動產生依賴的理解

關於makefile中自動產生依賴的理解

本博文是在學習了《GNU Make中文手冊》後記錄下來的自己的關於自動產生makefile依賴的語句的理解,向大家分享。

《GNU make中文手冊》中的相關章節見一下連結:

http://blog.csdn.net/gmpy_tiger/article/details/51849257

========================================================================================

為了理解自動產生依賴的程式碼,必須先掌握這兩個基礎又有點偏的知識點:

1、Makefile 中,一個檔案可以作為多個規則的目標(多個規則中只能有一個規則定義命令)。這種情況時,以這個檔案為目標的規則的所有依賴檔案將會被合併成此目標一個依賴檔案列表

,當其中任何一個依賴檔案比目標更新(比較目標檔案和依賴檔案的時間戳)時,make 將會執行特定的命令來重建這個目標。

舉個例子:

有如下的makefile:

               foo.o : defs.h
               bar.o : defs.h test.h
               foo.o : config.h

等效於:

               foo.o : defs.h config.h

               bar.o : defs.h test.h

就是把相同foo.o目標的規則(最多隻允許一個規則有命令,其他規則只能有依賴)合併所有的依賴。

2、在linux 的命令sed中,有這麼一個規則(模式替換單獨的單詞,見《Linux命令列與shell指令碼程式設計大全》):

       sed編輯器用圓括號來定義替代模式的子字串,替代字元由反斜槓和陣列組成。

       很難理解是吧,舉個例子你就懂了。

       echo "maybe this is a test" | sed 's/\ (this\ ) is a \ (test\ )/Is \1 really \2 /g'

輸出:

       maybe Is this really test

       關於指令碼的echo,管道,sed的替換命令s等基礎我就不講了,自己百度學習。這裡我要講的是,用“()”小括號括起來的被替換內容

,可以在替換內容上用“\數字”代替,直接動態引用,省去重複輸入的麻煩。例如上面的例子,\1代表this,\2代表test,整個sed命令的意思是把

       this is a test

替換為

       Is this really test

ps:因為小括號在正則表示式中有意義,因此需要轉義,因此是\ (...\ )而不是(...)

========================================================================================

廢話不多說,先直接上我自己寫得自動產生依賴的程式碼(與《GNU Make中文手冊》有些許出入,會寫linux指令碼的就會發現,修改的部分無傷大雅):

              %.d : %.c

                         gcc -MM  $< > [email protected]$ $ $ $; \                                    (1)
                         sed 's/\ ($*\ )\.o/\1.o [email protected]/g' < [email protected]$ $ $ $ > [email protected]; \       (2)

                         rm -f [email protected]$ $ $ $                                                       (3)

ps:網頁的排版問題,為了看的直觀做了修改,使用時請把四個$以及\ (和\ )之間的空格去掉,下同

繼續以例子講解:

原始碼如下(helloworld.c):

          #include <stdio.h>
          #include "test.h" //test.h為空檔案,只用於實驗講解
          int main(int argc, char *argv){
                  printf("hello world!\n");
          }

(1):

用gcc -MM helloworld.c的輸出結果是:

         helloworld.o: helloworld.c test.h

因此(1)行程式碼

            gcc -MM  $< > [email protected]$ $ $ $; \                                    (1)

的作用,就是生成helloworld.o.xxxx的臨時檔案,檔案內寫得是"helloworld.o: helloworld.c test.h"

ps:在第一行的程式碼裡涉及到makefile的自動化變數$<、[email protected]和linux指令碼的重定向,自行百度,不再講解。

(2):

第二行的程式碼

 sed 's/\ ($*\ )\.o/\1.o [email protected]/g' < [email protected]$ $ $ $ > [email protected]; \       (2)

參考本博文上文的基礎知識2,其中,$*是自動化變數,在這裡指的是:helloworld。[email protected]也是自動化變數,在這裡指的是helloworld.d。

這行程式碼可以理解為:

            sed 's/helloworld.o/helloworld.o helloworld.d/g' < [email protected]$ $ $ $ >[email protected]

            ps:其中的兩個< 、>為linux指令碼的重定向,自己百度學習。

因此,實際的處理結果是把第(1)行程式碼的結果

helloworld.o: helloworld.c test.h

轉換為:

helloworld.o helloworld.d: helloworld.c test.h

並把轉換的結果儲存到helloworld.d檔案中。

(3):

第二行程式碼其實就已經完成任務了,第三行程式碼僅僅是刪除第一行程式碼建立的臨時檔案[email protected]$$$$。在此不再詳述。

=======================================================================================

自動產生依賴的程式碼就這樣理解,那怎麼使用呢?

先看看上面程式碼生成的結果:

 helloworld.o helloworld.d: helloworld.c test.h      儲存在helloworld.d檔案中

要使用,除了上面的程式碼之外,只需要加一句

            include helloworld.d

其實就相當於把程式碼自動生成的helloworld.o helloworld.d: helloworld.c test.h包含在makefile中。

包含上了helloworld.d的作用有兩條

1、因為要包含helloworld.d,當搜尋不到有helloworld.d檔案時,就會自動匹配上文產生依賴的程式碼,自行生成helloworld.d,當然,當helloworld.c或者test.h修改後,由於helloworld.d已經過時,也會重新生成helloworld.d

2、helloworld.o的依賴會合並上helloworld.c test.h(參考本博文上文的基礎知識1),從而實現了自動產生依賴

=======================================================================================

總結起來,我對上面helloworld原始碼寫的makefile如下:

             CC = gcc 
TARGET = helloworld

$(TARGET) : 

include $(TARGET).d

%.d : %.c 
    gcc -MM $^ > [email protected]$ $ $ $; \
    sed 's/\ ($*.o\ )/\1 [email protected]/g' < [email protected]$ $ $ $ > [email protected]; \
    rm  [email protected]$ $ $ $

.PHONY: clean

clean:
    $(RM) $(TARGET) $(TARGET).d $(TARGET).o

helloworld.d如下:

             helloworld.o helloworld.d: helloworld.c test.h

相關推薦

關於makefile自動產生依賴理解

本博文是在學習了《GNU Make中文手冊》後記錄下來的自己的關於自動產生makefile依賴的語句的理解,向大家分享。 《GNU make中文手冊》中的相關章節見一下連結: http://blog.csdn.net/gmpy_tiger/article/details/5

makefile自動產生依賴關係

我們在編譯原始碼的時候,有時候會發現當我們修改某個.h檔案,make之後並沒有發生任何變化,大家是不是很困惑,命名修改了.h檔案為什麼不編譯呢,其實我們的.h不是依賴檔案,什麼意思?納尼?不是依賴檔案。。。我想告訴大家的是,是的,確實是的。 那問題來了,怎麼把我們的make

使用eclipse在Maven本地倉自動安裝依賴jar包的目錄結構

場景:maven專案新增第三方jar包依賴 解決方法:在本地倉中建立用到的依賴目錄結構。 建立步驟如下: a,以ojdbc14.jar為例,假如我們要在pom.xml裡寫成下面引用: <dependency> <groupId>me.li

Makefile常見的自動變量和含義

makefile info 自動 vmm var p s xms userinfo href 劫V3W71v9QGW貝膳http://jz.docin.com/cjwjy04096 1姥樸5KAQ訪顯39http://shufang.docin.com/fjqbs11

makefile(05)_自動生成依賴關系

makefile 自動生成依賴 include 11.自動生成依賴關系_上 11.0. 實驗原料 本節實驗所需的源文件和頭文件:原文件:func.c #include "stdio.h" #include "func.h" void foo() { printf("void foo() :

關於對iOS自動釋放池autoreleasepool的一些理解

因為現在大家都在使用ARC模式下進行程式設計,一個很重要的問題也是最容易被大家所忽視的問題就是自動釋放池,大部分程式設計師尤其是剛入行的都只是知道有這麼一個東西,但具體是什麼,工作的原理是什麼,在什麼時候使用它都一概不知。所以寫一篇文章,記錄一下個人對自動釋放池的一些理解。

《轉》mavenimport scope依賴方式解決單繼承問題的理解

在maven多模組專案中,為了保持模組間依賴的統一,常規做法是在parent model中,使用dependencyManagement預定義所有模組需要用到的dependency(依賴) <dependencyManagement>

理解git衝突產生的原因

例子一 1.master 新建檔案1.txt。 111 bug code 2.切出功能分支test,此時內容保持不變。同時開發了一點新的功能。 111 bug code new code int test 3.此時發現:master上的程式碼有bug,緊急修復了b

makefile的目標的依賴該怎麼寫?

注意,這篇博文 並不是makefile的教程! 並不是makefile的教程! 並不是makefile的教程! 僅僅是在學習makefile過程中關於如何寫依賴的一個感悟。 makefile的學習文件可參考: http://download.csdn.net/detail/

Makefile自動生成依賴檔案,並自動編譯

因為經常要用到makefile編譯,每次都為標頭檔案的依賴關係頭痛,所以這次費了兩天時間開發了一個通用的makefile,它可以自動生成依賴檔案,並編譯,當然你要按檔案裡面的說明來填充一些中間檔名. 程式碼如下: #自動依賴項(*.d),並編譯生成檔案 #編譯選項 LDF

Makefile如何根據原始檔自動生成其所需要的標頭檔案

前言 Makefile自動生成標頭檔案依賴是很常用的功能,本文的目的是想盡量詳細說明其中的原理和過程。 Makefile模板 首先給出一個本人在小專案中常用的Makefile模板,支援自動生成標頭檔案依賴。 CC = gcc CFLAGS = -Wa

IDEA maven引入的依賴自動匯入專案

一般來說是maven配置有問題,或者是有一個或是多個無法找到並且無法從maven倉庫下載,只要有一個jar沒載入成功,整個專案的jar就不會匯入到專案中,這是idea的特點。右面的這個窗口裡可以看具體是那個jar出了問題,沒有載入成功~當沒有紅色浪線說明maven載入成功。並

一份通用makefile,自動遍歷子目錄原始檔,自動生成依賴

這份makefile可以將當前makefile所在資料夾以及所有子資料夾中的cpp檔案打包成靜態庫/動態庫/可執行檔案. 自動生成所有依賴關係,修改任何檔案都可以觸發重新編譯相應依賴的檔案。 在U

makefile的為目標如何理解

使用makefile編譯C或者C++專案,經常會有 make all ,make clean,make install等命令,後面的all,clean install 都成為偽目標。 那麼相對於偽目標

makefile 自動生成依賴檔案

gcc  -c -o a.o a.c -Wp, -MD a.d a.d就是生成的依賴檔案 在a.d中 有 a.o:a.c a.h  (以及其他依賴的標頭檔案等) 在makefile中,包含依賴檔案,使用依賴檔案,使用如下: include a.d %.o : %.c$(CC

在Intellij IDEA 自動載入Maven管理的依賴包的原始碼

如果你的專案不是用 Maven 管理的,可以在專案依賴的Libraries下手工新增依賴包對應的原始碼jar檔案路徑, 方法可以參考此文: https://yq.aliyun.com/articles/72560 但如果你是用 Maven 來管理專案,就不用怎麼麻煩了,只需要在 Intellij IDE

makefile專題:自動生成依賴關係(續)

.PHONY : all clean rebuild MKDIR := mkdir RM := rm -rf CC := gcc DIR_DEPS := deps DIR_EXES := exes

Makefile常用自動變數

自動變數含義 $*不包含副檔名的目標檔名稱 $+所有的依賴檔案,以空格分開,並以出現的先後為序,可能包含重複的依賴檔案 $<第一個依賴檔案的名稱 $?所有時間戳比目標檔案晚的依賴檔案,並以空格分開 [email protected]目標檔案的完整名稱 $^所

makefile自動生成依賴

Makefile中,可能需要書寫一些規則來描述一個.o目標檔案和標頭檔案的依賴關係.例如,如果在main.c中使用"#include defs.h",那麼我們可能需要如下那樣的一個規則來描述當頭檔案"defs.h"被修改以後執行make,目標"main.o"應該被重建.

make的引數以及Makefile自動變數

最近把Makefile相關的內容稍微梳理了一遍,記錄下一些常用的內容,這篇寫下引數和自動變數吧,首先make的引數: make的引數 常用: “-q” “--question” 這個引數的行為是找目標的意思,也就是說,如果目標存在,那麼其什麼也不會輸出, 當然也不會執行編