最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于make命令與makefile文件詳解

 更新時(shí)間:2018年01月09日 10:57:02   作者:haozlee  
下面小編就為大家分享一篇基于make命令與makefile文件詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

一、多個(gè)源文件帶來(lái)的問(wèn)題

在編寫(xiě)c/c++測(cè)試程序時(shí),我們習(xí)慣每次修改一處代碼,然后就馬上編譯運(yùn)行來(lái)查看運(yùn)行的結(jié)果。這種編譯方式對(duì)于小程序來(lái)說(shuō)是沒(méi)有多大問(wèn)題的,可對(duì)于大型程序來(lái)說(shuō),由于包含了大量的源文件,如果每次改動(dòng)一個(gè)地方都需要編譯所有的源文件,這個(gè)簡(jiǎn)單的直接編譯所有源文件方式對(duì)程序員來(lái)說(shuō)簡(jiǎn)直是噩耗。

我們看一個(gè)例子:

// main.c
#include "a.h"
// 2.c
#include "a.h"
#include "b.h"
// 3.c
#include "b.h"
#include "c.h"

如果程序員只修改了頭文件c.h,則源文件main.c和2.c都無(wú)需編譯,因?yàn)樗鼈儾灰蕾囘@個(gè)頭文件。而對(duì)3.c來(lái)說(shuō),由于它包含了c.h,所以在頭文件c.h改動(dòng)后,就必須得新編譯。

而如果改動(dòng)了b.h可是忘記編譯了2.c,那么最終的程序就可能無(wú)法正常工作。

make 工具就是為了解決上述問(wèn)題而出現(xiàn)的,它會(huì)在必要時(shí)重新編譯所有受改動(dòng)影響的源文件。

二、make 命令

make命令本身支持許多選項(xiàng),最常用的是-f選項(xiàng)。如果我們直接運(yùn)行

make

那么make命令會(huì)首先在當(dāng)前目錄查找名為makefile的文件,如果找不到,就會(huì)查找名為Makefile的文件。

為了指示make命令將哪個(gè)文件作為makefile文件,可以使用 -f 選項(xiàng):

make -f Makefile1

三、makefile 文件

上面提到makefile文件,那么什么是makefile文件呢?

make命令功能雖然十分強(qiáng)大,但是光憑其自身無(wú)法了解如何構(gòu)建應(yīng)用程序的。這時(shí),makefile就出來(lái)了,它告訴make應(yīng)用程序如何構(gòu)建的。make命令和makefile文件的結(jié)合提供了一個(gè)在管理項(xiàng)目的十分強(qiáng)大的工具,它們不僅用于控制源文件的編譯,而且還提供了將應(yīng)用程序安裝到目標(biāo)目錄等其他功能。

3.1 依賴關(guān)系

依賴關(guān)系定義了應(yīng)用程序里面每個(gè)文件與其他源文件之間的關(guān)系。例如在上面的例子中,我們可以定義最終應(yīng)用程序依賴于目標(biāo)文件main.o,2.o和3.o。同樣,main.o依賴于main.c和a.h,2.o依賴于2.c,a.h和b.h,3.o依賴于3.c,b.h和c.h。

在makefile文件中,依賴關(guān)系的寫(xiě)法是:先寫(xiě)目標(biāo)的名稱,然后緊跟一個(gè)冒號(hào),接著是空格或者制表符tab,最后是用空格或者制表符tab隔開(kāi)的文件列表。上面的例子的依賴關(guān)系如下:

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

這組依賴關(guān)系形成一個(gè)層次結(jié)構(gòu),展示了源文件之間的關(guān)系。例如,如果源文件b.h發(fā)生改變,就需要重新編譯2.o和3.o,接下來(lái)還需要重新編譯myapp。

3.2 規(guī)則

makefiel文件中的規(guī)則定義了目標(biāo)的創(chuàng)建方式。在上面的例子中,我們使用gcc -c 2.c創(chuàng)建2.o。這個(gè)gcc命令即是目標(biāo)2.o的創(chuàng)建方式,也即是規(guī)則。

在makefile文件中,規(guī)則都必須以tab開(kāi)頭。

在源文件所在的目錄下創(chuàng)建Makefile1文件,其內(nèi)容如下。

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

三個(gè)頭文件a.h,b.h,c.h內(nèi)容都為空,源文件的內(nèi)容如下:

/* main.c */
#include <stdlib.h>
#include "a.h"
extern void function_two();
extern void function_three();
int main()
{
 function_two();
 function_three();
 exit(EXIT_SUCCESS);
}
/* 2.c */
#include <stdio.h>
#include "a.h"
#include "b.h"
void function_two() {
 printf("function two\n");
}
/* 3.c */
#include <stdio.h>
#include "b.h"
#include "c.h"
void function_three() {
 printf("function three\n");
}

