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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows平台下Makefile学习笔记

發布時間:2024/4/11 windows 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows平台下Makefile学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

來源:http://blog.csdn.net/clever101

?

????????決心學習Makefile,一方面是為了解決編譯開源代碼時需要跨編譯平臺的問題(發現一些開源代碼已經在使用VS2010開發,但我還沒安裝VS2010,我想在VS2008下編譯這些代碼);另一方面源碼在服務器端編譯的話,使用IDE的方式編譯還是不太方便。

?

???????本文主要分為三部分:第一部分講述namke工具使用makefile的用法;第二部分講述makefile的主要語法;第三部分講述自己動手實踐學習寫makefile文件。第四部分是編寫一個工具將vc工程文件轉化為Makefile文件。

?

???????首先要清楚的是在VS環境下使用Makefile的工具是nmake。因此我們需要弄明白nmake的使用Makefile文件常用命名行用法。nmake使用Makefile文件常用命名行用法是:


? ? ?

[plain]?view plaincopy
  • namke?/f??makefile?/x?stderrfile??[macrodefs]?[targets]??
  • ?


    其中makefile為makefile文件,/x stderrfile為可選參數,即把namke錯誤存儲到文件stderrfile。

    ?

    ??????接著介紹makefile的主要語法。makefile的注釋以#開頭,如:

    [plain]?view plaincopy
  • #?this?is?my?first?makefile??


  • Makefile的一個重要組成部分是宏。Makefile中的宏和C語言的中宏類似,其實質就是字符串替換。其語法很簡單,如下:

    ?

    macro name =? macro value

    ?

    直譯就是宏名 =? 宏的值

    ?

    ??????VS預定義了很多宏,如OUTDIR,你可以在你的Makefile重新定義這些宏以覆蓋原來的值。

    ?

    ???????宏可以使用環境變量,如你的系統有一個OPEN_SOURCE的環境變量,然后你可以這樣定義宏:

    ?????THIRD_PARTY? =? $(OPEN_SOURCE)

    ?

    ??????宏的引用用法是 $(宏名)。

    ?

    接著介紹Makefile的第二個重要組成部分預處理指令。Makefile的預處理指令和C語言的預處理指令類似,其常用指令如下:

    !ERROR string????? ——??? 顯示錯誤“string”, 然后停止執行,錯誤代碼為U1050

    !MESSAGE string? ——?? 顯示字符串,這個一般用于信息顯示C語言的#pragma message

    !INCLUDE [<]filename[>] —— 包含makefile。

    !IF const?——? 如果成立(非零),則處理!F和下一個!ELSE或!ENDIF之間的語句

    還有諸如!IFDEF macroname、!IFNDEF macroname、!ELSE、!ELSEIF、!ELSEIFDEF、!ELSEIFNDEF、!ENDIF和C語言的#if之類的指令的意義是一致的,這里就不一一詳述了。

    ?

    ?? Makefile的第三個主要組成部分是描述塊。描述塊的結構如下:

    目標:依賴項

    ?????命令

    ??

    這里略微解釋下什么叫目標、依賴項和命令。所謂目標就是用戶最終希望得到的結果,也就是nmake需要生成的結果。目標可以是一個文件、目錄,也可以什么都不是。如果目標不存在或者目標的時間戳(文件的最后修改時間)比依賴項早,或者目標類型不是文件,nmake將運行描述塊中的“命令”。

    ?

    依賴項是指在生成目標所需要使用到的對象。一個目標可以有一個或多個依賴項,也可以沒有依賴項。多個依賴項以空格分隔。如果指定的依賴項不存在,則在其他描述塊的目標中尋找,但首先需要生成這個目標。

    ?

    命令是nmake在生成目標時所調用的命令。與用戶自己在命令行中執行效果是一樣的。

    ?

    在使用namke進行程序構建時,nmake采用了時間戳判斷機制。在生成一個目標時,會判斷目標文件是否存在或目標的最后修改時間是否晚于所有依賴項的最后修改時間。如果所有依賴項的最后修改時間都比目標的最后修改時間晚,則說明當前的目標文件是使用現有的依賴項生成,是最新的,沒有必要再進行生成。

    ?? 介紹到這里,可能你對Mdakefile的語法細節有了大致的了解,但估計你對Makefile的常用文件結構還不了解。如果缺少對這一層的理解,你還是對如何編寫Makefile文件一頭霧水。下面介紹一下常用的Makefile文件結構。Makefile文件結構可以是如下的結構:

    # 宏定義

    ……


    # 描述塊

    ?

    ??????? 學了這么多,我們來實踐一下。首先我們來一個簡單的控制臺工程——ConsoleTest。一切根據工程向導采用默認設置即可。然后在main函數中添加幾句簡單代碼(這個用于判斷我們生成的程序是否成功),具體如下:

    [plain]?view plaincopy
  • int?_tmain(int?argc,?_TCHAR*?argv[])??
  • {??
  • ????printf("Hello?World!?\n");??
  • ????getchar();??
  • ????return?0;??
  • }??



  • ?????? 然后我們在ConsoleTest文件夾下新建一個makefile.vc。我們開始正式編寫一個makefile文件了。這時我們的大腦可能會一片空白,雖然你學了很多makefile語法,但邁出第一步依然是困難,這是正常的反應。好吧,讓我們一步步來吧。首先要告訴你makefile的一個基本原則:以終為始,這個似乎和我們平時進行的過程式編程的原則相悖。所謂以終為始,就是你通過makefile文件首先告訴編譯器這個工程是想生成一個exe還是一個dll還是一個靜態庫。然后告訴編譯器要生成這個exe之類需要生成哪些obj文件。在這個例子中,我們要生成一個exe,所以我們在makefile文件的第一行就是:

    [plain]?view plaincopy
  • all:ConsoleTest.exe??



  • 接下來就是編譯器的一般生成過程:編譯加鏈接命令,具體是:

    [plain]?view plaincopy
  • #?compile??
  • stdafx.obj:?stdafx.cpp??
  • ????cl?-c?-D_X86=1?-DWIN32?-D_DEBUG?-D_CONSOLE?-Istdafx.h?stdafx.cpp??
  • ?????
  • ConsoleTest.obj:?ConsoleTest.cpp?stdafx.obj??
  • ????cl?-c?-D_X86=1?-DWIN32?-D_DEBUG?-D_CONSOLE?-Istdafx.h?ConsoleTest.cpp??
  • ??
  • #?link??
  • ConsoleTest.exe:?ConsoleTest.obj??
  • link?/INCREMENTAL:YES?/NOLOGO?/subsystem:console?/out:ConsoleTest.exe?ConsoleTest.obj?kernel32.lib??


  • 其中cl語句是VC編譯器的編譯器的命令行編譯,link語句是VC鏈接器的命令行用法,這里只簡單敘述cl和link的用法。

    cl的一些常用選項:

    -c: 編譯但不鏈接

    -D: 定義預處理器,如-D_X86=1:指定在x86平臺上編譯,-D_DEBUG:定義預處理器_DEBUG,

    -I:包含的頭文件

    cl的最后一個參數是所編譯的文件。

    ?

    link的一些常用選項:

    /INCREMENTAL:是否啟用增量鏈接,YES為啟用,NO為不啟用,

    /NOLOGO: 取消顯示啟動版權標志

    /SUBSYSTEM:指定子系統,在PC桌面程序上一般是兩個選項:console(控制臺程序)和WINDOWS(非控制臺程序)。

    /out: 指定輸出的文件。

    link最后的參數是需要鏈接的obj文件和庫文件。

    ?

    cl和link的詳細用法請參考MSDN和參考文獻2《VC命令行編譯C++》。

    ?

    我們看到生成的obj文件和ConsoleTest.exe是放到當前的源碼文件夾下。一般我們想把它放到debug文件夾下。那么我們該怎么做呢?這時就可以用到makefile中的一個常用部分——宏。我們可以這樣定義一個宏,然后創建debug文件夾,具體代碼是:

    OUTDIR = .\Debug

    ?

    #這里增加了一個輸出:$(OUTDIR)

    [plain]?view plaincopy
  • all:?$(OUTDIR)?$(OUTDIR)\ConsoleTest.exe??



  • #假如不存在$(OUTDIR)文件夾,就創建它

    [plain]?view plaincopy
  • $(OUTDIR)?:??
  • if?not?exist?"$(OUTDIR)"?mkdir?$(OUTDIR)??


  • 相應地,生成的obj文件和exe文件都需要加上輸出文件的路徑,具體如下:

    [plain]?view plaincopy
  • #?compile??
  • $(OUTDIR)\stdafx.obj:?stdafx.cpp??
  • ????cl?-c?-D_X86=1?-DWIN32?-D_DEBUG?-D_CONSOLE?-Istdafx.h?/Fo"$(OUTDIR)\\"?/Fd"$(OUTDIR)\\"?stdafx.cpp???
  • ?????
  • $(OUTDIR)/ConsoleTest.obj:?ConsoleTest.cpp?$(OUTDIR)\stdafx.obj??
  • ????cl?-c?-D_X86=1?-DWIN32?-D_DEBUG?-D_CONSOLE?-Istdafx.h?/Fo"$(OUTDIR)\\"?/Fd"$(OUTDIR)\\"?ConsoleTest.cpp??
  • ??
  • #?link??
  • $(OUTDIR)\ConsoleTest.exe:?$(OUTDIR)\ConsoleTest.obj??
  • ????link?/INCREMENTAL:YES?/NOLOGO?/subsystem:console?/out:$(OUTDIR)\ConsoleTest.exe?$(OUTDIR)\ConsoleTest.obj?kernel32.lib??


  • 這里cl工具增加了兩個選項

    /Fo:指定obj文件的放置路徑

    /Fd:指定pdb文件的放置路徑

    ?

    這里需要值得注意的,Windows平臺下文件反斜杠應該采用\,而不是跨平臺的/,因為我曾把OUTDIR = .\Debug寫成OUTDIR = ./Debug,結果造成if not exist不識別$(OUTDIR)而造成語法錯誤。/在windows平臺下的makefile中大多地方可以識別,但在一些地方不能識別(例如if not exist語句),而\在任何地方都能識別的。

    ?

    還有就是命令語句必須至少空出一格,而不能頂格寫。如果if not exist"$(OUTDIR)" mkdir $(OUTDIR)頂格,就會出現錯誤:

    makefile.vc(5) : fatal error U1034: 語法錯誤 : 缺少分隔符

    Stop.

    ?

    ??? 除開命令語句,其它語句都應該頂格寫。

    ?

    我們繼續完善這個makefile。我們想增加一個清理輸出文件的指令,就是常用的clean指令。我們可以在描述塊all后面加一個描述塊:clean,clean描述塊的代碼如下:

    [plain]?view plaincopy
  • clean:??
  • ???????if?exist?$(OUTDIR)?del?$(OUTDIR)\*.ilk??
  • ???????if?exist?$(OUTDIR)?del?$(OUTDIR)\*.obj??
  • ????if?exist?$(OUTDIR)?del?$(OUTDIR)\*.exe????


  • ??????? 如果makefile文件中不存在clean這個描述塊,而你運行下面的命令:

    nmake /f makefile.vc clean

    會出現下面的錯誤提示:

    NMAKE : fatal error U1052: 未找到文件“clean”

    Stop.

    ?

    ?????? 我們繼續完善這個makefile。因為現在只能編譯debug版本,我們想用戶能指定編譯debug版本或release版本,用戶只需要輸入“debug”或“release”來指定。我們想到可以設定一個宏標記來指定,當用戶輸入正確時就編譯相應的版本,錯誤時就提示使用方法。同時我們想到前面提到nmake工具的命令行用法是:

    [plain]?view plaincopy
  • namke?/f??makefile?/x?stderrfile??[macrodefs]?[targets]??


  • 其中macrodefs就是允許我們定義一些自定義宏來控制編譯輸出的。這次我們可以定義兩個宏debug和release。具體不再詳述,下面列出代碼:

    [plain]?view plaincopy
  • #設置編譯標記,初始化為FALSE??
  • CFGSET?????=??FALSE??
  • ??
  • #定義debug版本的預處理器??
  • CCDEBUG????=?-DWIN32?-D_DEBUG?-D_CONSOLE??
  • ??
  • #定義release版本的預處理器??
  • CCNODBG????=?-DWIN32?-D_NDEBUG?-D_CONSOLE??
  • ??
  • !IFDEF?debug??
  • CC?????????=?$(CCDEBUG)??
  • OUTDIR?=?.\Debug??
  • CFGSET?????=??TRUE??
  • !ELSE?IFDEF?release??
  • CC?????????=?$(CCNODBG)??
  • OUTDIR?=?.\Release??
  • CFGSET?????=??TRUE??
  • !ENDIF??
  • ??
  • #?提示用法??
  • #??
  • !IF?"$(CFGSET)"==?"FALSE"??
  • !MESSAGE?Usage:?nmake?/f?Makefile.vc?[<config>]?[<target>]????????
  • !MESSAGE??
  • !MESSAGE?where?<config>?is?one?of:??
  • !MESSAGE?-??release=1???????????????-?build?release?version??
  • !MESSAGE?-??debug=1?????????????????-?build?debug?version??
  • !MESSAGE??
  • !MESSAGE?<target>?may?be:??
  • !MESSAGE?-??clean?????????????????-?clear?output?file??
  • !MESSAGE??
  • !MESSAGE??
  • !ERROR?please?choose?a?valid?configuration?instead"??
  • !ENDIF??
  • ??
  • ??
  • #這里增加了一個輸出:$(OUTDIR)??
  • all:?$(OUTDIR)?$(OUTDIR)\ConsoleTest.exe??
  • ??
  • #假如不存在$(OUTDIR)文件夾,就創建它??
  • $(OUTDIR)?:??
  • ?if?not?exist?"$(OUTDIR)"?mkdir?$(OUTDIR)??
  • ???
  • clean:??
  • ???????if?exist?$(OUTDIR)?del?$(OUTDIR)\*.ilk??
  • ???????if?exist?$(OUTDIR)?del?$(OUTDIR)\*.obj??
  • ???????if?exist?$(OUTDIR)?del?$(OUTDIR)\*.exe???????
  • ?????
  • #?compile??
  • $(OUTDIR)\stdafx.obj:?stdafx.cpp??
  • ????cl?-c??$(CC)?-Istdafx.h?/Fo"$(OUTDIR)\\"?/Fd"$(OUTDIR)\\"?stdafx.cpp???
  • ?????
  • $(OUTDIR)\ConsoleTest.obj:?ConsoleTest.cpp?$(OUTDIR)\stdafx.obj??
  • ????cl?-c??$(CC)?-Istdafx.h?/Fo"$(OUTDIR)\\"?/Fd"$(OUTDIR)\\"?ConsoleTest.cpp??
  • ??
  • #?link??
  • $(OUTDIR)\ConsoleTest.exe:?$(OUTDIR)\ConsoleTest.obj??
  • ????link?/machine:x86?/INCREMENTAL:YES?/NOLOGO?/subsystem:console?/out:$(OUTDIR)\ConsoleTest.exe?$(OUTDIR)\ConsoleTest.obj?kernel32.lib??
  • ??????


  • 該makefile的用法是:

    [plain]?view plaincopy
  • #編譯debug版本??
  • nmake?/f?makefile.vc?debug=1??
  • #編譯release版本??
  • nmake?/f?makefile.vc?release=1??
  • #清除debug版本??
  • nmake?/f?makefile.vc?debug=1?clean??
  • #清除release版本??
  • nmake?/f?makefile.vc?release=1?clean??


  • 參考文獻:

    ?

    1. MSDN 2008,Microsoft Corporation

    2. VC命令行編譯C++

    3. 精通Windows API,范文慶、周彬彬、安靖編著

    總結

    以上是生活随笔為你收集整理的Windows平台下Makefile学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

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