//test.c:
#include <stdio.h>
int main(void)
{
printf("hello world!");
return 0;
}
======================================
一、
1. 編譯過程:預處理(processing)-》編譯(compilation)-》匯編(assembly)->Linking
2. 預處理:
gcc -E test.c -o test.i / gcc -E test.c
預處理的結果就是將stdio.h文件中的內容插入到test.c中
3.編譯為匯編代碼:
gcc -S test.i -o test.s
-S選項表示生成匯編代碼, -o表示輸出匯編代碼文件。
4. 匯編:
gcc -C test.s -o test.o
匯編器將匯編代碼編譯成目標文件
5. 鏈接:
gcc test.o -o test
二、
1.對多個文件進行編譯:
gcc test1.c test2.c -o test
2.檢錯
gcc -pedantic illcode.c -o illcode
-pedantic 幫助程序員發現不符合ansi/iso標准代碼。
-Wall 使gcc產生盡可能多的警告信號
-Werror會在警告的地方停止編譯,迫使程序員對自己代碼進行修改
三、庫文件的鏈接:
函數庫是由一些頭文件(.h)和庫文件(.so, .lib, .dll)的集合。 LINUX默認將頭文件放在/usr/include/, 庫文件放在/usr/lib/; 如果我們要用的庫不在這些目錄下,所以在gcc編譯的時候必須用自己的辦法來查找所需要的頭文件和庫文件。
例: test.c鏈接mysql,我們要下載mysql的庫——MySQL Connectors, 下下來以后由個include的文件夾, 里面包含頭文件, 還有一個lib的文件夾,里面包含二進制so文件libmysqlclient.so,其中include的路徑是/usr/dev/mysql/include, lib的文件夾是/usr/dev/mysql/lib
1. 編譯成目標文件:
gcc -c -I /usr/dev/mysql/include test.c -o test.o
2. 鏈接:最后我們把所有的目標文件鏈接成可執行文件。
gcc -L /usr/dev/mysql/lib -lmysqlclient test.o -o test
linux下動態鏈接庫用so結尾,靜態鏈接庫由a結尾。
3.強制鏈接時使用靜態鏈接庫:
加-static
gcc -L /usr/dev/mysql/lib -static -lmysqlclient test.o -o test
靜態庫搜索順序
(1). ld 會去找gcc命令中參數-L
(2)再找gcc環境變量library_PATH
(3)再找內定目錄/lib, /usr/lib, /usr/local/lib
動態鏈接搜索順序:
(1)編譯目標代碼時候指定的搜索路徑
(2)環境變量LD_LIBRARY_PATH
(3)配置文件/etc/ld.so.con
(4)/lib, /usr/lib
GDB調試:
1. gcc -g main.c -o main
在用gcc時候,加上-g表示在生成的目標文件中加入源代碼信息以便調試
2. l, list 從第一行開始列出源代碼
3. start, 開始執行程序,第一行break
4. n, next下一行
5. s, step進入函數
6. bt, backtrace查看函數棧
7. i locals, 用info命令查看局部變量
8. f 1, 到棧幀1
9. p sum, print出sum的值
10. finish, 運行到返回點——如果是從s進來的函數
11. set var sum=0, 調試過程中給變量sum賦值
12. p result[2]=33, 用p賦值
13. display sum, 每次程序停止的時候顯示sum的值
14. b, break當前的循環
15. b 9, 在第9行設置斷點
16. c, 連續運行continue
17. i breakpoints, 查看所有斷點
18. delete breakpoint 2, 刪除斷點2
19. disable breakpoint 2 , 禁用斷點2
20. enable breakpoint 2 , 啟用
21. break 9 if sum!=0 , 當滿足條件時候斷點激活
22. r , 從頭開始執行run
Makefile基礎:
1. Makefile 是由一組rule組成, 每條rule信息如下:
target ...: prerequistites ...
<tab>command1
<tab>command2
例:
main: main.o stack.o maze.o
gcc main.o stack.o maze.o -o main
只要有一個prerequisities更新了,目標也會被更新,就是執行command
2. clean規則
用於清除編譯產生的二進制文件,保留源文件:
clean:
@echo "cleaning project"
-rm main *.o
@echo "clean completed"
如果命令前加@則不顯示命令本身,只顯示結果。 如果加-表示即使命令出錯也不會停止。 通常rm或者mkdir前面要加-,因為可能沒有這個文件,或者已經有了這個文件。
如果存在有文件名字就叫做clean,則會出錯,那么就要添加一行,將clean關鍵字申明成偽目標
.PHONY:clean
3. 4個規則關鍵字:
install:將可執行文件、配置文件、docs分別拷貝到不同安裝目錄
all:執行主要編譯工作,通常用作缺省目標
clean:刪除編譯生成的二進制文件
distclean:不僅刪除二進制文件,還刪除其他的,只留下源文件。
4. 隱含規則和模式規則:
其中有一條
%.o: %.c
$(compile.c) $(output_option) $<
$@為規則中的target, $<為規則中的第一個條件,上面那句相當於 cc -c $@ $<
進而相當於所有符合這樣的依賴關系:
main.o:main.h statk.h maze.h
可以隱含
main.o: main.c
cc -c o main.o main.c
5. 變量:
main.o: main.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
CC = gcc
CFLAGS = -o -g
CPPFLAGS = -Iinclude
:=, 立即賦值
?=, 如果沒有賦過值才進行賦值
+=, 追加賦值
$^, 表示將所有條件組成的列表
$?, 表示所有比目標新的條件組成的列表
6. 自動處理依賴關系:
例:
all: main
main: main.o stack.o maze.o
gcc $^ -o $@
clean:
-rm main *.o
.PHONY: clean
sources = main.c stack.c maze.c
include $(souces: .c = .d)
%.d: %.c
set -e; rm -f $@;\
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$;\ # $$$$相當於兩個$ , 表示進程
....略...