我的Makefil

1. Makefile-exe

CC:=gcc
CXX:=g++
RM:=rm -rf

OUTDIR:=$(EXEDIR)
EXENAME:=$(PROJNAME)
EXESRCS:=$(COMPILE_FILES)
CFLAGS:=$(COMPILE_FLAGS)
LDFLAGS:=$(LINK_FLAGS)
DEBUG:=Y

EXEOBJS:=$(patsubst %.cpp,%.oo,$(EXESRCS))
EXEOBJS:=$(patsubst %.c,%.o,$(EXEOBJS))
EXEDEPS:=$(patsubst %.cpp,%.dd,$(EXESRCS))
EXEDEPS:=$(patsubst %.c,%.d,$(EXEDEPS))

ifeq ($(DEBUG),Y)
CFLAGS+=-O0 -ggdb3
else
CFLAGS+=-O3 -fomit-frame-pointer
endif

.PHONY:all clean
all:$(OUTDIR).dir $(OUTDIR)/$(EXENAME)
 
$(OUTDIR)/$(EXENAME):$(EXEDEPS) $(EXEOBJS) 
	$(CXX)  $(EXEOBJS) -o $@ $(LDFLAGS)

-include $(EXEDEPS)
%.d: %.c
	@$(CC) -MM $(CFLAGS) $< | sed -e 's,^[0-9a-zA-Z._-]*: \([0-9a-zA-Z._-]*/\),\1&,' -e 's,^\([0-9a-zA-Z._-/]*\)\.o:,\1.o \1.d:,' > $@
%.dd: %.cpp
	@$(CXX) -MM $(CFLAGS) $< | sed -e 's,^[0-9a-zA-Z._-]*: \([0-9a-zA-Z._-]*/\),\1&,' -e 's,^\([0-9a-zA-Z._-/]*\)\.o:,\1.oo \1.dd:,' > $@
%.o:%.c
	$(CC) $(CFLAGS)  -c $< -o $@
%.oo:%.cpp
	$(CXX) $(CFLAGS)  -c $< -o $@
%.dir:
	@echo "Checking directory $*"
	@if [ ! -d $* ]; then \
		echo "Making directory $*"; \
		mkdir -p $* ;\
	fi;

clean:
	-$(RM) $(EXEOBJS) $(EXEDEPS) $(OUTDIR)/$(EXENAME)

2. Makefile-so

CC:=gcc
CXX:=g++
LD:=ld
RM:=rm -rf

OUTDIR:=$(LIBDIR)
LIBNAME:=lib$(PROJNAME)
LIBSRCS:=$(COMPILE_FILES)
CFLAGS:=$(COMPILE_FLAGS)
LDFLAGS:=$(LINK_FLAGS)
DEBUG:=Y

LIBOBJS:=$(patsubst %.cpp,%.oo,$(LIBSRCS))
LIBOBJS:=$(patsubst %.c,%.o,$(LIBOBJS))
LIBDEPS:=$(patsubst %.cpp,%.dd,$(LIBSRCS))
LIBDEPS:=$(patsubst %.c,%.d,$(LIBDEPS))
CFLAGS+=-I. -Wall

ifeq ($(DEBUG),Y)
CFLAGS+=-O0 -ggdb3
else
CFLAGS+=-O3 -fomit-frame-pointer
endif

.PHONY:all clean
all:$(OUTDIR).dir $(OUTDIR)/$(LIBNAME)
 
$(OUTDIR)/$(LIBNAME):$(LIBDEPS) $(LIBOBJS)
	$(CC) -shared -fPIC  $(LIBOBJS) -o [email protected] $(LDFLAGS)

-include $(LIBDEPS)
%.d: %.c
	@$(CC) -MM $(CFLAGS) $< | sed -e 's,^[0-9a-zA-Z._-]*: \([0-9a-zA-Z._-]*/\),\1&,' -e 's,^\([0-9a-zA-Z._-/]*\)\.o:,\1.o \1.d:,' > $@
%.dd: %.cpp
	@$(CXX) -MM $(CFLAGS) $< | sed -e 's,^[0-9a-zA-Z._-]*: \([0-9a-zA-Z._-]*/\),\1&,' -e 's,^\([0-9a-zA-Z._-/]*\)\.o:,\1.oo \1.dd:,' > $@
