2010年2月2日 星期二

nmake 簡單教學

在Linux下使用的是make,而在Windows下使用的就是nmake啦!

在語法上,有一些不同,這裡留下一些記錄!

有很多語法跟在Linux下的make是相同的,可以參考Makefile - 簡單教學

!IFDEF
了解後面的變數是否有被定義,若有被定義的話,就執行後面要執行的指令!

!IFNDEF
了解後面的變數(可以是全域變數)是否有被定義,若有沒有被定義的話,就執行後面要執行的指令!

!IF
在後面的判斷式是否成立

!ENDIF
做為!IFDEF的結尾

!ELSE
!IF, !ENDIF一起使用的語法

!ELSEIF
是跟!IF!ELSEIF!ENDIF一起使用的,與!ELSE不同的是,後面可以接判斷式

!ERROR
顯示出後面的錯誤訊息,並且停止nmake的執行

!MESSAGE
顯示出後面的訊息,但與!ERROR的差別在於,並不會停止nmake的執行!

!INCLUDE
把後面接的檔案的內容貼到目前的位置上

!ELSEIFDEF
!ELSE IFDEF 的同義資料表。

!ELSEIFNDEF
!ELSE IFNDEF 的同義資料表。

!UNDEF macroname
取消定義 macroname。

而要讀取出變數的內容的話,則必需使用$()把它包起來!

下面就一個編譯.cpp的例子
food.hfood.cppmain.cpp請參考這裡
另外,要注意的一點是,這裡的[tab]指的是,一定要用tab鍵產生出來的,在linux的make,指令前一定要用[tab]鍵,但是,在nmake似乎沒有這一個限制,但是,基於習慣與相容性,我還是會用[tab]鍵。
mymake
# Program, flags, etc.
CC      = cl
CCFLAGS = /c
OBJ     = main.obj food.obj
TARGET  = main.exe

everything: $(TARGET)

clean:
[tab]del $(OBJ) $(TARGET)

all: clean everything

food.obj: food.cpp
[tab]$(CC) $(CCFLAGS) food.cpp /Fo$@

main.obj: main.cpp
[tab]$(CC)  $(CCFLAGS) main.cpp /Fo$@

main.exe: $(OBJ)
[tab]$(CC) $(OBJ) /Fe$@


而,可以透過隱含規則再簡化Makefile的內容,請參考Makefile - 簡單教學
# Program, flags, etc.
CC      = cl
CCFLAGS = /c
OBJ     = main.obj food.obj
TARGET  = main.exe
FLAGS   =

!IF "$(NAME)" == "koba"
!MESSAGE  You want to try Koba phase
FLAGS = /DKOBA
!ELSEIF "$(NAME)" == "caspar"
!MESSAGE  You want to try caspar phase
FLAGS = /DCASPAR
!ELSE
!MESSAGE  You want to try other phase
!ENDIF

everything: $(TARGET)

clean:
[tab]del $(OBJ) $(TARGET)

all: clean everything

.cpp.obj:
[tab]$(CC) $(CCFLAGS) $< /Fo$@ $(FLAGS)

$(TARGET): $(OBJ)
[tab]$(CC) $(OBJ) /Fe$@


這裡要注意的是,在Windows下的nmake與Linux下的make的語法確實有所不同!例如在隱含規則就有非常大的不同。可以參考Makefile - 簡單教學
像是$<(只能用在隱含規則中),而在make就沒有這一個限制!

可以執行以下的命令,看出輸出結果有所不同!
下面三個nmake指印選一個執行
$ nmake /f mymake all name=caspar
$ nmake /f mymake all name=koba
$ nmake /f mymake all

最後再執行編譯出來的結果

$ main.exe

[2011.09.18 補充]
!IF DEFINED(DATE) && DEFINED(TIME)
確認DATE與TIME變數同時有被定義

!IF EXIST(File.txt)
確認File.txt存在時,才做以以下被包住的程式碼

[2011.12.07 補充]
參考簡單的 nmake 使用的 Makefile 範例得知,nmake有一個替換功能
巨集替換

[2012.01.03 補充]
在nmake的指令中,如果要定義巨集有包含空格,請以引號括住這些定義。

這裡要解釋一下,

target : prerequisites
command

1. $@表示target的第一個名字,也就是代表目前的標的(target)
2. $**目前目標的所有相依性(一般linux下是用$^來表示
3. $?同一個規則的所有先決條件名,但是只有原始程式碼改過的比obj檔新才會符合,也就是比target還新的先決條件檔案。
4. $*同一個規則的第一個先決條件,但是不包含副檔名
5. $<具有比目前目標較晚之時間戳記的相依性檔案。只有在介面規則的命令中才有效。


參考資料:
nmake的用法
筆記:學習vc之cl, link, rc常用參數
命令行編譯工具NMAKE
對於.NET中的NMake和Makefile的理解
NMAKE Reference
[C++] nmake 最簡單範例
Nmake Tool
簡單的 nmake 使用的 Makefile 範例

沒有留言: