我剛開始學Linux的時候,並沒有用Makefile。寫一個test.c ,然后直接gcc -o -g test test.c。后來文件一多,各種.c .h 文件。原來的方法是沒法編譯的。所以這時候就要靠Makefile。
先寫一個簡單的例子吧。現在有一段代碼
#include<stdio.h> int main(int args,char *argv[]) { printf("hello,world!!"); return 0; }
稍微插一段編譯原理:首先你的.c到Linux可執行文件.elf 要經歷的過程是:.h .c->.i->.o->elf
首先是預編譯:加載頭文件和動態鏈接庫 。然后是匯編,編譯,最后是鏈接
其實是這樣:
gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.s
gcc -c hello.s -o hello.o
現在動手寫一個Makefile 直接vim Makefile
test 是目標文件,而test.c是依賴文件。下面的紅色字體是命令。在Makefile中的命令,必須要以【tab】鍵開始!
想一想,Linux內核成千個.c .h也這樣寫豈不是要累死!!!
如何寫一個比較通用的Makefile呢
先上一個Makefile再慢慢講解吧 !!!
SRC =$(wildcard *.c) OBJS =$(patsubst %.c,%.o,$(SRC)) CC = gcc CFLAGS = -Wall -g LIBS = -lpthread DEFS = INCLUDE = -I ./ TARGET = test $(TARGET):$(OBJS) $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $@ -o $^ $(LIBS) .PHONY:clean clean: rm -rf *.o $(TARGET)
紅色字體是Makefile中的變量。使用變量的方式就是$(變量名) $@表示目標文件 $^表示第一個依賴文件 翻譯一下:
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $@ -o $^ $(LIBS) ==gcc -Wall -g -I ../ test -o test.c -lpthread
-I 表示加入的頭文件即$(INCLUDE) 后面跟文件路徑。 后面的$(LIBS)表示動態庫。注意一下,這只是我起的名字,隨便什么都可以的。
.PHONY表示偽目標
生成clean。clean 執行的是刪除生成的文件。如果當前文件夾沒有clean的文件,其實也可以不用加.PHONY。
wildcard是makefile中的函數,放在這里是取當前文件夾中的所有.c文件。
一點點文字只能大致描述一下。很多地方都沒講到。比如1.已經編譯的一個項目,需要改一點東西,這時候makefile只會重新編譯改了的文件。makefile會自動根據文件改動時間來判斷的。2.在多目錄結構下有多個makefile怎么來編譯。等等。希望對讀者有些幫助!!