1. 程式人生 > >Windows平臺下Makefile學習筆記(二)

Windows平臺下Makefile學習筆記(二)

作者:朱金燦

       上次我們學習了怎麼用Makefile編譯一個控制檯工程。這次我們學習一下如何使用Makefile來編譯一個win 32的GUI程式。win 32的GUI程式其編譯過程大部分和控制檯程式一樣,不同的是多了一步RC編譯器將資原始檔編譯成res檔案,然後在最後一步連結中需要把這個res檔案連結到exe檔案中。

        好,現在讓我們在實踐中學習吧。新建一個win32 應用程式工程——Win32Test。讓我們先完成C++程式碼部分的Makefile的編寫,還記得Makefile的原則是以終為始嗎?忘記了就翻翻上一篇:Windows平臺下Makefile學習筆記(一)

。具體程式碼如下:

  1. #設定編譯標記,初始化為FALSE  
  2. CFGSET     =  FALSE  
  3. #定義debug版本的前處理器  
  4. CCDEBUG    = -DWIN32 -D_DEBUG -D_WINDOWS  
  5. #定義release版本的前處理器  
  6. CCNODBG    = -DWIN32 -D_NDEBUG -D_WINDOWS  
  7. !IFDEF debug  
  8. CC         = $(CCDEBUG)  
  9. OUTDIR = .\Debug  
  10. CFGSET     =  TRUE  
  11. !ELSE IFDEF release  
  12. CC         = $(CCNODBG)  
  13. OUTDIR = .\Release  
  14. CFGSET     =  TRUE  
  15. !ENDIF  
  16. # 提示用法  
  17. #  
  18. !IF "$(CFGSET)"== "FALSE"  
  19. !MESSAGE Usage: nmake /f Makefile.vc [<config>] [<target>]        
  20. !MESSAGE  
  21. !MESSAGE where <config> is one of:  
  22. !MESSAGE -  release=1               - build release version  
  23. !MESSAGE -  debug=1                 - build debug version  
  24. !MESSAGE  
  25. !MESSAGE <target> may be:  
  26. !MESSAGE -  clean                 - clear output file  
  27. !MESSAGE  
  28. !MESSAGE  
  29. !ERROR please choose a valid configuration instead"  
  30. !ENDIF  
  31. #這裡增加了一個輸出:$(OUTDIR)  
  32. all: $(OUTDIR) $(OUTDIR)\Win32Test.exe  
  33. #假如不存在$(OUTDIR)資料夾,就建立它  
  34. $(OUTDIR) :  
  35.  if not exist "$(OUTDIR)" mkdir $(OUTDIR)  
  36. clean:  
  37.        if exist $(OUTDIR) del $(OUTDIR)\*.ilk  
  38.        if exist $(OUTDIR) del $(OUTDIR)\*.obj  
  39.        if exist $(OUTDIR) del $(OUTDIR)\*.exe       
  40. # compile  
  41. $(OUTDIR)\stdafx.obj: stdafx.cpp  
  42.     cl -c  $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" stdafx.cpp   
  43. $(OUTDIR)\Win32Test.obj: Win32Test.cpp $(OUTDIR)\stdafx.obj  
  44.     cl -c  $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" Win32Test.cpp  
  45. # link  
  46. $(OUTDIR)\Win32Test.exe: $(OUTDIR)\Win32Test.obj  
  47.     link /machine:x86 /INCREMENTAL:YES /NOLOGO /subsystem:WINDOWS /out:$(OUTDIR)\Win32Test.exe $(OUTDIR)\Win32Test.obj kernel32.lib user32.lib  

           我們執行一下這個Makefile: nmake /f makefile.vc debug=1

發現在Debug目錄下確實生成了一個Win32Test.exe,但是我們雙擊它,卻無法執行起來,顯然是缺少了一個資源生成檔案,即res檔案。編譯res檔案需要用到編譯工具rc.exe。rc.exe的常用引數有如下:

/n  —— 在字串表(一種資源型別)中的所有字元都將有0結束符

/v  —— 顯示編譯器在編譯過程中輸入的資訊

