makefile

 main.c, mytool1.h, mytool1.c, mytool2.h, mytool2.c函數

咱們能夠這樣來編譯:學習

gcc -c main.cspa

gcc -c mytool1.c線程

gcc -c mytool2.c調試

gcc -o main main.o mytool1.o mytool2.ocomponent

 

Makefile文件中最重要的是描述文件的依賴關係的說明,其通常的格式爲:對象

target: components文檔

TAB ruleget

 

第一行表示的是依賴關係,第二行是規則。編譯器

例如上面那個Makefile文件的第二行:main: main.o mytool1.o mytool2.o,表示咱們的目標(target)main的依賴對象(components)是main.o mytool1.o mytool2.o

當依賴的對象在目標修改後修改的話,就要去執行規則行所指定的命令。

例如上面那個Makefile文件的第三行:gcc -o main main.o mytool1.o mytool2.o

注意:規則行中的TAB表示那裏是一個TAB 鍵。

 

3. Makefile的經常使用變量

Makefile 有三個很是有用的變量:$@,$^,$<。其意義爲:

$@:目標文件

$^:全部的依賴文件

$<:第一個依賴文件

若是使用上面三個變量,上面那個Makefile文件可簡化爲:

  1. #這是簡化後的Makefile  
  2. main: main.o mytool1.o mytool2.o   
  3.             gcc -o $@ $^  
  4. main.o: main.c mytool1.h mytool2.h  
  5.             gcc -c $<  
  6. mytool1.o: mytool1.c mytool1.h  
  7.             gcc -c $<  
  8. mytool2.o: mytool2.c mytool2.h  
  9.             gcc -c $<  

 

通過簡化後咱們的Makefile是簡單了一點,不過人們有時候還想簡單一點。這裏咱們學習一個Makefile的缺省規則

.c.o:

gcc -c $<

這個規則表示全部的 .o文件都是依賴與相應的.c文件的。例如mytool.o依賴於mytool.c這樣Makefile還能夠變爲:

# 這是再一次簡化後的Makefile

main:main.o mytool1.o mytool2.o

gcc -o $@ $^

.c.o:

gcc -c $<

好了,咱們的Makefile 也差很少了,若是想知道更多的關於Makefile規則能夠查看相應的文檔。

3.程序庫的連接

試着編譯下面這個程序

/* temp.c */

#include

int main(int argc,char **argv)

{

double value;

printf("Value:%f\n",value);

}

這個程序至關簡單,可是當咱們用 gcc -o temp temp.c 編譯時會出現下面所示的錯誤。

/tmp/cc33Kydu.o: In function `main':

/tmp/cc33Kydu.o(.text+0xe): undefined reference to `log'

collect2: ld returned 1 exit status

出現這個錯誤是由於編譯器找不到log的具體實現。雖然咱們包括了正確的頭文件,可是咱們在編譯的時候仍是要鏈接肯定的庫。在Linux下,爲了使用數學 函數,咱們必須和數學庫鏈接,爲此咱們要加入 -lm 選項。 gcc -o temp temp.c -lm這樣纔可以正確的編譯。也許有人要問,前面咱們用printf函數的時候怎麼沒有鏈接庫呢?是這樣的,對於一些經常使用的函數的實現,gcc編譯器會自 動去鏈接一些經常使用庫,這樣咱們就沒有必要本身去指定了。有時候咱們在編譯程序的時候還要指定庫的路徑,這個時候咱們要用到編譯器的 -L選項指定路徑。好比說咱們有一個庫在 /home/hoyt/mylib下,這樣咱們編譯的時候還要加上 -L/home/hoyt/mylib。對於一些標準庫來講,咱們沒有必要指出路徑。只要它們在起缺省庫的路徑下就能夠了。系統的缺省庫的路徑/lib /usr/lib /usr/local/lib 在這三個路徑下面的庫,咱們能夠不指定路徑。

還有一個問題,有時候咱們使用了某個函數,可是咱們不知道庫的名字,這個時候怎麼辦呢?很抱歉,對於這個問題我也不知道答案,我只有一個傻辦法。首先,我 到標準庫路徑下面去找看看有沒有和我用的函數相關的庫,我就這樣找到了線程(thread)函數的庫文件(libpthread.a)。 固然,若是找不到,只有一個笨方法。好比我要找sin這個函數所在的庫。 就只好用 nm -o /lib/*.so|grep sin>~/sin 命令,而後看~/sin文件,到那裏面去找了。在sin文件當中,我會找到這樣的一行libm-2.1.2.so:00009fa0 W sin 這樣我就知道了sin在 libm-2.1.2.so庫裏面,我用 -lm選項就能夠了(去掉前面的lib和後面的版本標誌,就剩下m了因此是 -lm)。 若是你知道怎麼找,請趕快告訴我,我回很是感激的。謝謝!

4.程序的調試

咱們編寫的程序不太可能一次性就會成功的,在咱們的程序當中,會出現許許多多咱們想不到的錯誤,這個時候咱們就要對咱們的程序進行調試了。

最經常使用的調試軟件是gdb.若是你想在圖形界面下調試程序,那麼你如今能夠選擇xxgdb.記得要在編譯的時候加入 -g選項.關於gdb的使用能夠看gdb的幫助文件。因爲我沒有用過這個軟件,因此我也不可以說出如何使用。不過我不喜歡用gdb.跟蹤一個程序是很煩的 事情,我通常用在程序當中輸出中間變量的值來調試程序的。固然你能夠選擇本身的辦法,沒有必要去學別人的。如今有了許多IDE環境,裏面已經本身帶了調試 器了。你能夠選擇幾個試一試找出本身喜歡的一個用。

5.頭文件和系統求助

有時候咱們只知道一個函數的大概形式,不記得確切的表達式,或者是不記得着函數在那個頭文件進行了說明。這個時候咱們能夠求助系統。

好比說咱們想知道fread這個函數的確切形式,咱們只要執行 man fread 系統就會輸出着函數的詳細解釋的。和這個函數所在的頭文件說明了。 若是咱們要write這個函數的說明,當咱們執行man write時,輸出的結果卻不是咱們所須要的。 由於咱們要的是write這個函數的說明,但是出來的倒是write這個命令的說明。爲了獲得write的函數說明咱們要用 man 2 write. 2表示咱們用的write這個函數是系統調用函數,還有一個咱們經常使用的是3表示函數是C的庫函數。

記住無論何時,man都是咱們的最好助手。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息