Windows平臺下Makefile學習筆記(二)
作者:朱金燦
上次我們學習了怎麼用Makefile編譯一個控制檯工程。這次我們學習一下如何使用Makefile來編譯一個win 32的GUI程式。win 32的GUI程式其編譯過程大部分和控制檯程式一樣,不同的是多了一步RC編譯器將資原始檔編譯成res檔案,然後在最後一步連結中需要把這個res檔案連結到exe檔案中。
好,現在讓我們在實踐中學習吧。新建一個win32 應用程式工程——Win32Test。讓我們先完成C++程式碼部分的Makefile的編寫,還記得Makefile的原則是以終為始嗎?忘記了就翻翻上一篇:Windows平臺下Makefile學習筆記(一)
- #設定編譯標記,初始化為FALSE
- CFGSET = FALSE
- #定義debug版本的前處理器
- CCDEBUG = -DWIN32 -D_DEBUG -D_WINDOWS
- #定義release版本的前處理器
- CCNODBG = -DWIN32 -D_NDEBUG -D_WINDOWS
- !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)\Win32Test.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)\Win32Test.obj: Win32Test.cpp $(OUTDIR)\stdafx.obj
- cl -c $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" Win32Test.cpp
- # link
- $(OUTDIR)\Win32Test.exe: $(OUTDIR)\Win32Test.obj
- 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 /?來查詢。
那麼讓我們再新增編譯資原始檔這一部分吧(下面紅色部分的就是新增和修改部分):
- #設定編譯標記,初始化為FALSE
- CFGSET = FALSE
- #定義debug版本的前處理器
- CCDEBUG = -DWIN32 -D_DEBUG <span style="color:#FF0000;">-D_WINDOWS</span>
- #定義release版本的前處理器
- CCNODBG = -DWIN32 -D_NDEBUG <span style="color:#FF0000;">-D_WINDOWS</span>
- !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)\Win32Test.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
- if exist $(OUTDIR) del $(OUTDIR)\*.res
- # compile
- $(OUTDIR)\stdafx.obj: stdafx.cpp
- cl -c $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" stdafx.cpp
- $(OUTDIR)\Win32Test.obj: Win32Test.cpp $(OUTDIR)\stdafx.obj
- cl -c $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" Win32Test.cpp
- # compile resource script
- <span style="color:#FF0000;"> rc.exe /n /v /fo $(OUTDIR)\Win32Test.res Win32Test.rc</span>
- # link
- $(OUTDIR)\Win32Test.exe: $(OUTDIR)\Win32Test.obj
- 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程式碼如下:
- #設定編譯標記,初始化為FALSE
- CFGSET = FALSE
- #定義debug版本的前處理器
- CCDEBUG = -DWIN32 -D_DEBUG -D_WINDOWS
- #定義release版本的前處理器
- CCNODBG = -DWIN32 -D_NDEBUG -D_WINDOWS
- !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)\DlgTest.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
- if exist $(OUTDIR) del $(OUTDIR)\*.res
- # compile
- $(OUTDIR)\stdafx.obj: stdafx.cpp
- cl -c $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" stdafx.cpp
- $(OUTDIR)\DlgTest.obj: DlgTest.cpp $(OUTDIR)\stdafx.obj
- cl -c $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" DlgTest.cpp
- $(OUTDIR)\DlgTestDlg.obj: DlgTestDlg.cpp $(OUTDIR)\stdafx.obj
- cl -c $(CC) -Istdafx.h /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" DlgTestDlg.cpp
- # compile resource script
- rc.exe /n /v /fo $(OUTDIR)\DlgTest.res DlgTest.rc
- # link
- $(OUTDIR)\DlgTest.exe: $(OUTDIR)\DlgTest.obj $(OUTDIR)\DlgTestDlg.obj
- 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,範文慶、周彬彬、安靖編著