(最近開發的項目中須要編寫Shell腳本對整個工程進行自動化編譯,即在Shell腳本中使用make命令來進行編譯,下面回顧一下Shell腳本中如何使用make命令)程序員
在開發一個系統時,通常是將一個系統分紅幾個模塊,這樣作提升了系統的可維護性,但因爲各個模塊間不可避免存在關聯,因此當一個模塊改動後,其餘模塊也許會有所更新,固然對小系統來講,手工編譯鏈接是沒問題,可是若是是一個大系統,存在不少個模塊,那麼手工編譯的方法就不適用了。爲此,在Linux系統中,專門提供了一個make命令來自動維護目標文件,與手工編譯和鏈接相比,make命令的優勢在於他只更新修改過的文件(在Linux中,一個文件被建立或更新後有一個最後修改時間,make命令就是經過這個最後修改時間來判斷此文件是否被修改),而對沒修改的文件則置之不理,而且make命令不會漏掉一個須要更新的文件。shell
文件和文件間或模塊或模塊間有可能存在倚賴關係,make命令也是依據這種依賴關係來進行維護的,因此咱們有必要了解什麼是依賴關係;make命令固然不會本身知道這些依賴關係,而須要程序員將這些依賴關係寫入一個叫makefile的文件中。bash
下面是詳細解析:工具
1、Make命令ui
一、make命令基礎概念.net
Make這個詞,英語的意思是」製做」。Make命令直接用了這個意思,就是要作出某個文件。好比,要作出文件a.txt,就能夠執行下面的命令。命令行
$ make a.txt
可是,若是你真的輸入這條命令,它並不會起做用。由於Make命令自己並不知道,如何作出a.txt,須要有人告訴它,如何調用其餘命令完成這個目標。
好比,假設文件a.txt 依賴於b.txt 和 c.txt ,是後面兩個文件鏈接(cat命令)的產物。那麼,make 須要知道下面的規則。對象
a.txt: b.txt c.txt
cat b.txt c.txt > a.txt
也就是說,make a.txt 這條命令的背後,實際上分紅兩步:第一步,確認 b.txt 和 c.txt 必須已經存在,第二步使用 cat 命令 將這個兩個文件合併,輸出爲新文件。
像這樣的規則,都寫在一個叫作Makefile的文件中,Make命令依賴這個文件進行構建。Makefile文件也能夠寫爲makefile, 或者用命令行參數指定爲其餘文件名。blog
$ make -f rules.txt # 或者 $ make --file=rules.txt
上面代碼指定make命令依據rules.txt文件中的規則,進行構建。繼承
二、make命令使用方法
Make命自己可帶有四種參數:標誌、宏定義、描述文件名和目標文件名。其標準形式爲:
Make [flags] [macro definitions] [targets]
Unix系統下標誌位flags選項及其含義爲:
-f file 指定file文件爲描述文件,若是file參數爲"-"符,那麼描述文件指向標準輸入。若是沒有"-f"參數,則系統將默認當前目錄下名爲makefile或者名爲Makefile的文件爲描述文件。在Linux中, GNU make 工具在當前工做目錄中按照GNUmakefile、makefile、Makefile的順序搜索 makefile文件。
-i 忽略命令執行返回的出錯信息。
-s 沉默模式,在執行以前不輸出相應的命令行信息。
-r 禁止使用build-in規則。
-n 非執行模式,輸出全部執行命令,但並不執行。
-t 更新目標文件。
-q make操做將根據目標文件是否已經更新返回"0"或非"0"的狀態信息。
-p 輸出全部宏定義和目標文件描述。
-d Debug模式,輸出有關文件和檢測時間的詳細信息。
Linux下make標誌位的經常使用選項與Unix系統中稍有不一樣,下面咱們只列出了不一樣部分:
-c dir 在讀取 makefile 以前改變到指定的目錄dir。
-I dir 當包含其餘 makefile文件時,利用該選項指定搜索目錄。
-h help文擋,顯示全部的make選項。
-w 在處理 makefile 以前和以後,都顯示工做目錄。
經過命令行參數中的target ,可指定make要編譯的目標,而且容許同時定義編譯多個目標,操做時按照從左向右的順序依次編譯target選項中指定的目標文件。若是命令行中沒有指定目標,則系統默認target指向描述文件中第一個目標文件。
一般,makefile 中還定義有 clean 目標,可用來清除編譯過程當中的中間文件,例如:
clean:
rm -f *.o
運行 make clean 時,將執行 rm -f *.o 命令,最終刪除全部編譯過程當中產生的全部中間文件。
隱含規則
在make 工具中包含有一些內置的或隱含的規則,這些規則定義瞭如何從不一樣的依賴文件創建特定類型的目標。Unix系統一般支持一種基於文件擴展名即文件名後綴的隱含規則。這種後綴規則定義瞭如何將一個具備特定文件名後綴的文件(例如.c文件),轉換成爲具備另外一種文件名後綴的文件(例如.o文件):
.c:.o
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
系統中默認的經常使用文件擴展名及其含義爲:
.o 目標文件
.c C源文件
.f FORTRAN源文件
.s 彙編源文件
.y Yacc-C源語法
.l Lex源語法
在早期的Unix系統系統中還支持Yacc-C源語法和Lex源語法。在編譯過程當中,系統會首先在makefile文件中尋找與目標文件相關的.C文件,若是還有與之相依賴的.y和.l文件,則首先將其轉換爲.c文件後再編譯生成相應的.o文件;若是沒有與目標相關的.c文件而只有相關的.y文件,則系統將直接編譯.y文件。
而GNU make 除了支持後綴規則外還支持另外一種類型的隱含規則--模式規則。這種規則更加通用,由於能夠利用模式規則定義更加複雜的依賴性規則。模式規則看起來很是相似於正則規則,但在目標名稱的前面多了一個 % 號,同時可用來定義目標和依賴文件之間的關係,例以下面的模式規則定義瞭如何將任意一個 file.c 文件轉換爲 file.o 文件:
%.c:%.o
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
2、Makefile文件
一、概述
Makefile文件由一系列規則(rules)構成。每條規則的形式以下。
<target> : <prerequisites> [tab] <commands>
上面第一行冒號前面的部分,叫作」目標」(target),冒號後面的部分叫作」前置條件」(prerequisites);第二行必須由一個tab鍵起首,後面跟着」命令」(commands)。
「目標」是必需的,不可省略;」前置條件」和」命令」都是可選的,可是二者之中必須至少存在一個。
每條規則就明確兩件事:構建目標的前置條件是什麼,以及如何構建。
二、 目標(target)
一個目標(target)就構成一條規則。目標一般是文件名,指明Make命令所要構建的對象,好比 a.txt 。目標能夠是一個文件名,也能夠是多個文件名,之間用空格分隔
除了文件名,目標還能夠是某個操做的名字,這稱爲」僞目標」(phony target)。
clean: rm *.o
上面代碼的目標是clean,它不是文件名,而是一個操做的名字,屬於」僞目標 「,做用是刪除對象文件。
$ make clean
可是,若是當前目錄中,正好有一個文件叫作clean,那麼這個命令不會執行。由於Make發現clean文件已經存在,就認爲沒有必要從新構建了,就不會執行指定的rm命令
爲了不這種狀況,能夠明確聲明clean是」僞目標」,寫法以下。
.PHONY: clean
clean: rm *.o temp
聲明clean是」僞目標」以後,make就不會去檢查是否存在一個叫作clean的文件,而是每次運行都執行對應的命令。像.PHONY這樣的內置目標名還有很多,能夠查看手冊。
若是Make命令運行時沒有指定目標,默認會執行Makefile文件的第一個目標。
$ make
上面代碼執行Makefile文件的第一個目標。
例:執行多個目標
.PHONY: cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm program
cleanobj : rm *.o
cleandiff : rm *.diff
3、shell 腳本各類執行方式(source ./*.sh, . ./*.sh, ./*.sh)的區別
結論一: ./*.sh的執行方式等價於sh ./*.sh或者bash ./*.sh,此三種執行腳本的方式都是從新啓動一個子shell,在子shell中執行此腳本。
結論二: .source ./*.sh和 . ./*.sh的執行方式是等價的,即兩種執行方式都是在當前shell進程中執行此腳本,而不是從新啓動一個shell 而在子shell進程中執行此腳本。
驗證依據:沒有被export導出的變量(即非環境變量)是不能被子shell繼承的
驗證結果:
[root@localhost ~]#name=dangxu //定義通常變量
[root@localhost ~]# echo ${name}
dangxu
[root@localhost ~]# cat test.sh //驗證腳本,實例化標題中的./*.sh
#!/bin/sh
echo ${name}
[root@localhost ~]# ls -l test.sh //驗證腳本可執行
-rwxr-xr-x 1 root root 23 Feb 6 11:09 test.sh
[root@localhost ~]# ./test.sh //如下三個命令證實告終論一 [root@localhost ~]# sh ./test.sh [root@localhost ~]# bash ./test.sh [root@localhost ~]# . ./test.sh //如下兩個命令證實告終論二 dangxu [root@localhost ~]# source ./test.sh dangxu [root@localhost ~]# --------------------- 做者:zqixiao_09 來源:CSDN 原文:https://blog.csdn.net/zqixiao_09/article/details/51417138 版權聲明:本文爲博主原創文章,轉載請附上博文連接!