/fo —— 指定res輸出檔案的檔名

    其它的引數可以通過命令rc.exe /?來查詢。

    那麼讓我們再新增編譯資原始檔這一部分吧(下面紅色部分的就是新增和修改部分):

  1. #設定編譯標記,初始化為FALSE  
  2. CFGSET     =  FALSE  
  3. #定義debug版本的前處理器  
  4. CCDEBUG    = -DWIN32 -D_DEBUG <span style="color:#FF0000;">-D_WINDOWS</span>  
  5. #定義release版本的前處理器  
  6. CCNODBG    = -DWIN32 -D_NDEBUG <span style="color:#FF0000;">-D_WINDOWS</span>  
  7. !IFDEF debug  
  8. CC         = $(CCDEBUG)  
  9. OUTDIR = .\Debug  
  10. CFGSET     =  TRUE  
  11. !ELSE IFDEF release  
  12. CC         = $(CCNODBG)  
  13. OUTDIR = .\Release  
  14. CFGSET     =  TRUE  
  15. !ENDIF  
  16. # 提示用法  
  17. #  
  18. !IF "$(CFGSET)"== "FALSE"  
  19. !MESSAGE Usage: nmake /f Makefile.vc [<config>] [<target>]        
  20. !MESSAGE  
  21. !MESSAGE where <config> is one of:  
  22. !MESSAGE -  release=1               - build release version  
  23. !MESSAGE -  debug=1                 - build debug version  
  24. !MESSAGE  
  25. !MESSAGE <target> may be:  
  26. !MESSAGE -  clean                 - clear output file  
  27. !MESSAGE  
  28. !MESSAGE  
  29. !ERROR please choose a valid configuration instead"  
  30. !ENDIF  
  31. #這裡增加了一個輸出:$(OUTDIR)  
  32. all: $(OUTDIR) $(OUTDIR)\Win32Test.exe  
  33. #假如不存在$(OUTDIR)資料夾,就建立它  
  34. $(OUTDIR) :  
  35.  if not exist "$(OUTDIR)" mkdir $(OUTDIR)  
  36. clean:  
  37.        if exist $(OUTDIR) del $(OUTDIR)\*.ilk  
  38.        if exist $(OUTDIR) del $(OUTDIR)\*.obj  
  39.        if exist $(OUTDIR) del $(OUTDIR)\*.exe       
  40.        if exist $(OUTDIR) del $(OUTDIR)\*.res      
  41. # compile  
  42. $(OUTDIR)\stdafx.obj: stdafx.cpp  
  43.     cl -c  $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" stdafx.cpp   
  44. $(OUTDIR)\Win32Test.obj: Win32Test.cpp $(OUTDIR)\stdafx.obj  
  45.     cl -c  $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" Win32Test.cpp  
  46. # compile resource script  
  47.    <span style="color:#FF0000;"> rc.exe /n /v /fo $(OUTDIR)\Win32Test.res Win32Test.rc</span>  
  48. # link  
  49. $(OUTDIR)\Win32Test.exe: $(OUTDIR)\Win32Test.obj  
  50.     link /machine:x86 /INCREMENTAL:YES /NOLOGO <span style="color:#FF0000;">/subsystem:WINDOWS</span> /out:$(OUTDIR)\Win32Test.exe $(OUTDIR)\Win32Test.obj $(OUTDIR)\Win32Test.res kernel32.lib <span style="color:#FF0000;">user32.lib</span>  

 讓我們再搞得高階一些,用Makefile編譯一個MFC工程(基於對話方塊)——DlgTest。具體的Makefile程式碼如下:
  1. #設定編譯標記,初始化為FALSE  
  2. CFGSET     =  FALSE  
  3. #定義debug版本的前處理器  
  4. CCDEBUG    = -DWIN32 -D_DEBUG -D_WINDOWS  
  5. #定義release版本的前處理器  
  6. CCNODBG    = -DWIN32 -D_NDEBUG -D_WINDOWS  
  7. !IFDEF debug  
  8. CC         = $(CCDEBUG)  
  9. OUTDIR = .\Debug  
  10. CFGSET     =  TRUE  
  11. !ELSE IFDEF release  
  12. CC         = $(CCNODBG)  
  13. OUTDIR = .\Release  
  14. CFGSET     =  TRUE  
  15. !ENDIF  
  16. # 提示用法  
  17. #  
  18. !IF "$(CFGSET)"== "FALSE"  
  19. !MESSAGE Usage: nmake /f Makefile.vc [<config>] [<target>]        
  20. !MESSAGE  
  21. !MESSAGE where <config> is one of:  
  22. !MESSAGE -  release=1               - build release version  
  23. !MESSAGE -  debug=1                 - build debug version  
  24. !MESSAGE  
  25. !MESSAGE <target> may be:  
  26. !MESSAGE -  clean                 - clear output file  
  27. !MESSAGE  
  28. !MESSAGE  
  29. !ERROR please choose a valid configuration instead"  
  30. !ENDIF  
  31. #這裡增加了一個輸出:$(OUTDIR)  
  32. all: $(OUTDIR) $(OUTDIR)\DlgTest.exe  
  33. #假如不存在$(OUTDIR)資料夾,就建立它  
  34. $(OUTDIR) :  
  35.  if not exist "$(OUTDIR)" mkdir $(OUTDIR)  
  36. clean:  
  37.        if exist $(OUTDIR) del $(OUTDIR)\*.ilk  
  38.        if exist $(OUTDIR) del $(OUTDIR)\*.obj  
  39.        if exist $(OUTDIR) del $(OUTDIR)\*.exe       
  40.        if exist $(OUTDIR) del $(OUTDIR)\*.res      
  41. # compile  
  42. $(OUTDIR)\stdafx.obj: stdafx.cpp  
  43.     cl -c  $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" stdafx.cpp   
  44. $(OUTDIR)\DlgTest.obj: DlgTest.cpp $(OUTDIR)\stdafx.obj  
  45.     cl -c  $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" DlgTest.cpp  
  46. $(OUTDIR)\DlgTestDlg.obj: DlgTestDlg.cpp $(OUTDIR)\stdafx.obj  
  47.     cl -c  $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" DlgTestDlg.cpp  
  48. # compile resource script  
  49.     rc.exe /n /v /fo $(OUTDIR)\DlgTest.res DlgTest.rc  
  50. # link  
  51. $(OUTDIR)\DlgTest.exe: $(OUTDIR)\DlgTest.obj $(OUTDIR)\DlgTestDlg.obj  
  52.     link /machine:x86 /INCREMENTAL:YES /NOLOGO /subsystem:WINDOWS /out:$(OUTDIR)\DlgTest.exe $(OUTDIR)\DlgTest.obj $(OUTDIR)\DlgTestDlg.obj $(OUTDIR)\DlgTest.res kernel32.lib user32.lib  

         和Win32應用程式的Makefile比較可以知道,MFC程式的Makefile和Win 32GUI程式的步驟和過程基本一致。

         Windows平臺下Makefile學習就此告一段落了,你學會了嗎?

參考文獻:

1. 精通Windows API,範文慶、周彬彬、安靖編著