當前位置:首頁 » 編程軟體 » makefile調用shell腳本

makefile調用shell腳本

發布時間: 2022-05-25 17:51:13

1. makefile 文件詳細介紹

makefile文件主要有以下五種組成部分。顯式規則:顯式規則說明了生成一個或多個目標文件的方法和步驟。這是在編寫makefile文件時明顯指出的,包括要生成的文件、生成文件的依賴文件以及生成的命令等。隱式規則:由於make工具有自動推導的功能,所以在編寫makefile文件的時候可以利用該規則,簡略地書寫makefile。再由 make 工具本身自動推導需要使用的規則。變數的定義: make工具支持變數的定義,這些變數往往都是字元串,因此makefile中的變數更像是C語言中的宏。當makefile被執行時,其中的變數都會被展開到相應的引用位置上。文件指示:其包括三個部分,一個是在一個makefile中引用另一個makefile,就像C語言中的include一樣。另一個是指根據某些情況指定makefile中的有效部分,就像C語言中的預編譯tlif一樣。還有就是定義一個多行的命令。注釋: makefile 中支持行注釋,這一點需要特別注意。makefile 中的注釋和 shell腳本一樣,其注釋是用「#」字元。如果需要在 makefile中使用「#」字元,可以用『\』對其進行轉義。例如,「\#」表示一個『#』字元。makefile文件的文件名最好命名為makefile或者Makefile。因為在默認的情況下,make命令會在當前目錄下按順序找尋這兩個文件進行解釋。用戶也可以為makefile文件自定義一個文件名,例如,Make.makefile,Make.admin等。

2. makefile 文件介紹

makefile文件主要有以下五種組成部分。顯式規則:顯式規則說明了生成一個或多個目標文件的方法和步驟。這是在編寫makefile文件時明顯指出的,包括要生成的文件、生成文件的依賴文件以及生成的命令等。隱式規則:由於make工具有自動推導的功能,所以在編寫makefile文件的時候可以利用該規則,簡略地書寫makefile。再由 make 工具本身自動推導需要使用的規則。變數的定義: make工具支持變數的定義,這些變數往往都是字元串,因此makefile中的變數更像是C語言中的宏。當makefile被執行時,其中的變數都會被展開到相應的引用位置上。
文件指示:其包括三個部分,一個是在一個makefile中引用另一個makefile,就像C語言中的include一樣。另一個是指根據某些情況指定makefile中的有效部分,就像C語言中的預編譯tlif一樣。還有就是定義一個多行的命令。
注釋: makefile 中支持行注釋,這一點需要特別注意。makefile 中的注釋和 shell腳本一樣,其注釋是用「#」字元。如果需要在 makefile中使用「#」字元,可以用『\』對其進行轉義。例如,「\#」表示一個『#』字元。makefile文件的文件名最好命名為makefile或者Makefile。因為在默認的情況下,make命令會在當前目錄下按順序找尋這兩個文件進行解釋。用戶也可以為makefile文件自定義一個文件名,例如,Make.makefile,Make.admin等。

3. 在一個Makefile中的語句 $(shell pwd)/include/

makefile中,要調用shell腳本。需要特殊的語法。
比如要調用xxx命令。
相應的語法是
$(shell xxx)

你直接使用xxx,比如pwd命令。人家makefile哪知道是shell命令啊。它只會把pwd當成makefile變數或者規則。

4. makefile中怎麼使用SHELL自定義函數

