轉自:http://www.linuxidc.com/Linux/2017-01/139702.htmlinux
最近寫了一個遞歸Makefile,目的是既能夠實現子模塊的單獨編譯,也能夠不作任何修改就和整個程序的總體進行無縫銜接的編譯。具體的思路是藉助第三方文件,將子模塊編譯好的.o文件的路徑自動寫到config.mk文件中,在總控Makfile中只須要include這個config.mk就能夠。單個模塊的編譯只須要cd到相應目錄就能夠進行本模塊的單獨編譯,整個程序的編譯也只須要cd到頂層目錄,分別執行make config
,make
,make install
就能夠進行編譯和安裝。下面這個就是頂層Makefilesql
CROSS_COMPILE=
#CC=/opt/arm-cross-compile/arm-2010.09/bin/arm-none-linux-gnueabi-gcc #CC=gcc CC=arm-linux-gnueabi-gcc D=-DDEBUG CFLAGS= -g -O3 $(D) export CC CFLAGS INCLUDE_DIR = $(shell cd ./common/include/; pwd) SUB_DIR= ./entry/ \ ./sqlite/ \ NFS_DIR:=~/nfs CORE_NAME = core $(shell touch config.mk) include ./config.mk all:$(OBJS) $(CC) $(CFLAGS) $^ -lpthread -L/home/jiang/nfs/usr/lib/ -lsqlite3 -o $(CORE_NAME) config: @echo "OBJS+=\\" > config.mk @for dir in $(SUB_DIR); \ do \ echo "\n"; \ $(MAKE) -C $$dir ; \ echo "\n"; \ done clean: $(RM) ./config.mk @for dir in $(SUB_DIR); \ do \ echo "\n"; \ $(MAKE) -C $$dir clean; \ echo "\n"; \ done install: cp $(CORE_NAME) $(NFS_DIR)
下面這個就是每個子模塊的Makfile,會把編譯成功的.o文件路徑添加到config.mk中shell
CUR_DIR=$(shell pwd)
OBJ_DIR:=$(CUR_DIR)/obj INCLUDE_DIR= -I ./include -I ../common/include SRC=$(wildcard ./src/*.c) all:$(SRC) $(CC) $(CFLAGS) $(INCLUDE_DIR) -c $^ mv ./*.o $(OBJ_DIR) echo "${OBJ_DIR}/*.o \\" >> ../config.mk echo "\033[44;37m $(notdir $(CUR_DIR)) done \033[0m" clean: $(RM) $(OBJ_DIR)/*
下面就是config.mk的內容,會在頂層目錄中執行make config以後自動生成ruby
OBJS+=\
/home/jiang/Documents/Documents/IntellStorage/A9_main/A9_core/entry/obj/*.o \ /home/jiang/Documents/Documents/IntellStorage/A9_main/A9_core/sqlite/obj/*.o \
爲了使一個頭文件的實例在整個工程中只有一份,對於接口文件,約定一概以inter_開頭進行命名而且放置在本身的include目錄中,下面這個腳本的做用就是掃描指定的子模塊的include目錄,將其中的inter_*頭文件在entry模塊的include中自動生成同名符號連接文件。bash
#|/bin/bash #掃描指定include的文件,符合inter_*.h的文件會自動在entry/include中建立其符號連接 SHELL_DIR=$(cd $(dirname ${0});pwd) cd ${SHELL_DIR} SUB_INCLUDES="../camera/include ../buzzer/include ../gsm/include ../led/include ../sqlite/include ../zigbee/include" for A_SUB_INCLUDE in ${SUB_INCLUDES} do echo ${A_SUB_INCLUDE} ( cd ${A_SUB_INCLUDE} HEADERS=$(ls ./inter*) for A_HEADER in ${HEADERS} do ln -s ../${A_SUB_INCLUDE}/${A_HEADER} ../../entry/include/${A_HEADER} done ) done