1. 程式人生 > >Makefile中如何根據原始檔自動生成其所需要的標頭檔案

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

前言

Makefile自動生成標頭檔案依賴是很常用的功能,本文的目的是想盡量詳細說明其中的原理和過程。

Makefile模板

首先給出一個本人在小專案中常用的Makefile模板,支援自動生成標頭檔案依賴。

CC      = gcc 
CFLAGS  = -Wall -O
INCLUDEFLAGS = 
LDFLAGS = 
OBJS    = seq.o
TARGETS = test_seq 

.PHONY:all 
all : $(TARGETS)

test_seq:test_seq.o $(OBJS)
    $(CC) -o [email protected] $^ $(LDFLAGS)

%.o:%.c
    $(CC) -o 
[email protected]
-c $< $(CFLAGS) $(INCLUDEFLAGS) %.d:%.c @set -e; rm -f [email protected]; $(CC) -MM $< $(INCLUDEFLAGS) > [email protected]$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o [email protected] : ,g' < [email protected]$$$$ > [email protected]; \ rm -f
[email protected]
$$$$ -include $(OBJS:.o=.d) .PHONY:clean clean: rm -f $(TARGETS) *.o *.d *.d.*

基礎知識

在進行下一步之前,首先需要了解make的執行步驟:

  1. 讀入Makefile
  2. 讀入被include的其它Makefile
  3. 初始化Makefile中的變數
  4. 推導隱晦規則,並分析所有規則
  5. 為所有目標建立依賴關係鏈
  6. 根據依賴關係,決定哪些目標需要重新生成
  7. 執行生成命令

如何動態生成依賴關係?

從上面make的執行過程中可看出,要動態生成依賴關係,只能利用第2步讀入其它Makefile的機制。那麼,我們是否可以先把生成的依賴關係儲存到檔案,然後再把該檔案的內容包含進來? 答案是Yes! 只要利用include的機制。

include關鍵字是用於讀入其它Makefile檔案。當該檔案不存在時,make會尋找是否有生成它的規則,如果有,則執行其生成命令,然後再嘗試讀入。在include前加減號"-"可以上make忽略其產生的錯誤,並不輸出任何錯誤資訊。

即是說,我們需要提供生成規則檔案的規則。例如,我們可以這樣動態生成標頭檔案依賴關係:

seq.d : seq.c
    @echo “seq.o seq.d : seq.c seq.h" > [email protected]

-include seq.d

當make執行時,Makefile中的內容將是這樣子(指記憶體上的資料):

seq.d : seq.c
    @echo “seq.o seq.d : seq.c seq.h" > [email protected]

seq.o seq.d : seq.c seq.h

特別注意的是,由於對seq.c和seq.h的修改需要更新seq.d的內容(因為依賴關係可能已變化),因此seq.d也要在依賴關係的目標列表中。

自動生成標頭檔案依賴

基於上面的例子,現在可以開始討論如何自動生成標頭檔案依賴。

自動生成依賴關係

大多數c/c++編譯器提供了-M選項,可自動尋找原始檔依賴的標頭檔案,並生成依賴規則。對於gcc,需要使用-MM選項,否則它會把系統依賴的標頭檔案也包含進來。例如執行下面一個命令:

    gcc -MM seq.c

將輸出:

    seq.o : seq.c seq.h

但我們需要結果是seq.d也要包含在目標列表中,所以還需要對它進行文字處理。因此,上面的例子可改為:

seq.d : seq.c
    @set -e; \
    gcc -MM $< > [email protected]$$$$; \
    sed 's,\($*\)\.o[ :]*,\1.o [email protected] : ,g' < [email protected]$$$$ > [email protected]; \
    rm -f [email protected]$$$$

-include seq.d

生成規則中的執行命令解釋

第一個命令@set -e。@關鍵字告訴make不輸出該行命令;set -e的作用是,當後面的命令的返回值非0時,立即退出。

那麼為什麼要把幾個命令寫在”同一行“(是對於make來說,因為\的作用就是連線行),並用分號隔開每個命令?因為在Makefile這樣做才能使上一個命令作用於下一個命令。這裡是想要set -e作用於後面的命令。

第二個命令gcc -MM $< > [email protected]$$$$, 作用是根據原始檔生成依賴關係,並儲存到臨時檔案中。內建變數$<的值為第一個依賴檔案(那seq.c),$$$$為字串"$$",由於makefile中所有的$字元都是特殊字元(即使在單引號之中!),要得到普通字元$,需要用$$來轉義; 而$$是shell的特殊變數,它的值為當前程序號;使用程序號為字尾的名稱建立臨時檔案,是shell程式設計常用做法,這樣可保證檔案唯一性。

第三個命令作用是將目標檔案加入依賴關係的目錄列表中,並儲存到目標檔案。關於正則表示式部分就不說了,唯一要注意的是內建變數$*$*的值為第一個依賴檔案去掉字尾的名稱(這裡即是seq)。

第四個命令是將該臨時檔案刪除。

如果把內建變數都替換成其值後,實際內容是這樣子:

seq.d : seq.c
    @set -e; \
    gcc -MM seq.c > seq.d.$$$$; \
    sed 's,\(seq\)\.o[ :]*,\1.o seq.d : ,g' < seq.d.$$$$ > seq.d; \
    rm -f seq.d.$$$$

-include seq.d

Makefile的模式匹配

最後,再把Makefile的模式匹配應用上,就完成自動生成標頭檔案依賴功能了:

