日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

开发工具(三)

發布時間:2024/10/8 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 开发工具(三) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

內建規則

到目前為止,我們已經在makefile文件中確切的指定了如何執行過程的每一步。事實上,makefile有大量的內建規則從而可以很大程度的簡化makefile文件,特別是當我們有大量源文件的時候。下面我們創建foo.c,這是一個傳統的Hello World程序。

#include <stdlib.h>
#include <stdio.h>
int main()
{
??? printf(“Hello World/n”);
??? exit(EXIT_SUCCESS);
}

不指定makefile文件,我們嘗試使用make來編譯。

$ make foo
cc???? foo.c -o foo
$

正如我們所看到的,make知道如何調用編譯器,盡管在這種情況下,他選擇cc而不是gcc(在Linux下這可以正常工作,因為通常cc鏈接到gcc)。有時,這些內建規則是推斷規則(inference rules)。默認的規則使用宏,所以通過為這些宏指定一個新值,我們可以改變默認的行為。

$ rm foo
$ make CC=gcc CFLAGS=”-Wall -g” foo
gcc -Wall -g??? foo.c?? -o foo
$

我們可以使用-p選項使得make打印出其內建規則。內建規則太多而不能在這里全部列出,但是下面是GNU版本的make的make -p的簡短輸出,演示了其中的部分規則:

OUTPUT_OPTION = -o $@
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
%.o: %.c
# commands to execute (built-in):
??????? $(COMPILE.c) $(OUTPUT_OPTION) $<

我們現在可以通過指定構建目標文件的規則使用這些內建規則來簡化我們的makefile文件,所以makefile文件的相關部分簡化為:

main.o: main.c a.h
2.o: 2.c a.h b.h
3.o: 3.c b.h c.h

后綴與模式規則

我們所看到的內建規則使用后綴進行工作(與Windows和MS-DOS的文件名擴展相類似),所以當指定一個帶有擴展名的文件時,make知道應使用哪條規則來創建帶有不同擴展名的文件。在這里最通常的規則就是由以.c為結尾的文件創建以.o為結尾的文件。這個規則就是使用編譯器編譯文件,但是并不鏈接源文件。

有時我們需要能夠創建新規則。程序開發作者過去在一些源文件上需要使用不同的編譯器進行編譯:兩個在MS-DOS下,以及Linux下的gcc。要滿足MS-DOS編譯器的要求,C++源文件而不是C源文件,需要以.cpp為后綴進行命名。不幸的是,現在Linux下使用的make版本并沒有編譯.cpp文件的內建規則。(他確實具有一個在Unix下更為常見的.cc的規則)

所以或者是為每一個單獨的文件指定一個規則,或者是我們需要教給make一個新的規則來由以.cpp為擴展名的文件創建目標文件。假如我們在這個工程中有大量的源文件,指定一個新規則節省了大量的輸入工作,并且使得在工程中添加一個新源文件更為容易。

要添加一個新的后綴規則,我們首先在makefile文件中添加一行,告訴make新的后綴;然后我們就可以使用這個新的后綴來編寫一條規則。make使用下面的語法樣式來定義一條通用的規則來由具有舊后綴的文件創建具有新后綴的文件:

.<old_suffix>.<new_suffix>:

下面是我們的makefile文件中一條新的通用規則的代碼片段,用于將.cpp文件轉換為.o文件:

.SUFFIXES:????? .cpp
.cpp.o:
?? $(CC) -xc++ $(CFLAGS) -I$(INCLUDE) -c $<

特殊依賴.cpp.o:告訴make接下來的規則用于將以.cpp為后綴的文件轉換為以.o為后綴的文件。當我們編寫這個依賴時,我們使用特殊的宏名,因為我們并不知道我們將要轉換的實際文件名。要理解這條規則,我們只需要簡單的回憶起$<會擴展為起始文件名(帶有舊后綴)即可。注意,我們只是告訴make如何由.cpp文件得到.o文件;make已經知道如何由一個目標文件獲得二進制可執行文件。

當我們調用make時,他使用我們的新規則由bar.cpp獲得bar.o,然后使用其內建規則由.o獲得一個可執行文件。-xc++標記用于告訴gcc這是一個C++源文件。

