makefile文件的一些解讀

hit2015spring歡迎關注我的博客晨鳧追風

這篇文章算是一個學習的筆記吧,在很多的程序構建過程中的一些東西

gcc編程的四個步驟

這裏寫圖片描述

命令格式如下

Gcc [選項] 要編譯的文件 [選項] [目標文件]

其中[目標文件]可以缺省,Gcc默認生成可執行的文件名爲:要編譯的文件.out

例子:

# vi hello.c 
#include <stdlib.h>
#include <stdio.h>
void main(void)
{
printf("hello world!\r\n");
}

編譯的命令爲

gcc  hello.c -o hello.exe

輸出的是可執行文件 hello.exe

預處理

GccE hello.co hello.i

主要處理#include和#define

#include包含進來的.h文件插入到#include所在的位置
把源程序中使用到的#define定義,用實際定義的字符串代替

上面命令中輸出的是.i文件,該文件是經過預處理的C源程序。這個文件是可以查看的文本文件

編譯

首先檢查代碼規範,是否有語法錯誤
把代碼翻譯成彙編語言

該階段的命令如下,它也可以接受.c後綴的文件

gcc -S hello.i -o hello.s

輸出的是.s後綴名的文件,可以查看的文本文件

彙編

這個階段是把上面的彙編程序翻譯成二進制的機器指令文件

這個階段接受的是.c或者.i或者.s文件都是沒有問題的

命令行如下,它可以接受.c或者.i或者.s

Gccc hello.so hello.o

生成的是二進制文件,需要反彙編器GDB幫助才能讀懂

鏈接

這裏涉及到兩種函數庫:

靜態庫:編譯鏈接時,把庫代碼全部加入到可執行文件中去,生成的文件比較大,運行時不在需要庫文件,後綴名一般爲.lib(win).a(Linux)
動態庫:在編譯鏈接時並沒有把庫文件代碼,加入到可執行文件中,而是在程序執行時,由運行時的鏈接文件加載庫,節省系統開銷,後綴一般爲.dll(win).so(linux)

這裏生成庫的方法爲:

生成靜態庫的方法:  
    ar cr libxxx.a file1.o file2.o  
就是把file1.o和file2.o打包生成libxxx.a靜態庫  
使用的時候  
    gcc test.c -L/path -lxxx -o test  

動態庫的話:  
    gcc -fPIC -shared file1.c -o libxxx.so  
也可以分成兩部來寫:  
    gcc -fPIC file1.c -c //這一步生成file1.o  
    gcc -shared file1.o -o libtest.so 

在運行程序時,需要在環境變量中指定動態庫的位置,這裏舉例在Linux中的配置

export LD_LIBRARY_PATH=path

這裏需要說明一個情況:

庫中有同名的動態庫和靜態庫文件時,系統會優先選擇鏈接動態庫,如果想要指定用靜態庫,則在編譯的時候加入編譯選項 -static,就會找到靜態庫。

靜態庫鏈接時的搜索路徑順序

1 ld會去找GCC命令中的參數-L
2 再找gcc的環境變量LIBRARY_PATH
3 再找內定目錄 /lib /usr/lib /usr/local/lib 這是當初compile gcc時寫在程序內的

動態庫鏈接執行時的搜索路徑順序

1 編譯目標代碼時指定的動態庫搜索路徑
2 環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑
3 配置文件/etc/ld.so.conf中指定的動態庫搜索路徑
4 默認的動態庫搜索路徑/lib
5 默認的動態庫搜索路徑/usr/lib

於是這個階段的命令如下

Gcc hello.o –o hello

生成可執行文件 hello
上面是用一個個命令行來對一個簡單的程序進行生產的過程,然而很多的工程需要很多的代碼,然後就有一個叫make的工具來管理這些文件。

Makefile文件的一些知識

make工具是根據Makefile文件來對編譯過程建立一個描述數據庫,這個數據庫記錄了所有各個文件之間的相互關係,以及它們的的關係描述,當其中一個文件修改時,他通過比較前後兩個文件修改的時間來決定是不是需要重新編譯。


1 所有的文件都沒有被編譯過,則對各個C源文件進行編譯鏈接,生成可執行程序
2 每一個在上次執行make之後修改過的C源代碼文件,在本次執行make時會被重新編譯
3 頭文件在上一次執行make之後被修改。則所有的包含這個頭文件的C源文件在本次執行Make時會被重新編譯

這些文件重新編譯生成中間文件.o文件,這些.o文件重新連接,就能形成可執行文件

makefile簡單規則:

  target ...:prerequisites .......
  command
  ...
  ....

target是一個目標文件,

1 可以是Object File
2 也可以是可執行文件
3 標籤

prerequisites

是生成這個target所需要的文件或者目標

command 是

make需要執行的命令

target 這個目標文件依賴於prerequisites這些文件,生成的規則在command裏面,如果prerequisites裏面有至少一個文件的時間比target要新的話,那就會執行command命令

這個command命令是以一個Tab鍵作爲開頭

make的工作方式:

這裏舉個例子

  edit : main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o 
cc -o edit main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o 

main.o : main.c defs.h 
cc -c main.c 
kbd.o : kbd.c defs.h command.h 
cc -c kbd.c 
command.o : command.c defs.h command.h 
cc -c command.c 
display.o : display.c defs.h buffer.h 
cc -c display.c 
insert.o : insert.c defs.h buffer.h 
cc -c insert.c 
search.o : search.c defs.h buffer.h 
cc -c search.c 
files.o : files.c defs.h buffer.h command.h 
cc -c files.c 
utils.o : utils.c defs.h 
cc -c utils.c 
clean : 
rm edit main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o

輸入make命令

“`
1 make會在當前目錄下找到名字叫Mkaefile或者makefile的文件

2 如果找到了,它會找文件中的第一個目標文件,並把它(上面的edit)作爲最終的目標文件

3 如果edit不存在或者後面所依賴的.o文件比它要新,就會執行後面所定義的命令來生成這個edit文件

4 如果edit所依賴的.o文件也存在,那麼make會在當前文件中找目標爲.o文件的依賴性,如果找到了,就根據規則生成.o文件

“`
就像是剝洋蔥一樣,一層套着一層,直到最後的c代碼文件和H文件,最後編譯吃第一個目標文件

make只是找文件之間的依賴關係,像clean這樣的,沒有被目標文件關聯或者間接關聯的,那麼它後面的命令將不會被自動執行,但是可以用make指令顯式的要求執行它 make clean

當然 clean是放在最後的,這是一個不成文的規定吧

當然還有很多的編譯選項沒有說明,會再接着學習記錄

福利答謝大家!

感謝您閱讀本篇文章,對此特別發放一個無門檻的現金紅包,打開支付寶掃碼領取,可以領到錢的哦!
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章