hello.h
/* File name: hello.h * c header file */ #ifndef HELLO_H#define HELLO_H #ifdef __cplusplusextern "C" {#endifvoid print_hello();#ifdef __cplusplus}#endif#endif
main.cxx
/* File naem: main.cxx * c++ source file */ #include "hello.h" int main(){print_hello();return 0;}
Makefile
############################################################################# ## Generic Makefile for C/C++ Program## Author: Yanbin Lee# Date : 2017/07/05#============================================================================# The C/C++ program compiler.CC=gccCXX=g++# 編譯器在編譯時間的參數設定,包含標頭檔路徑設定CFLAGS:=-Wall -O2 -gCFLAGS+=-I $(shell pwd)/includeCXXFLAGS:=-Wall -O2 -gCXXFLAGS+=-I $(shell pwd)/include# 庫檔案添加LDFLAGS:=LDFLAGS+=# 指定來源程式存放位置SRCDIRS:=.SRCDIRS+=dir# 設定程式中使用檔案類型SRCEXTS:=.c .cxx# 設定運行程式名PROGRAM:=hello#t1=$(addprefix $(SRCDIRS)/*,$(SRCEXTS))#t2=$(foreach d,$(SRCDIRS),echo $(d))#t3=$(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))#all:#@echo $(t3)SOURCES=$(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))OBJS=$(foreach x,$(SRCEXTS),$(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES)))).PHONY: all clean distclean install%.o: %.c$(CC) -c $(CFLAGS) -o $@ $<%.o: %.cxx$(CXX) -c $(CXXFLAGS) -o $@ $<$(PROGRAM): $(OBJS)ifeq ($(strip $(SRCEXTS)),.c)$(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)else$(CXX) -o $(PROGRAM) $(OBJS) $(LDFLAGS)endifinstall:install -m 755 -D -p $(PROGRAM) ./binclean:rm -f $(shell find -name "*.o")rm -f $(PROGRAM)distclean:rm -f $(shell find -name "*.o")rm -f $(shell find -name "*.d")rm -f $(PROGRAM)all:@echo $(OBJS)
本樣本工程代碼可到此下載:點擊開啟連結
擷取root許可權,輸入make得到可執行檔hello,然後運行:
1. 部分makefile函數
該小節介紹了使用到的部分函數,完整的函數介紹可參考:
【Makefile常用函數總結】http://blog.csdn.net/ustc_dylan/article/details/6963248
filter:過濾函數
sources := foo.c bar.c baz.s ugh.h
$(filter %.c %.s,$(sources))
數傳回值為“foo.c bar.c baz.s”
patsubst:模式替換函數
$(patsubst %.c,%.o,x.c.c bar.c)
#把字串“x.c.c bar.c”中以.c結尾的單詞替換成以.o結尾的字元。函數的返回結果是“x.c.o bar.o”
wildcard:模式比對檔案名稱
在Makefile中,它被展開為已經存在的、使用空格分開的、匹配此模式的所有檔案清單
foreach:迴圈函數
$(foreach VAR,LIST,TEXT)
執行時把“LIST”中使用空格分割的單詞依次取出賦值給變數“VAR”,然後執行“TEXT”運算式
a.o b.o
string:去空格函數,去掉<string>字串中開頭和結尾的Null 字元
$(strip a b c )
把字串“abc”去到開頭和結尾的空格,結果是“abc”。
$(findstring <find>,<in> )
addprefix :加首碼函數
$(addprefix src/,foo bar)傳回值是“src/foosrc/bar”
2. 痛點解釋
本Makefile 中比較難理解的可能是【SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))】這句,單純從文法理解會比較難理解,可逐步拆解
測試1
檔案夾下建立檔案
root@ubuntu:/home/share/task002# ls
hello.c hello.h Makefile mian.cxx
Makefile:
SRCDIRS:=.
SRCEXTS:=.c .cxx
t1=$(addprefix $(SRCDIRS)/*,$(SRCEXTS))
all:
@echo $(t1)
輸出:./hello.c ./mian.cxx(一開始以為輸出的會是./*.c、./*cxx)
測試2
在測試1的基礎上添加一個dir檔案夾
SRCDIRS:=.
SRCDIRS+=dir
t2=$(foreach d,$(SRCDIRS),echo $(d))
all:
@echo $(t2)
輸出:echo . echo dir【注意不是結果不是由all得到的,而是由foreach的規則輸出的】
測試3
在測試2的基礎上添加一個a.c檔案
SRCDIRS:=.
SRCDIRS+=dir
SRCEXTS:=.c .cxx
t3=$(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
all:
@echo $(t3)
輸出:./hello.c ./mian.cxx dir/a.c(單純的去理解很難,還是自己測試一下比較合理)
測試4
同理對OBJS=$(foreach x,$(SRCEXTS),$(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES))))進行處理,同時在dir目錄下建立一個檔案a.o
最終的輸出:./hello.o dir/a.o ./mian.o
3. 注意事項
l 在windows下編輯的時候注意空格、注意Tab鍵、注意分行符號,這些都是坑
l 時間有限,未測試添加動態庫時Makefile檔案是否可用