main3.capp
1 #include <stdio.h> 2 #include "static_lib.h" 3 #include "fun.h" 4 5 int main(void){ 6 int a=2,b=3; 7 printf("add:%d sub:%d mul:%d div:%d\n",add(a,b),sub(a,b),mul(a,b),div(a,b)); 8 fun1(); 9 return 0; 10 }
static_lib.h和函數
1 extern int add(int a,int b); 2 extern int sub(int a,int b); 3 extern int mul(int a,int b); 4 extern int div(int a,int b);
static_lib.cui
1 int add(int a,int b){ 2 return a + b; 3 } 4 5 int sub(int a,int b){ 6 return a - b; 7 } 8 9 int mul(int a,int b){ 10 return a * b; 11 } 12 13 int div(int a,int b){ 14 return a / b; 15 }
fun.h和spa
1 extern void fun1();
fun.c3d
1 #include <stdio.h> 2 void fun1(){ 3 printf("fun1 ..."); 4 }
其中stati_lib.c中的文件編譯成靜態庫code
按照正常的編譯方法,這個程序能夠按以下順序編譯blog
可是每次改了源代碼以後都這樣子編譯顯然是不明智的,因此須要編寫一個Makefile規則文件get
Makefile的規則爲源碼
其中target是目標文件或者動做it
prerequisites是生成目標依賴的文件
command是規則執行的命令,若是命令與依賴規則在一行,則以';'分割,若是在另外一行,則以tab開頭
編寫一個最簡單的Makefile編譯這些源碼
1 app3 : static_lib.a fun.o 2 gcc main3.c static_lib.a fun.o -o app3 3 4 fun.o : 5 gcc -c fun.c 6 static_lib.o : 7 gcc -c static_lib.c 8 9 static_lib.a : static_lib.o 10 ar rcs static_lib.a static_lib.o 11 12 clean : 13 rm static_lib.a static_lib.o fun.o app3
執行make clean能夠將原來的清理掉
執行make會從新編譯源碼
這樣當咱們修改源代碼以後就能夠簡單的編譯源碼了
但上面的Makefile顯然不夠簡潔,咱們能夠利用一些make的隱式規則,簡寫makefile,這些隱含規則能夠經過 make -p 指令查看。
1 app3 : static_lib.a fun.o main3.o 2 gcc main3.o fun.o static_lib.a -o app3 3 4 static_lib.a : static_lib.o # 隱含會尋找*.c文件編譯成*.o文件 5 ar rcs static_lib.a static_lib.o 6 7 clean : 8 rm *.a *.o app3
執行make能夠看到依然可以編譯成功
其中cc是一個符號連接
還能夠進一步使用一些變量,進一步提升Makefile的可維護性
1 CC = gcc 2 OBJS = main3.o static_lib.a fun.o 3 GEN_OPTS = -o 4 app3 : $(OBJS) 5 $(CC) $(OBJS) $(GEN_OPTS) app3 6 7 static_lib.a : static_lib.o # 隱含會尋找*.c文件編譯成*.o文件 8 ar rcs static_lib.a static_lib.o 9 10 clean : 11 rm *.a *.o app3
執行make
並且能夠看到 1,2,4行的gcc存在縮進,說明隱含規則也使用指明的CC變量編譯。
進一步的,咱們可使用一些自動化的變量。
1 CC = gcc 2 OBJS = main3.o static_lib.a fun.o 3 GEN_OPTS = -o 4 app3 : $(OBJS) 5 $(CC) $(OBJS) $(GEN_OPTS) app3 6 7 static_lib.a : static_lib.o # 隱含會尋找*.c文件編譯成*.o文件 8 ar rcs $@ $^ 9 10 clean : 11 rm *.a *.o app3
其中自動化變量 $@表示規則中的目標文件集,$^表示依賴集,這個Makefile執行以後也能獲得想要的結果
最後結合前面的變量,再結合函數,等寫一個更完善的makefile,能夠作到增長了新的c文件或h文件不須要修改Makefile文件,再次以前,首先將static_lib.* 移動到lib目錄下,將其他源碼文件移動到src目錄。
並修改main3.c的include爲 ../lib/static_lib.h,修改Makefile文件以下
1 CC = gcc 2 SRC = ./src 3 LIB = ./lib 4 OBJS = $(patsubst %.c, %.o, $(wildcard $(SRC)/*.c)) 5 LIBS = $(patsubst %.c, %.a, $(wildcard $(LIB)/*.c)) 6 GEN_OPTS = -o 7 app3 : $(OBJS) $(LIBS) 8 $(CC) $(OBJS) $(LIBS) $(GEN_OPTS) app3 9 @echo "gen done" 10 # 將lib目錄下的c文件編譯成a庫文件 11 $(LIBS) : $(patsubst %.c, %.o, $(wildcard $(LIB)/*.c)) 12 ar rcs $@ $^ 13 14 clean : 15 -rm $(SRC)/*.o $(LIB)/*.a app3 16 @echo clean done.
其中patsubst是一個函數,替換通配符,wildcard函數擴展通配符,展開目錄下的全部匹配文件。
命令前面加'-'的話表示即使出錯也繼續執行。