執(zhí)行make命令,:

$ make -f Makefile1 
gcc -c main.c 
gcc -c 2.c 
gcc -c 3.c 
gcc -o myapp main.o 2.o 3.o

運(yùn)行應(yīng)用程序:

$ ./myapp 
function two 
function three

從輸出可以說(shuō)明應(yīng)用程序已被正確構(gòu)建。

如果改變b.h頭文件,makefile能夠正確處理這一變化,只有2.c和3.c發(fā)生重新編譯:

$ touch b.h
$ make -f Makefile1 
gcc -c 2.c 
gcc -c 3.c 
gcc -o myapp main.o 2.o 3.o

3.3 注釋

makefile文件使用#來(lái)表示注釋,一直延續(xù)到這一行的結(jié)束。

3.4 宏

不同的平臺(tái)下可能使用不同的編譯器,不同的環(huán)境(例如開(kāi)發(fā)與線上環(huán)境)也可能使用不同的編譯器選項(xiàng),為了便于修改makefile這些可變的參數(shù),我們可以使用宏來(lái)實(shí)現(xiàn)makefile。

makefile引用宏定義的方法為$(MACRONAME)。我們來(lái)看如何使用宏來(lái)改寫(xiě)上面的makefile文件。

all: myapp
# 編譯器
CC = gcc
# include的搜索路徑
INCLUDE = .
# 編譯器參數(shù)
CFLAGS = -g -Wall -ansi
myapp: main.o 2.o 3.o
 $(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
 $(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.c a.h b.h
 $(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c
3.o: 3.c b.h c.h
 $(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c

我們習(xí)慣在makefile文件中將第一個(gè)目標(biāo)定義為all,然后再列出其他從屬的目標(biāo),上面的makefile也遵循這個(gè)約定。

運(yùn)行make命令:

$ make -f Makefile2 
gcc -I. -g -Wall -ansi -c main.c 
gcc -I. -g -Wall -ansi -c 2.c 
gcc -I. -g -Wall -ansi -c 3.c 
gcc -o myapp main.o 2.o 3.o

同樣也正確構(gòu)建了應(yīng)用程序myapp。

3.5 多個(gè)目標(biāo)

makefile文件除了定義編譯的目標(biāo)外,還可以定義其他的目標(biāo)。例如,增加一個(gè)clean選項(xiàng)來(lái)刪除不需要的目標(biāo)文件,增加一個(gè)install選項(xiàng)來(lái)將編譯成功的應(yīng)用程序安裝到另一個(gè)目錄下,等等。

all: myapp
CC = gcc
INSTDIR = /usr/local/bin
INCLUDE = .
CFLAGS = -g -Wall -ansi
myapp: main.o 2.o 3.o
 $(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
 $(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.c a.h b.h
 $(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c
3.o: 3.c b.h c.h
 $(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c
clean:
 -rm main.o 2.o 3.o
install: myapp
 @if [ -d $(INSTDIR) ]; \
  then \
  cp myapp $(INSTDIR);\
  chmod a+x $(INSTDIR)/myapp;\
  chmod og-w $(INSTDIR)/myapp;\
  echo "Install in $(INSTDIR)";\
 else \
  echo "sorry, $(INSTDIR) does not exist";\
 fi

上面的makefile文件有幾點(diǎn)需要注意的。

(1)特殊目標(biāo)all只指定了myapp這個(gè)目標(biāo),因此,在執(zhí)行make命令時(shí)未指定目標(biāo),它的默認(rèn)行為就是創(chuàng)建目標(biāo)myapp。

(2)目標(biāo)clean用來(lái)測(cè)試編譯過(guò)程中產(chǎn)生的中間文件。

(3)目標(biāo)install用于將應(yīng)用程序安裝到指定目錄,它依賴于myapp,即執(zhí)行install前須先創(chuàng)建myapp。install目標(biāo)由shell腳本組成,由于make命令在執(zhí)行規(guī)則時(shí)會(huì)調(diào)用一個(gè)shell,并且會(huì)針對(duì)每個(gè)規(guī)則使用一個(gè)新的shell,所以必須在上面每行代碼的結(jié)尾加上一個(gè)\,讓所有的shell腳本都處于同一行。

腳本以@開(kāi)頭,說(shuō)明make在執(zhí)行這些規(guī)則之前不會(huì)在標(biāo)準(zhǔn)輸出顯示命令本身。

創(chuàng)建myapp:

$ make -f Makefile3 
gcc -I. -g -Wall -ansi -c main.c 
gcc -I. -g -Wall -ansi -c 2.c 
gcc -I. -g -Wall -ansi -c 3.c 
gcc -o myapp main.o 2.o 3.o

將myapp安裝到指到目錄:

$ make -f Makefile3 install 
Install in /usr/local/bin

然后可以直接執(zhí)行myapp:

$ myapp 
function two 
function three

刪除中間文件:

$ make -f Makefile3 clean 
rm main.o 2.o 3.o

以上這篇基于make命令與makefile文件詳解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C語(yǔ)言求2的n次方多種方法總結(jié)

    C語(yǔ)言求2的n次方多種方法總結(jié)

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言求2的n次方多種方法的相關(guān)資料,求2的N次冪是一個(gè)常用的功能,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • Qt+QWidget實(shí)現(xiàn)簡(jiǎn)約美觀的加載動(dòng)畫(huà)

    Qt+QWidget實(shí)現(xiàn)簡(jiǎn)約美觀的加載動(dòng)畫(huà)

    這篇文章主要為大家詳細(xì)介紹了Qt如何結(jié)合QWidget實(shí)現(xiàn)簡(jiǎn)約美觀的加載動(dòng)畫(huà),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • C++設(shè)計(jì)模式中的橋模式你了解嗎

    C++設(shè)計(jì)模式中的橋模式你了解嗎

    這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式中的橋模式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • C++實(shí)現(xiàn)俄羅斯方塊

    C++實(shí)現(xiàn)俄羅斯方塊

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)俄羅斯方塊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • c++實(shí)現(xiàn)的常見(jiàn)緩存算法和LRU

    c++實(shí)現(xiàn)的常見(jiàn)緩存算法和LRU

    LRU緩存算法也叫LRU頁(yè)面置換算法,是一種經(jīng)典常用的頁(yè)面置換算法,下面這篇文章主要介紹了c++實(shí)現(xiàn)的常見(jiàn)緩存算法和LRU,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-01-01
  • C語(yǔ)言中數(shù)組的一些基本知識(shí)小結(jié)

    C語(yǔ)言中數(shù)組的一些基本知識(shí)小結(jié)

    這篇文章主要介紹了C語(yǔ)言中數(shù)組的一些基本知識(shí)小結(jié),其中重點(diǎn)是對(duì)于數(shù)組的內(nèi)存分配相關(guān)方面的知識(shí)整理,需要的朋友可以參考下
    2016-04-04
  • C++ 中 socket編程實(shí)例詳解

    C++ 中 socket編程實(shí)例詳解

    這篇文章主要介紹了C++ 中 socket編程實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C語(yǔ)言示例講解do?while循環(huán)語(yǔ)句的用法

    C語(yǔ)言示例講解do?while循環(huán)語(yǔ)句的用法

    在不少實(shí)際問(wèn)題中有許多具有規(guī)律性的重復(fù)操作,因此在程序中就需要重復(fù)執(zhí)行某些語(yǔ)句。一組被重復(fù)執(zhí)行的語(yǔ)句稱之為循環(huán)體,能否繼續(xù)重復(fù),決定循環(huán)的終止條件
    2022-06-06
  • 基于Qt開(kāi)發(fā)一個(gè)簡(jiǎn)單的OFD閱讀器

    基于Qt開(kāi)發(fā)一個(gè)簡(jiǎn)單的OFD閱讀器

    這篇文章主要為大家詳細(xì)介紹了如何使用Qt框架開(kāi)發(fā)一個(gè)功能強(qiáng)大且性能優(yōu)異的OFD閱讀器,文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下
    2025-01-01
  • c++選擇排序詳解

    c++選擇排序詳解

    選擇排序(Selection sort)是一種簡(jiǎn)單直觀的排序算法。它的工作原理是每一次從無(wú)序組的數(shù)據(jù)元素中選出最?。ɑ蜃畲螅┑囊粋€(gè)元素,存放在無(wú)序組的起始位置,無(wú)序組元素減少,有序組元素增加,直到全部待排序的數(shù)據(jù)元素排完。
    2017-05-05

最新評(píng)論

洛阳市| 新邵县| 江北区| 杭锦旗| 黔西县| 巴南区| 达州市| 山丹县| 通河县| 石渠县| 江华| 无棣县| 云南省| 金门县| 昌都县| 大同市| 福鼎市| 章丘市| 淄博市| 页游| 锡林郭勒盟| 万载县| 增城市| 嘉鱼县| 绥芬河市| 宾阳县| 龙门县| 郴州市| 陆川县| 新巴尔虎左旗| 新竹市| 白水县| 开江县| 河北区| 合作市| 仁怀市| 江油市| 永嘉县| 洪洞县| 白河县| 毕节市|