在近些時候,make知道如何處理帶有.cpp擴展名的C++源文件,但是當將一種文件類型轉換為另一種文件類型時,這個技術是十分有用的。

更為舊的make版本包含一個對應的語法用來達到同樣的效果,而且更好。例如,匹配規則使用通配符語法來匹配文件,而不是僅依賴于文件擴展名。

對于上面例子中與.cpp規則等同的模式規則如下:

%.cpp: %o
?? $(CC) -xc++ $(CFLAGS) -I$(INCLUDE) -c $<

使用make管理庫

當我們正處理一個大型工程時,使用庫來管理多個編譯產品通常是比較方便的。庫是文件,通常以.a為擴展名,包含一個目標文件的集合。make命令有一個處理庫的特殊語法,從而使得他們更易于管理。

這個語法就是lib (file.o),這就意味著目標文件file.o存儲在庫lib.a中。make具有一個內建的規則用于管理庫,通常如下面的樣子:

.c.a:
?? $(CC) -c $(CFLAGS) $<
?? $(AR) $(ARFLAGS) $@ $*.o

宏$(AR)與$(ARFLAGS)通常分別默認為命令ar與選項rv。這個簡短的語法告訴make由一個.c文件得到.a庫,他必須執行兩條規則:

第一條規則是他必須編譯源文件并且生成一個目標文件
第二條規則是使用ar命令來修改庫,添加新的目標文件

所以,如果我們有一個庫fud,包含文件bas.o,在第一條規則中$<被替換為bas.c。在第二條規則中,$@被替換為庫fud.a,而$*被替換為bas。

試驗--管理庫

實際上,管理庫的規則的使用是相當簡單的。下面我們修改我們的程序,從而文件2.o與3.o保存在一個名為mylib.a的庫中。我們的makefile文件需要一些小的修改,所以Makefile5如下所示:

all: myapp
# Which compiler
CC = gcc
# Where to install
INSTDIR = /usr/local/bin
# Where are include files kept
INCLUDE = .
# Options for development
CFLAGS = -g -Wall -ansi
# Options for release
# CFLAGS = -O -Wall -ansi
# Local Libraries
MYLIB = mylib.a
myapp: main.o $(MYLIB)
?? $(CC) -o myapp main.o $(MYLIB)
$(MYLIB): $(MYLIB)(2.o) $(MYLIB)(3.o)
main.o: main.c a.h
2.o: 2.c a.h b.h
3.o: 3.c b.h c.h
clean:
?? -rm main.o 2.o 3.o $(MYLIB)
install: myapp
?? @if [ -d $(INSTDIR) ]; /
??? then /
????? cp myapp $(INSTDIR);/
????? chmod a+x $(INSTDIR)/myapp;/
????? chmod og-w $(INSTDIR)/myapp;/
????? echo “Installed in $(INSTDIR)”;/
?? else /
????? echo “Sorry, $(INSTDIR) does not exist”;/
?? fi

在這里需要注意我們是如何使用默認規則來完成大多數工作的?,F在讓我們來測試我們的新版本makefile文件。

$ rm -f myapp *.o mylib.a
$ make -f Makefile5
gcc -g -Wall -ansi?? -c -o main.o main.c
gcc -g -Wall -ansi?? -c -o 2.o 2.c
ar rv mylib.a 2.o
a - 2.o
gcc -g -Wall -ansi?? -c -o 3.o 3.c
ar rv mylib.a 3.o
a - 3.o
gcc -o myapp main.o mylib.a
$ touch c.h
$ make -f Makefile5
gcc -g -Wall -ansi?? -c -o 3.o 3.c
ar rv mylib.a 3.o
r - 3.o
gcc -o myapp main.o mylib.a
$

工作原理

我們首先刪除所有的目標文件以及庫,并且允許make構建myapp,他通過編譯并且在使用庫鏈接main.o之前創建庫,從而創建myapp。然后我們測試3.o的測試規則,他會通知make,如果c.h發生變動,那么3.c必須進行重新編譯。他會正確的完成這些工作,在重新鏈接之前會編譯3.c并且更新庫,從而創建一個新的可執行文件myapp。

高級主題:Makefile與子目標

如果我們編寫一個大工程,有時將組成庫的文件由主文件分離并且存儲在一個子目錄中是十分方便的。使用make可以兩種方法來完成這個任務。

