Makefile巢狀執行
轉自:http://blog.csdn.net/shallnet/article/details/37595465?utm_source=tuicool&utm_medium=referral
=================================================
在大一些的專案裡面,所有原始碼不會只放在同一個目錄,一般各個功能模組的原始碼都是分開的,各自放在各自目錄下,並且標頭檔案和.c原始檔也會有各自的目錄,這樣便於專案程式碼的維護。這樣我們可以在每個功能模組目錄下都寫一個Makefile,各自Makefile處理各自功能的編譯連結工作,這樣我們就不必把所有功能的編譯連結都放在同一個Makefile裡面,這可使得我們的Makefile變得更加簡潔,並且編譯的時候可選擇編譯哪一個模組,這對分塊編譯有很大的好處。
現在我所處於工程目錄樹如下:
- .
- ├── include
- │ ├── common.h
- │ ├── ipc
- │ │ └── ipc.h
- │ └── tools
- │ ├── base64.h
- │ ├── md5.h
- │ └── tools.h
- ├── Makefile
- ├── src
- │ ├── ipc
- │ │ ├── inc
- │ │ ├── Makefile
- │ │ └── src
- │ │ └── ipc.c
-
│ ├── main
- │ │ ├── inc
- │ │ ├── Makefile
- │ │ └── src
- │ │ ├── main.c
- │ │ └── main.c~
- │ └── tools
- │ ├── inc
- │ ├── Makefile
- │ └── src
- │ ├── base64.c
- │ ├── md5.c
- │ └── tools.c
- └── tags
-
13 directories, 16 files
這樣組織專案原始碼要比之前合理一些,那這樣怎麼來寫Makefile呢?我們可以在每個目錄下寫一個Makefile,通過最頂層的Makefile一層一層的向下巢狀執行各層Makefile。那麼我們最頂層的Makefile簡單點的話可以這樣寫:
- # top Makefile for xxx
- all :
- >---$(MAKE) -C src
- tags:
- >---ctags -R
- clean :
- >---$(MAKE) -C src clean
- .PHONY : all clean tags
命令:
>---$(MAKE) -C src
就是進入src目錄繼續執行該目錄下的Makefile。然後src目錄下的Makefile在使用同樣的方法進入下一級目錄tools、main、ipc,再執行該目錄下的Makefile。其實這樣有些麻煩,我們可以直接從頂層目錄進入最後的目錄執行make。再加入一些偽目標完善下,我們的頂層Makefile就出來了:
- # Top Makefile for C program
- # Copyright (C) 2014 shallnew \at 163 \dot com
- all :
- >---$(MAKE) -C src/ipc
- >---$(MAKE) -C src/tools
- >---$(MAKE) -C src/main
- tags:
- >---ctags -R
- help:
- >[email protected] "===============A common Makefilefor c programs=============="
- >[email protected] "Copyright (C) 2014 liuy0711 \at 163\dot com"
- >[email protected] "The following targets aresupport:"
- >[email protected]
- >[email protected] " all - (==make) compile and link"
- >[email protected] " obj - just compile, withoutlink"
- >[email protected] " clean - clean target"
- >[email protected] " distclean - clean target and otherinformation"
- >[email protected] " tags - create ctags for vimeditor"
- >[email protected] " help - print help information"
- >[email protected]
- >[email protected] "To make a target, do 'make[target]'"
- >[email protected] "========================= Version2.0 ======================="
- obj:
- >---$(MAKE) -C src/ipc obj
- >---$(MAKE) -C src/tools obj
- >---$(MAKE) -C src/main obj
- clean :
- >---$(MAKE) -C src/ipc clean
- >---$(MAKE) -C src/tools clean
- >---$(MAKE) -C src/main clean
- distclean:
- >---$(MAKE) -C src/ipc distclean
- >---$(MAKE) -C src/tools distclean
- >---$(MAKE) -C src/main distclean
- .PHONY : all clean distclean tags help
- # A Makefile to generate archive file
- # Copyright (C) 2014 shallnew \at 163 \dot com
- CFLAGS += -g -Wall -Werror -O2
- CPPFLAGS += -I. -I./inc -I../../include
- # SRC_OBJ = $(patsubst %.c, %.o, $(wildcard *.c))
- SRC_FILES = $(wildcard src/*.c)
- SRC_OBJ = $(SRC_FILES:.c=.o)
- SRC_LIB = libtools.a
- all : $(SRC_LIB)
- $(SRC_LIB) : $(SRC_OBJ)
- >---$(AR) rcs [email protected] $^
- >---cp [email protected] ../../libs
- obj : $(SRC_OBJ)
- # clean target
- clean:
- >---$(RM) $(SRC_OBJ) $(SRC_LIB)
- distclean:
- >---$(RM) $(SRC_OBJ) $(SRC_LIB) tags *~
- .PHONY : all obj clean disclean
- # A Makefile to generate executive file
- # Copyright (C) 2014 shallnew \at 163 \dot com
- CFLAGS += -g -Wall -Werror -O2
- CPPFLAGS += -I. -I./inc -I../../include
- LDFLAGS += -lpthread -L../../libs -ltools -lipc
- # SRC_OBJ = $(patsubst %.c, %.o, $(wildcard *.c))
- SRC_FILES = $(wildcard src/*.c)
- SRC_OBJ = $(SRC_FILES:.c=.o)
- SRC_BIN = target_bin
- all : $(SRC_BIN)
- $(SRC_BIN) : $(SRC_OBJ)
- >---$(CC) -o [email protected] $^ $(LDFLAGS)
- obj : $(SRC_OBJ)
- # clean target
- clean:
- >---$(RM) $(SRC_OBJ) $(SRC_BIN) $(SRC_BIN).exe
- distclean:
- >---$(RM) $(SRC_OBJ) $(SRC_BIN) $(SRC_BIN).exe tags*~
- .PHONY : all obj clean disclean
最後在頂層執行:
- # make clean
- make -C src/ipc clean
- make[1]: Entering directory`/home/Myprojects/example_make/version-3.0/src/ipc'
- rm -f src/ipc.o libipc.a
- make[1]: Leaving directory`/home/Myprojects/example_make/version-3.0/src/ipc'
- make -C src/tools clean
- make[1]: Entering directory `/home/Myprojects/example_make/version-3.0/src/tools'
- rm -f src/base64.o src/md5.o src/tools.o libtools.a
- make[1]: Leaving directory`/home/Myprojects/example_make/version-3.0/src/tools'
- make -C src/main clean
- make[1]: Entering directory`/home/Myprojects/example_make/version-3.0/src/main'
- rm -f src/main.o target_bin target_bin.exe
- make[1]: Leaving directory`/home/Myprojects/example_make/version-3.0/src/main'
- # make
- make -C src/ipc
- make[1]: Entering directory`/home/Myprojects/example_make/version-3.0/src/ipc'
- cc -g -Wall -Werror -O2 -I. -I./inc-I../../include -c -o src/ipc.osrc/ipc.c
- ar rcs libipc.a src/ipc.o
- cp libipc.a ../../libs
- make[1]: Leaving directory `/home/Myprojects/example_make/version-3.0/src/ipc'
- make -C src/tools
- make[1]: Entering directory`/home/Myprojects/example_make/version-3.0/src/tools'
- cc -g -Wall -Werror -O2 -I. -I./inc-I../../include -c -o src/base64.osrc/base64.c
- cc -g -Wall -Werror -O2 -I. -I./inc -I../../include -c -o src/md5.o src/md5.c
- cc -g -Wall -Werror -O2 -I. -I./inc-I../../include -c -o src/tools.osrc/tools.c
- ar rcs libtools.a src/base64.o src/md5.o src/tools.o
- cp libtools.a ../../libs
- make[1]: Leaving directory`/home/Myprojects/example_make/version-3.0/src/tools'
- make -C src/main
- make[1]: Entering directory`/home/Myprojects/example_make/version-3.0/src/main'
- cc -g -Wall -Werror -O2 -I. -I./inc-I../../include -c -o src/main.osrc/main.c
- cc -o target_bin src/main.o -lpthread -L../../libs -ltools-lipc
- make[1]: Leaving directory`/home/Myprojects/example_make/version-3.0/src/main'
- #
最後生成了可執行程式檔案。這樣的話一個工程的各個模組就變得獨立出來了,不但原始碼分開了,而且各自有各自的Makefile,並且各個功能模組是可獨立編譯的。
我們發現頂層Makefile還有可以改進的地方,就是在進入下一層目錄是要重複寫多次,如下:
- >---$(MAKE) -C src/ipc
- >---$(MAKE) -C src/tools
- >---$(MAKE) -C src/main
每增加一個目錄都要在多個偽目標裡面加入一行,這樣不夠自動化啊,於是我們想到shell的迴圈語 句,我們可以在每條規則的命令處使用for迴圈。如下:
- DIR = src
- SUBDIRS = $(shell ls $(DIR))
- all :
- >[email protected] subdir in $(SUBDIRS); \
- >---do $(MAKE) -C $(DIR)/$$subdir; \
- >---done
這樣懶人有可以高興很久了。不過還有問題:
上面for迴圈會依次進入系統命令ls列出的目錄,但我們對每個目錄的make順序可能有要求,在該專案當中,main目錄下的Makefile必須最後執行,因為最終的連結需要其他目錄編譯生成的庫檔案,否則會執行失敗。並且在當前的Makefile中,當子目錄執行make出現錯誤時,make不會退出。在最終執行失敗的情況下,我們很難根據錯誤的提示定位出具體是是那個目錄下的Makefile出現錯誤。這給問題定位造成了很大的困難。為了避免這樣的問題,在命令執行錯誤後make退出。
所以將剛才的Makefile修改為如下
- DIR = src
- SUBDIRS = $(shell ls $(DIR))
- all :
- >[email protected] subdir in $(SUBDIRS); \
- >---do $(MAKE) -C $(DIR)/$$subdir || exit 1; \
- >---done
這樣在執行出錯時立馬退出,但這樣還是沒有解決問題,編譯錯誤還是會出現。那怎麼解決呢?
我們可以通過增加規則來限制make執行順序,這樣就要用到偽目標,對每一個模組我們都為他寫一條規則,每個模組名稱是目標,最後需要執行的模組目標又是其他模組的目標,這樣就限制了make順序。在執行到最後需要執行的目標時,發現存在依賴,於是先更新依賴的目標,這樣就不會出錯了。並且這樣的話,我們還可以對指定模組進行編譯,比如我只修改了tools模組,我只想看看我修改的這個模組程式碼是否可以編譯通過,我可以在編譯時這樣:
- # make tools
- make -C src/tools
- make[1]: Entering directory`/home/Myprojects/example_make/version-2.1/src/tools'
- cc -g -Wall -Werror -O2 -I. -I./inc-I../../include -c -o src/base64.o src/base64.c
- cc -g -Wall -Werror -O2 -I. -I./inc-I../../include -c -o src/md5.osrc/md5.c
- cc -g -Wall -Werror -O2 -I. -I./inc-I../../include -c -o src/tools.osrc/tools.c
- ar rcs libtools.a src/base64.o src/md5.o src/tools.o
- cp libtools.a ../../libs
- make[1]: Leaving directory`/home/Myprojects/example_make/version-2.1/src/tools'
- #
我們的頂層Makefile又進化了,也是這一節最終Makefile:
- # Top Makefile for C program
- # Copyright (C) 2014 shallnew \at 163 \dot com
- DIR = src
- MODULES = $(shell ls $(DIR))
- # MODULES = ipc main tools
- all : $(MODULES)
- $(MODULES):
- >---$(MAKE) -C $(DIR)/[email protected]
- main:tools ipc
- obj:
-
相關推薦
Makefile巢狀執行
轉自:http://blog.csdn.net/shallnet/article/details/37595465?utm_source=tuicool&utm_medium=referral ====================================
從頭開始寫專案Makefile(五):巢狀執行(轉)
【版權宣告:轉載請保留出處:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】 在大一些的專案裡面,所有原始碼不會只放在同一個目錄,一般各個功能模組的原始碼都是分開的,各自放在各自目錄下,並且標頭檔案
makefile 巢狀
目錄結構: dynamic 和 static 兩個目錄實現加法功能, 分別生成動態庫和靜態庫, main.c 主檔案連結加法功能, 終端命令執行: make dynamic=1 則編譯動態庫
redux-saga generator巢狀執行的阻塞與非阻塞
1.generator呼叫generator 在one中yield另一個generatoranother function*another(params){ // ... } function*one(params,{ call, put }){ // ...
寫了個巢狀執行make
跟我一起寫 Makefile ------------------------------陳皓 #VPATH = BaseRender:shaderUtil:testApp:glad:. PROJECT_PATH = $(shell pwd) OBJSD
巢狀執行MAKE $(MAKE) -C subdir
subsystem: cd subdir && $(MAKE) 其等價於: subs
shell指令碼巢狀執行expect命令
好吧,發現漏了一篇在草稿箱 )^-^( 為避免反覆呼叫,可以巢狀執行 相關命令: spawn:啟動一個程式或程序 send:給程序或程式返回結果 expect:接受程式或程序輸出 inter
迴圈巢狀如何執行和switch break區別
for語句裡巢狀if語句 當for語句裡第一個條件不滿足if語句時,則繼續執行for迴圈,若滿足,執行if語句 例: for(i=0;i<=4;i++) for(j=0;j<=4;j++) if(i!=j) { for(k=0;k<
迴圈巢狀如何執行和switch break區別
for語句裡巢狀if語句 當for語句裡第一個條件不滿足if語句時,則繼續執行for迴圈,若滿足,執行if語句 例: for(i=0;i<=4;i++) for(j=0;j<=4;j++) if(i
JSP中在JS函式中巢狀Java程式碼的執行問題
function exitSystem() { var ok = confirm("您確定要退出該系統嗎?"); if(ok){ <%sess
SQL語句巢狀時的執行順序
1.原語句:SELECT ID,NAME,STATES,(SELECT STATES FROM ITEM WHERE ID=T.ITEM_ID) AS ITEM_END_FLAGFROM RESULT TWHERE 1=12.ITEM表中實際沒有STATES列,但執行時語句
跟我一起寫Makefile(10)--- 變數(巢狀變數+追加變數+overrid+多行變數+環境變數+目標變數+模式變數)
使用變數 ———— 在Makefile中的定義的變數,就像是C/C++語言中的巨集一樣,他代表了一個文字字串,在Makefile中執行的時候其會自動原模原樣地展開在所使用的地方。其與C/C++所不同的是,你可以在Makefile中改變其值。在Makefile中,變數可以
dll巢狀引用缺失會造成執行時異常
在這次例項模仿中,我遇到了一個很煩人的問題,就是我拿到的原始碼能夠正確的執行,得到資料。而我模仿的例項卻在執行中老是會出異常。經過兩三天的糾結,終於在我的一個小demo的測試中發現了這個問題,那就是:有的時候,我們寫程
如何等到巢狀的block執行完後再執行其他程式碼?
現在有一個單例 Manage.h、Manage.m 裡面有你封裝的一個請求伺服器資料的方法。 例如:-(void)manageRequestWithUrl:(NSURL*)urlName handleBlock(void(^)(NSData *data,NSError*
shell巢狀expect執行screen命令
start.sh #!/usr/bin/env bash screen_name1=$"online" screen -dmS $screen_name1 cmd1=$"php pushOnlineN
makefile之巢狀shell命令
參考:http://blog.csdn.net/yusiguyuan/article/details/16951413 在Makefile中寫shell程式碼有點詭異,和不同的shell語法不太一樣,如果不瞭解,看Makefile會莫名其妙。下面總結了一些。 1:盡在Mak
迴圈裡面巢狀一個非同步請求,所有迴圈執行完畢後再返回請求的資料
場景介紹: 使用es6實現爬蟲,先遍歷完列表,然後迴圈列表的根據url去查詢每篇文章的詳細內容,最後將所有爬取完的資料寫入資料庫(只寫一次,避免資料庫頻繁的開啟的關閉,影響效能)。 原始實現方式和痛點分析: var list =["url1","url2","url3",.
黑馬程式設計師————java基礎-----for巢狀迴圈的執行順序
------<a href="http://www.itheima.com" target="blank">Java培訓、Android培訓、iOS培訓、.Net培訓</a>、期待與您交流! ------- 先寫一個for巢狀的小程式,輸出一個矩形,
(實驗)Java一個執行緒用synchronized巢狀鎖多個物件時呼叫wait()只釋放wait函式關聯的所物件還是釋放所有鎖物件
實驗是在JDK1.8下做的。 題目起的比較拗口,其實用程式碼說明起來更簡單,如下所示: public class MultiSynchronizedTest { private static Object lock1 = new Object(); p
巢狀容器 —— 在 Podman 容器內構建並執行 Buildah
開發十年,就只剩下這套架構體系了! >>>