GCC和程序編譯過程
GCC是linux下面的編譯器,最初名稱是GNU C Compiler (GCC) ,后面逐漸可以編譯各種語言,因此GNU Compiler Collection (GCC)。
他是自由軟件大神Richard Stallman發起的。目前GCC系列在win和unix環境都可以使用,win中可以使用mingw或者cygwin
使用GCC,就要知道它的各種編譯選項,而在這之前我們首先要知道程序的編譯過程:
預處理,一般是包含頭文件,展開宏定義等,生成.i格式輸出文件
編譯,將預處理后的文件編譯生成匯編代碼
匯編,將匯編代碼生成機器碼
鏈接,將多個不同的目標文件以及動態庫和靜態庫路徑鏈接生成最終的可執行文件
對於一個簡單的文件,上面的流程gcc命令如下:
程序的運行過程:
預處理->編譯->匯編->鏈接
預處理 gcc -E hello.c -o hello.i
編譯,生成匯編代碼 gcc -S hello.i -o hello.s
匯編,生成.o匯編文件 gcc -c hello.s -o hello.o
鏈接生成可執行文件 gcc hello.o -o hello
GCC的其他常用選項包括如下:
gcc選項:
-o 輸出可執行文件
-c 編譯生成目標文件
-g 輸出調試信息
-O2 編譯器優化級別 1-3
-Wall 警告選項 輸出警告信息
-l 緊接着鏈接庫 lpthread
-L 指定鏈接庫的路徑
-I 頭文件路徑
-shared 編譯成動態鏈接庫
注意-c只是生成目標文件,而-o直接回生成可執行文件
頭文件與鏈接庫文件
在編譯程序的時候,我們通常需要關注的是頭文件以及鏈接庫文件
頭文件.h開頭,一般會有各種函數和結構的聲明,庫文件包括動態鏈接庫與靜態鏈接庫,linux下分別是.so 和 .a
Makefile的作用和介紹
其實GCC編譯器完全可以滿足編譯C以及CPP程序的需求,那么為什么還需要makefile呢。
Makefile的作用是將GCC編譯的過程規則化,包括編譯順序,依賴關系,第二次進行增量編譯,編譯后的一些相關操作等。
Makefile會定義一對規則和依賴關系,規則定義如下:
名稱: 依賴項1 依賴項2 .....
[tab] 一系列命令
一些選項和宏定義:
# 注釋
\ 換行
macro宏定義
CC 表示編譯器的名稱
CFLAGS表示編譯器選項
LDLIBS表示鏈接庫選項
$@ 代指目標文件
$<第一個依賴文件
$^所有依賴文件
$?所有的比目標文件更新的依賴文件
$+和$^類似,但是可以包含重復
VPATH = src include 從src 和 include中尋找依賴項
vpath %.c src 從src找.c文件
vpath %.h include 從include找.h文件
%.o:%.c #%表示文件匹配
相關examples:
#(1)
.c.o: # .c.o:表示所有的.o都與其對應的.c依賴
gcc -c $< # 表示編譯所有的.c依賴項
#(2)
#main依賴於 mytool1 和 mytools2
main:main.o mytools1.o mytools2.o
gcc -o $@ $^
.c.o:
gcc -c $< -l.;
#(3)
LINK_TARGET = test_me.exe
OBJS = \
Test1.o \
Test2.o \
Main.o
REBUILDABLES = $(OBJS) $(LINK_TARGET)
clean :
rm -f $(REBUILDABLES)
echo Clean done
all : $(LINK_TARGET)
echo All done
$(LINK_TARGET) : $(OBJS)
g++ -g -o $@ $^
%.o : %.cpp
g++ -g -o $@ -c $<
Main.o : Main.h Test1.h Test2.h
Test1.o : Test1.h Test2.h
Test2.o : Test2.h
# %.dep : %.cpp
# g++ -M $(FLAGS) $< > $@
# include $(OBJS:.o=.dep)