首先,我們在此子目錄可以有第二個makefile文件來編譯文件,將其存儲在一個庫中,然后將庫拷貝到上一層主目錄。在高層目錄中的主makefile文件然后有一條規則用于構建這個庫,其調用第二個makefile文件的語法如下:

mylib.a:
?? (cd mylibdirectory;$(MAKE))

這就是說我們必須總是嘗試構建mylib.a。當make調用這條規則用于構建庫時,他會進入子目錄mylibdirectory,然后調用一個新的make命令來管理庫。因為這會調用一個新的shell,使用makefile的程序并不會執行cd命令。然而,所調用的用于執行規則構建庫的shell是在一個不同的目錄中。括號可以保證他們都會在一個單獨的shell中進行處理。

第二個方法是在一個單獨的makefile文件中使用一些額外的宏。這些額外的宏是通過在我們已經討論過的這些宏的基礎上添加D(對目錄而言)或是F(就文件而言)來生成的。然后我們可以用下面的規則來覆蓋內建的.c.o前綴規則:

.c.o:
???? $(CC) $(CFLAGS) -c $(@D)/$(<F) -o $(@D)/$(@F)

來在子目錄中編譯文件并且將目標文件留下子目錄中。然后我們可以用如下的依賴與規則來更新當前目錄中的庫:

mylib.a:?? mydir/2.o mydir/3.o
???? ar -rv mylib.a $?

我們需要決定在我們自己的工程中我們更喜歡哪種方法。許多工程只是簡單的避免具有子目錄,但是這樣會導致在源碼目錄中有大量的文件。正如我們在前面的概覽中所看到的,我們在子目錄中使用make只是簡單的增加了復雜性。

GNU make與gcc

如果我們正使用GNU make與GNU gcc編譯器,還有兩個有趣的選項:

第一個就是make的-jN("jobs")選項。這會使用make同時執行N條命令。此時make可以同時調用多條規則,獨立的編譯工程的不同部分。依據于我們的系統配置,這對于我們重新編譯的時候是一個巨大的改進。如果我們有多個源文件,嘗試這個選項是很有價值的。通常而言,小的數字,例如-j3,是一個好的起點。如果我們與其他用戶共享我們的機器,那么要小心使用這個選項。其他用戶也許不會喜歡每次編譯時我們啟動大量的進程數。

另一個有用的選項就是gcc的-MM選項。這會產生一個適合于make的依賴列表。在一個具有大量源碼文件的工程中,每一個文件都會包含不同的頭文件組合,要正確的獲得依賴關系是非常困難的,但是卻是十分重要的。如果我們使用每一個源文件依賴于每一個頭文件,有時我們就會編譯不必須的文件。另一方面,如果我們忽略一些依賴,問題就會更為嚴重,因為我們會沒有編譯那些需要重新編譯的文件。

試驗--gcc -MM

下面我們使用gcc的-MM選項來為我們的例子工程生成一個依賴列表:

$ gcc -MM main.c 2.c 3.c
main.o: main.c a.h
2.o: 2.c a.h b.h
3.o: 3.c b.h c.h
$

工作原理

gcc編譯只是簡單的以適于插入一個makefile文件中的形式輸出所需要依賴行。我們所需要做的就是將輸出保存到一個臨時文件中,然后將其插入makefile文件中,從而得到一個完美的依賴規則集。如果我們有一個gcc的輸出拷貝,我們的依賴就沒有出錯的理由。

如果我們對于makefile文件十分自信,我們可以嘗試使用makedepend工具,這些執行與-MM選項類似的功能,但是會將依賴實際添加到指定的makefile文件的尾部。

在我們離開makefile話題之前,也許很值得指出我們并不是只能限制自己使用makefile來編譯代碼或是創建庫。我們可以使用他們來自動化任何任務,例如,有一個序列命令可以使得我們由一些輸入文件得到一個輸出文件。通常"非編譯器"用戶也許適用于調用awk或是sed來處理一些文件,或是生成手冊頁。我們可以自動化任何文件處理,只要是make由文件的日期與時間信息的修改可以處理的。

轉載于:https://www.cnblogs.com/dyllove98/archive/2009/03/14/2461963.html

總結

以上是生活随笔為你收集整理的开发工具(三)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。