%.oo:%.cpp
	$(CXX) $(CFLAGS) $(DEFS) -c $< -o $@	
%.o:%.c
	$(CC) $(CFLAGS) $(DEFS) -c $< -o $@
%.dir:
	@echo "Checking directory $*"
	@if [ ! -d $* ]; then \
		echo "Making directory $*"; \
		mkdir -p $* ;\
	fi;

clean:
	-$(RM) $(OUTDIR)/* $(LIBOBJS) $(LIBDEPS)

3. Makefile-src

PROJNAME:=engine
LIBDIR:=../lib
LINK_FLAGS:=-lSDL -lGL -lGLU -lGLEW -lstdc++ -lMagick++ -lassimp
COMPILE_FLAGS:=-I/usr/include/SDL -I/usr/include/ImageMagick -I/usr/local/include/assimp -I../include -D_GNU_SOURCE=1 -D_REENTRANT -DARCH_X86=1 -Wno-int-to-pointer-cast
COMPILE_FILES:= util/Array.c\
	        util/Timer.c
include ../Makefile-so

4. 編譯靜態庫

如果是編譯靜態庫,使用下面的命令進行編譯:

AR:=ar

RANLIB:=ranlib

(OUTDIR)/$(LIBNAME):$(DEPS) $(OBJS)
$(AR) cr $@ (OBJS)
        $(RANLIB) $@

基本上上面的用法就足夠了,多多使用就好。

5. gcc 選項

-I :頭文件位置(編譯時用)
-l: 引用的庫的名稱(鏈接時用)

-L:引用的庫的位置(鏈接時用)

-Wall: 打開所有警告

-Wno-xxx:關閉某個警告

-O0 -ggdb3:沒有編譯優化,加入gdb調試信息

-O3:最優化編譯優化

-g或者-ggdb3生成調試信息

-D:定義的預編譯的變量名

-M:生成文件關聯的信息

-MM:同上,但是去除#include <...h>這樣的關聯信息

CFLAGS LDFLAGS:gcc內部定義的變量
自動化變量:

$@ 目標文件 $^ 所有依賴文件  $< 第一個依賴文件

6. 依賴文件

生成依賴.d文件:

需要生成這個文件的原因:有時候如果頭文件發生了改動,但是.c文件沒有發生改動,如果單純的依賴.c文件會導致頭文件的更新無法反映到可執行程序中去。

應採用下面這種方式來實現:

$EXENAME: $DEPENDENCE $OBJS

%.d:%.c

$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$

其中$@.$$$$表示以.d+進程號作爲一個臨時文件($$表示進程號,至於爲什麼要用4個,這是因爲首次要經過shell的處理,shell中$$表示$);

sed使用的是替換功能 sed 's/{old_string}/{new_string}/g' 或者採用逗號作爲分隔符sed 's,{old_string},{new_string},g', 分割符自己定義,只要和匹配模式裏面的字符不衝突就好

其中的匹配用到了正則表達式(正則表達式確實很強大,在grep, awk中均用到了,grep用於找到行,awk用於找到列)

這個是GNU Makefile中文手冊上的用法,比較好理解(一個sed命令,兩個重定向);

上面的腳本中是老師的用法:

  @$(CC) -MM $(CFLAGS) $< | sed -e 's,^[0-9a-zA-Z._-]*: \([0-9a-zA-Z._-]*/\),\1&,' -e 's,^\([0-9a-zA-Z._-/]*\)\.o:,\1.o \1.d:,' > $@

分兩步進行:第一步,先選出字符串中符合 XXX: aaa bbb格式的字符串;第二步,替換,將xxx.o替換成xxx.o xxx.d

7. Makefile內置函數

wildcard: 通配符 ,用法 $(wildcard *.c),獲取當前目錄下的所有的.c文件
patsubst: 模式替換,用法$(patsubst %.cpp %.oo $(SRCFILES)),將SRCFILES中所有的cpp換成.oo
ar xxxx.a a.o b.o :將a.o b.o加入到靜態庫中
ranlib xxxx.a :爲庫文件創建索引表
(ar t xxx.a:顯示庫中有哪些目標文件, nm -s xxx.a 顯示索引表)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章