%.d : %.c
    @set -e; \
    gcc -MM [email protected] > [email protected]$$$$; \
    sed 's,\($*\)\.o[ :]*,\1.o [email protected] : ,g' < [email protected]$$$$ > [email protected]; \
    rm -f [email protected]$$$$

-include seq.d

參考資料


相關推薦

Makefile如何根據原始檔自動生成需要檔案

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

eclipse根據資料庫自動生成dao、mapper、model

現在程式碼管理基本上是採用Maven管理,Maven的好處此處不多說,大家用百度搜索會有很多介紹,本文介紹一下用Maven工具如何生成Mybatis的程式碼及對映的檔案。 一、配置Maven pom.xml 檔案 在pom.xml增加以下外掛:

Linux的靜態庫、共享庫、檔案makefile檔案舉例

2、在bill.c檔案中引入標頭檔案,寫該函式的實現; ***@ubuntu:~/codeC/1201B$ more bill.c #include "bill.h" int bill(int a[], int n) {     int i,max = a[i];     for( i = 0; i <

vue+element-ui實現多層級複雜的維度根據資料自動生成的表頭

表頭主要複雜在:1,有三層,一層是大類,第二層是具體項,第三層是標準值/對比值2,首列和末尾列是一層3,整個表格的維度是根據資料的輸入自己生成,也就是動態的下面是在 vue + eleUI 中的解決方案:<el-table :data="tableData" borde

Makefile常見的自動變量和含義

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

在Eclipse設置自動生成javadoc註釋

eth ram ref pos 分享圖片 pes ron bubuko methods 1)windows-->preference-->Java-->Code Style-->Code Templates-->code-->new Ja

Intellij IDEAmybatis-generator自動生成

div file cto pack 返回 package numeric ret color 一、在maven工程中的resource中創建generatorConfig.xml 二、配置generatorConfig.xml: <?xml version="1.

使用T4模板從根據資料庫自動生成類類檔案

一個數據庫可能有多個表,需要生成多個類檔案,首先建立一個xx.ttinclude檔案.此檔案主要能夠生成單獨的類檔案。同時再定義一個類DBHelper來獲取資料庫裡所有表的資訊和資料。 <#@ assembly name="System.Core"#><#@ assembly nam

在EF使用Expression自動生成p=>new Entity(){X="",Y="",..}格式的Lambda表示式靈活實現按需更新

一、基本介紹                                        

使用xorm工具,根據資料庫自動生成 go 程式碼

使用xorm工具,根據資料庫自動生成 go 程式碼 引入 使用 golang 操作資料庫的同學都會遇到一個問題 —— 根據資料表結構建立對應的 struct 模型。因為 golang 的使用首字母控制可見範圍,我們經常要設計 struct 欄位名和資料庫欄位名的對應關係。久而久之

spring boot使用mybatis自動生成程式碼

在Spring boot當中如果使用mybatis自動生成外掛,可以大大的減少我們重複編碼的工作,只需要集中精力與力量放在重要的核心業務上。下面我們來記錄一下在Spring boot下使用mybatis外掛。 1. 在pom.xml檔案中新增外掛 ** 需要

Djngo基於Form自動生成標籤和登入判斷

一、What is Form? 當我們在註冊某個網站的時候經常看到當我們手機號碼的位數不夠或者email輸入格式錯誤的時候,旁邊就會給你提示個小框框,提示你輸入錯誤重新輸入。這個判斷我們可以用Django自己寫出一個這樣的判斷,但是當你寫完之後你會發現要很多判斷

mybits根據自動生成 java類和mapper 檔案

mybits根據表自動生成 java類和mapper 檔案   我這個腦子啊,每次建立新的工程都會忘記是怎麼整合mybits怎麼生成mapper檔案的,so today , I can't write this blog for myself.   NO.1 we should create table

【MPC5744P】S32DSProcessor Expert自動生成程式碼工具使用教程(二) FreeMaster除錯

對於使用除錯口,下位機不需要做任何特別的設定,直接按照連結中設定方法來設定上位機即可,注意FreeMaster只能監測下位機中的全域性變數。連結地址:https://blog.csdn.net/u010875635/article/details/84789579   若是使用

【MPC5744P】S32DSProcessor Expert自動生成程式碼工具使用教程(一) 開發環境搭建

MPC5744P是NXP近幾年推出來的主打安全功能的雙核MCU,非常適合在汽車控制器相關產品中使用,非常強大。但是強大的同時,也意味著開發難度增大。 MPC5744P外設功能相關的暫存器非常之多,且對應的參考教程非常少,像STM32之類的工業MCU開發難度根本無法與之相比,早期只能依據官方參

mybatis根據自動生成實體bean,xml檔案,mapper檔案

步驟: 1.下載mysql-connector-java-5.1.39.jar包2.在pom檔案中加入 <build> <plugins> <plugin> <groupId>org.mybatis.generator</groupId>

根據資源自動生成相應的selector

1.首先安裝外掛 開啟Android studio的settings找到其中的Plugins 然後點選從瀏覽器查詢外掛 然後搜尋SelectorChapek for Android外掛然後安裝

java根據資料庫自動生成vo 類

以前我們 spring + hibernate 寫程式,現在我用 spring + ibatis ,不管是hibernate 還是 Ibatis 都要自己寫一堆對應資料庫的vo類 今天早上我自己手工寫了一個程式,可以自動讀取資料庫 (目前只支援oracl 中的 varchar2 和 numb

根據資料庫自動生成java程式碼

package com.power.util; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import

ci框架根據配置自動生成controller控制器和model控制器(改版本)

CI修改如下: if($modle_file=config_item('modle_file')) { if ($modle_file === TRUE) { $modle_file=config_item('modle_type');