linux小記:makefile(隨使用程度持續更新)

[我的筆記,僅限自己看懂=.=,也會隨着我對makefile的需要程度和認知程度亂序更新]

格式

makefile的格式:

target : prerequisites 
  command  //任意的shell 命令

注意這個command可以是任意的shell命令

也就是說,如果

clean:
    echo "I love you"

當你在命令行中make clean的時候,只會顯示I love you;而對於下面的makefile:

xixi:
    rm *.o

當在命令行中輸入make xixi的時候,會執行rm *.o操作,刪除所有的.o文件,起到我們心中所認爲的clean的作用。

生成多個可執行程序

現在我們想生成兩個完全不相依賴的程序:myServer和myClient。規則已經在makefile中寫好,如下:

# Generated automatically from Makefile.in by configure.
CC=g++
CFLAGS=-g -I/usr/local/openssl/include/  -Wall
LD=-L/usr/local/openssl/lib  -lssl -lcrypto -ldl -lpthread
DISTDIR=Test

DIST=common.cpp \
    common.h \
    HttpProtocol.cpp \
    HttpProtocol.h \
    myServer.cpp \

myClient: myClient.c
    gcc -g -o myClient myClient.c -lssl -lcrypto -ldl
myServer: common.o myServer.o HttpProtocol.o
    $(CC) common.o myServer.o HttpProtocol.o -o myServer $(LD)
HttpProtocol.o: HttpProtocol.cpp
    g++ -g -c HttpProtocol.cpp
common.o: common.cpp
    g++ -g -c common.cpp
myServer.o: myServer.cpp
    g++ -g -c myServer.cpp

clean:  
    rm *.o
cleanAll:
    rm *.o myClient myServer

如果我們在命令行中輸入make

lgl@pArch ~/tmp/SSL $ make
gcc -g -o myClient myClient.c -lssl -lcrypto -ldl
lgl@pArch ~/tmp/SSL $ 

只生成了myClient一個程序,而myServer完全沒動靜。這是因爲makefile以最上面的目標文件爲最終的目標。那麼我們最終的目標就是myClient,生成myClient的先決條件(prerequisite)只需要myClient.c就夠了,所以即使寫好了myServer的生成規則,但是對於makefile來說,它認爲這跟生成myClient有什麼關係嗎?並沒有。那自然就不管了。
(插句廣告,根據上面的知識,我們可以使用make myClientmake myServer分別生成myClient或myServer)
所以如果我們要生成兩個目標程序,我們應該這樣寫:

# Generated automatically from Makefile.in by configure.
CC=g++
CFLAGS=-g -I/usr/local/openssl/include/  -Wall
LD=-L/usr/local/openssl/lib  -lssl -lcrypto -ldl -lpthread
DISTDIR=Test

DIST=common.cpp \
    common.h \
    HttpProtocol.cpp \
    HttpProtocol.h \
    myServer.cpp \

liuhaibo: myClient myServer #This decides the compiling order

myClient: myClient.c
    gcc -g -o myClient myClient.c -lssl -lcrypto -ldl
myServer: common.o myServer.o HttpProtocol.o
    $(CC) common.o myServer.o HttpProtocol.o -o myServer $(LD)
HttpProtocol.o: HttpProtocol.cpp
    g++ -g -c HttpProtocol.cpp
common.o: common.cpp
    g++ -g -c common.cpp
myServer.o: myServer.cpp
    g++ -g -c myServer.cpp

clean:  
    rm *.o
cleanAll:
    rm *.o myClient myServer

這樣在make的時候就成功生成了myClient和myServer,爲什麼呢?

因爲我們最終的目標是liuhaibo,而liuhaibo需要兩個先決條件,myClient和myServer,所以makefile自然得先生成這兩個先覺條件,於是myClient和myServer就被下面相應的規則生成出來了。然後你可能會奇怪在結束之後只有myClient和myServer,並沒有生成liuhaibo這個文件啊!此時好好想想makefile的規則,然後再看我們新添加的這句話:

liuhaibo: myClient myServer 

target: liuhaibo
prerequisites: myClient和myServer
command: 無
所以並沒有相應的shell命令,於是也就沒有執行任何東西啦。
我們還可以來個更明顯的現象,給它添加一個shell命令:

liuhaibo: myClient myServer
    touch "newFile_`date`"

於是:

lgl@pArch ~/tmp/SSL $ make
touch "newFile_`date`"
lgl@pArch ~/tmp/SSL $ make
touch "newFile_`date`"
lgl@pArch ~/tmp/SSL $ make
touch "newFile_`date`"
lgl@pArch ~/tmp/SSL $ ls newFile*  
'newFile_Sat May 21 15:14:51 CST 2016'
'newFile_Sat May 21 15:14:52 CST 2016'
'newFile_Sat May 21 15:14:53 CST 2016'

make一次,就運行一次touch "newFile_$(date)"一次,生成一個新文件。因爲這條shell命令生成的是newFile_$(date),跟liuhaibo這個文件並沒有關係,所以並沒有生成liuhaibo這個文件。

當然啦,一般沒人用liuhaibo這麼逗比的名詞的,一般大家都是用ALL或all,而且需要帶上.PHONY,比如:

.PHONY: ALL
ALL: myClient myServer

.PHONY

A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request. There are two reasons to use a phony target: to avoid a conflict with a file of the same name, and to improve performance.

If you write a rule whose recipe will not create the target file, the recipe will be executed every time the target comes up for remaking. Here is an example:

clean:
        rm *.o temp

Because the rm command does not create a file named clean, probably no such file will ever exist. Therefore, the rm command will be executed every time you say ‘make clean’.

In this example, the clean target will not work properly if a file named clean is ever created in this directory. Since it has no prerequisites, clean would always be considered up to date and its recipe would not be executed. To avoid this problem you can explicitly declare the target to be phony by making it a prerequisite of the special target .PHONY (see Special Built-in Target Names) as follows:

.PHONY: clean
clean:
        rm *.o temp

Once this is done, ‘make clean’ will run the recipe regardless of whether there is a file named clean.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章