你的意思是在shell是怎麼使用自定義函數吧?
下面給你個程序,你一看便知:(耐心看完)
#############################################################
#功能:裝載指定目錄數據
#作者:PENGWEI
#時間:2015-11-18
#############################################################
# 數據日期參數,待傳入
V_DATA_DATE=$1
#FTP完成後數據存放路徑
V_DATA_DIR=/home/almusr/data/odsdata/FTP/$V_DATA_DATE
# FTP完成後生成的標志文件所在路徑
V_FTP_FLAG=/home/almusr/data/etl_load/FTPOK
# 解壓數據前備份數據的存放路徑
V_DATA_BAK=/home/almusr/data/odsdata/odsdata_bak
# 配置文件存放路徑
V_CFG_DIR=/home/almusr/cfg
#日誌文件
LOGDIR=/home/almusr/log/Loaddata_log
LOGFILE=$LOGDIR/LoadData_$V_DATA_DATE.log
# 初始化系統參數
DBNAME=ALMDB
USER=almusr
PASSWORD=almusr
SCHEMA=ODSUSR
#如果 日誌目錄不存在
if [ ! -d "${LOGDIR}" ]
then
#建立目錄
mkdir -p "${LOGDIR}"
fi
#\n --回車
echo "\n日誌文件[$LOGFILE]\n"
#日誌函數
recordLog()
{
echo `date +"%Y-%m-%d %T"`": $1" | tee -a $LOGFILE
return 0
}
#判斷參數個數
if [ $# -ne 1 ]
then
recordLog "Usage:$0 directory"
exit 1
fi
# $?表示上述命令執行後返回的狀態(執行成功返回0 執行不成功返回非0)
if [ $? -ne 0 ]
then
recordLog "cd $V_DATA_DIR error !"
exit 1
fi
#連接資料庫
db2 connect to $DBNAME user $USER using $PASSWORD
if [ $? -ne 0 ]
then
recordLog "connect[$DBNAME] fail!"
exit 1
fi
#載入數據

RETVAL=0
for i in `cat $V_CFG_DIR/tab_tmp2.cfg`
do
#讀取表名並輸出
TABLE_NAME=`echo $i | awk -F "," '{print $1}'`

#讀取文件後綴名並輸出
echo " the table_name is $TABLE_NAME"

#拼接文件名
FILENAME=${TABLE_NAME}.del
#解壓縮 臨時變數
FILENAME_TMP=$FILENAME.gz

echo "the FILENAME is $FILENAME"

recordLog "the FILENAME $FILENAME!"

# 第一步:對壓縮文件備份,先掃描FTP完成標志,如果存在就說明FTP過程已結束,開始備份,否則等待繼續掃描
#進去FTP完成標志所在目錄
cd $V_FTP_FLAG
#掃描FTP完成標志
if [[ ! -e "${V_DATA_DATE}.ok" ]]; then
sleep 1800
else
cd $V_DATA_BAK
#備份文件
cp -r $V_DATA_DIR ${V_DATA_DATE}_bak
cd ${V_DATA_DATE}_bak
rm -rf ${V_DATA_DATE}

fi
recordLog "Copy data was finished"
# 第二步:刪除30天前的備份數據
v_BakFileDate=`date -d "- 30 day ${V_DATA_DATE}" +%Y%m%d`

cd $V_DATA_BAK
rm -rf ${v_BakFileDate}_bak
recordLog "Removed the bak_data of 30 days before!"

# 第三步:對文件進行解壓
cd $V_DATA_DIR

if [ -f $FILENAME_TMP ]
then
echo "$FILENAME_TMP must gunzip"

#解壓文件
gunzip $FILENAME_TMP

echo "$FILENAME_TMP ,gunzip success"

else
echo "$FILENAME exist,next step"
recordLog "$FILENAME exist,next step!"
fi

# 第四步:數據載入
if [ -f $FILENAME ]
then
# CMD="db2 \"load from $FILENAME of del MODIFIED BY coldel0x23 usedefaults keepblanks decpt. replace into ODSUSR.$TABLE_NAME data buffer 10000\" > $LOGDIR/$TABLE_NAME_XX.log 2>&1"
CMD="db2 \"load from $FILENAME of del replace into ODSUSR.$TABLE_NAME data buffer 10000\" > $LOGDIR/$TABLE_NAME.log 2>&1"
echo "$FILENAME is loading"
eval $CMD

fi

echo "load data is over"

recordLog "load data is over"

# 第五步:判斷載入是否正確
#判斷是否正常載入
read_num=`cat $LOGDIR/$TABLE_NAME.log | grep "Number of rows read" | awk -F'=' '{print $2}'`
skip_num=`cat $LOGDIR/$TABLE_NAME.log | grep "Number of rows skipped" | awk -F'=' '{print $2}'`
load_num=`cat $LOGDIR/$TABLE_NAME.log | grep "Number of rows loaded" | awk -F'=' '{print $2}'`
reject_num=`cat $LOGDIR/$TABLE_NAME.log | grep "Number of rows rejected" | awk -F'=' '{print $2}'`
delete_num=`cat $LOGDIR/$TABLE_NAME.log | grep "Number of rows deleted" | awk -F'=' '{print $2}'`
commit_num=`cat $LOGDIR/$TABLE_NAME.log | grep "Number of rows committed" | awk -F'=' '{print $2}'`

echo "$read_num,$skip_num,$load_num,$reject_num,$delete_num,$commit_num"

#條件判斷載入是否正確
if [[ "$read_num" -eq "$load_num" && "$load_num" -eq "$commit_num" ]]
then
echo "Data loading is perfect!"
else
cat $LOGDIR/$TABLE_NAME.log
recordLog "loading [$V_DATA_DIR/$TABLE_NAME] error!"
RETVAL=1
continue
fi
done
db2 connect reset >/dev/null 2>&1
if [ $RETVAL != 0 ]
then
recordLog "load data directory [$V_DATA_DIR] error!!!"
else
recordLog "load data directory [$V_DATA_DIR] successful!!!"
fi
# 第五步:完成退出

exit 0

你可以把上面這段代碼拷貝出來,查看一下recordLog,這是個日誌函數,自定義的,其中參數是外部傳入的,調用格式也有,好好看看吧,別忘了點贊啊

5. 求助perl設定環境變數

在Makefile可以調用shell腳本,但是Makefile和shell腳本是不同的。本文試著歸納一下Makefile和shell腳本的不同。
1、 shell中所有引用以$打頭的變數其後要加{},而在Makefile中的變數是以$打頭的後加()。實例如下:
Makefile
PATH="/data/"
SUBPATH=$(PATH)
Shell
PATH="/data/"
SUBPATH=${PATH}
2、Makefile中所有以$打頭的單詞都會被解釋成Makefile中的變數。如果你需要調用shell中的變數(或者正則表達式中錨定句位$),都需要加兩個$符號($$)。實例如下:
PATH="/data/"
all:
echo ${PATH}
echo $$PATH例子中的第一個${PATH}引用的是Makefile中的變數,而不是shell中的PATH環境變數,後者引用的事Shell中的PATH環境變數。

4、在Makefile中只能在target中調用Shell腳本,其他地方是不能輸出的。比如如下代碼就是沒有任何輸出:
VAR="Hello"
echo "$VAR"
all:
.....以上代碼任何時候都不會輸出,沒有在target內,如果上述代碼改為如下:
VAR="Hello"
all:
echo "$VAR"
.....以上代碼,在make all的時候將會執行echo命令。
5、在Makefile中執行shell命令,一行創建一個進程來執行。這也是為什麼很多Makefile中有很多行的末尾都是「; \」,以此來保證代碼是一行而不是多行,這樣Makefile可以在一個進程中執行,例如:
SUBDIR=src example
all:
@for subdir in $(SUBDIR); \
do\
echo "building "; \
done上述可以看出for循環中每行都是以」; \」結尾的。
6、獲取當前目錄
PATH=`pwd` 注意是``,不是''

6. 如何寫Makefile

相信很多朋友都有過這樣的經歷,看著開源項目中好幾頁的makefile文件,不知所雲。在日常學習和工作中,也有意無意的去迴避makefile,能改就不寫,能用ide就用ide。其實makefile並沒有想像的那麼難寫,只要你明白了其中的原理,自己實踐幾次。你也可以自己寫makefile,讓別人對你頭來羨慕的目光。

下面本人介紹一下自己的學習成果,初學階段,歡迎大家多多指正。

簡單的說,makefile定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至可以在makefile中執行shell腳本。makefile帶來的好處就是——「自動化編譯」,一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟體開發的效率。

關於程序的編譯和鏈接

一般來說,無論是C還是C++,首先要把源文件編譯成中間代碼文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,這個動作叫做編譯(compile),一般來說,每個源文件都應該對應於一個中間目標文件(O文件或是OBJ文件)。然後再把大量的Object File合成執行文件,這個動作叫作鏈接(link)。

編譯時,編譯器需要的是語法的正確,函數與變數的聲明的正確。對於後者,通常是你需要告訴編譯器頭文件的所在位置(頭文件中應該只是聲明,而定義應該放在C/C++文件中),只要所有的語法正確,編譯器就可以編譯出中間目標文件。

鏈接時,主要是鏈接函數和全局變數,所以,我們可以使用這些中間目標文件(O文件或是OBJ文件)來 鏈接我們的應用程序。鏈接器並不管函數所在的源文件,只管函數的中間目標文件(Object File),在大多數時候,由於源文件太多,編譯生成的中間目標文件太多,而在鏈接時需要明顯地指出中間目標文件名,這對於編譯很不方便,所以,我們要給 中間目標文件打個包,在Windows下這種包叫「庫文件」(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件。

下面我們開始看看如何自己寫出makefile。

Makefile的規則

目標 : 需要的條件 (注意冒號兩邊有空格)

命令(注意前面用tab鍵開頭)

解釋一下:

1 目標可以是一個或多個,可以是Object File,也可以是執行文件,甚至可以是一個標簽。

2 需要的條件就是生成目標所需要的文件或目標

3 命令就是生成目標所需要執行的腳本

總結一下,就是說一條makefile規則規定了編譯的依賴關系,也就是目標文件依賴於條件,生成規則用命令來描述。在編譯時,如果需要的條件的文件比目標更新的話,就會執行生成命令來更新目標。

下面舉個簡單的例子說明。如果一個工程有3個頭文件,和8個C文件,我們為了完成前面所述的那三個規則,我們的Makefile應該是下面的這個樣子的。

edit : main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

將上面的內容寫入到Makefile文件中,然後執行make就可以進行編譯,執行make clean就可以刪除所有目標文件。解釋一下,也就是說生成最終的目標文件edit,依賴於一系列的.o目標文件,而這些.o文件又是需要用源文件來編譯生成的。

需要注意的是,clean後面沒有條件,而clean本身也不是文件,它只不過是一個動作名字,其冒號後什麼也沒有,那麼,make就不會自動去找文件的依賴性,也就不會自動執行其後所定義的命令。

make是如何工作的

在默認的方式下,也就是我們只輸入make命令。那麼,

1、make會在當前目錄下找名字叫「Makefile」或「makefile」的文件。
2、如果找到,它會找文件中的第一個目標文件(target),在上面的例子中,他會找到「edit」這個文件,並把這個文件作為最終的目標文件。
3、如果edit文件不存在,或是edit所依賴的後面的 .o 文件的文件修改時間要比edit這個文件新,那麼,他就會執行後面所定義的命令來生成edit這個文件。
4、如果edit所依賴的.o文件也不存在,那麼make會在當前文件中找目標為.o文件的依賴性,如果找到則再根據那一個規則生成.o文件。(這有點像一個堆棧的過程)
5、當然,你的C文件和H文件是存在的啦,於是make會生成 .o 文件,然後再用 .o 文件生命make的終極任務,也就是執行文件edit了。

makefile中使用變數

前面的知識已經足以讓你自己完成一個簡單的makefile了,不過makefile的精妙之處遠不止如此,下面來看看如何在makefile中使用變數吧。

在上面的例子中,先讓我們看看edit的規則:

edit : main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

我們可以看到[.o]文件的字元串被重復了兩次,如果我們的工程需要加入一個新的[.o]文 件,那麼我們需要在兩個地方加(應該是三個地方,還有一個地方在clean中)。當然,我們的makefile並不復雜,所以在兩個地方加也不累,但如果 makefile變得復雜,那麼我們就有可能會忘掉一個需要加入的地方,而導致編譯失敗。所以,為了makefile的易維護,在makefile中我們 可以使用變數。makefile的變數也就是一個字元串,理解成C語言中的宏可能會更好。

於是,我們使用變數objects

objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

這樣一來,原來的makefile變成如下的樣子:

objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit $(objects)

這樣看起來方便多了吧,也更加省事了。如果有新的.o文件怎麼辦?當然是在objects裡面添加了,這樣只需要一處改變,很方便吧。

讓make自動推導

GNU的make很強大,它可以自動推導文件以及文件依賴關系後面的命令,於是我們就沒必要去在每一個[.o]文件後都寫上類似的命令,因為,我們的make會自動識別,並自己推導命令。

只要make看到一個[.o]文件,它就會自動的把[.c]文件加在依賴關系中,如果make找到一 個whatever.o,那麼whatever.c,就會是whatever.o的依賴文件。並且 cc -c whatever.c 也會被推導出來,於是,我們的makefile再也不用寫得這么復雜。我們的是新的makefile又出爐了。

objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

edit : $(objects)
cc -o edit $(objects)

main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h

clean :
rm edit $(objects)

當然,如果你覺得那麼多[.o]和[.h]的依賴有點不爽的話,好吧,沒有問題,這個對於make來說很容易,誰叫它提供了自動推導命令和文件的功能呢?來看看最新風格的makefile吧。

objects = main.o kbd.o command.o display.o /
insert.o search.o files.o utils.o

edit : $(objects)
cc -o edit $(objects)

$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h
clean :
rm edit $(objects)

不過話說回來,本人並不推薦這種方法。雖然簡單,但是這種方法破壞了文件本身的依賴關系。如果文件過多的話,可能你自己都不清楚了。

7. makefile到底是干什麼用的

一個工程(project)中的源文件不計其數,其按類型、功能、模塊分別放在若干個目錄中,makefile定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至於進行更復雜的功能操作,因為 makefile就像一個Shell腳本一樣,其中也可以執行操作系統的命令。

Makefile 文件描述了整個工程的編譯、連接等規則。其中包括:工程中的哪些源文件需要編譯以及如何編譯、需要創建那些庫文件以及如何創建這些庫文件、如何最後產生我們想要的可執行文件。盡管看起來可能是很復雜的事情,但是為工程編寫Makefile 的好處是能夠使用一行命令來完成「自動化編譯」,一旦提供一個(通常對於一個工程來說會是多個)正確的
Makefile。編譯整個工程你所要做的唯一的一件事就是在shell 提示符下輸入make命令。整個工程完全自動編譯,極大提高了效率。

如果你使用的是帶有圖形用戶界面的集成化開發環境如VisualStudio,一般用不著手動編寫makefile文件,當你需要時,VS可以為你自動生成。

8. Linux下shell腳本怎麼實現運行某個文件的makefile

make工具就知道阿,makefile文件里描述了編譯參數等信息

9. 如何在makefile中以source 來運行一個shell腳本

make -f /Path/to/your/project/Makefile

e.g.

make -f ~/nagios/xxx/src/Makefile

熱點內容
java返回this 發布:2025-10-20 08:28:16 瀏覽:648
製作腳本網站 發布:2025-10-20 08:17:34 瀏覽:939
python中的init方法 發布:2025-10-20 08:17:33 瀏覽:634
圖案密碼什麼意思 發布:2025-10-20 08:16:56 瀏覽:823
怎麼清理微信視頻緩存 發布:2025-10-20 08:12:37 瀏覽:734
c語言編譯器怎麼看執行過程 發布:2025-10-20 08:00:32 瀏覽:1069
郵箱如何填寫發信伺服器 發布:2025-10-20 07:45:27 瀏覽:302
shell腳本入門案例 發布:2025-10-20 07:44:45 瀏覽:163
怎麼上傳照片瀏覽上傳 發布:2025-10-20 07:44:03 瀏覽:855
python股票數據獲取 發布:2025-10-20 07:39:44 瀏覽:765