windows下makefile命令詳解


轉自https://blog.csdn.net/xiexievv/article/details/45775005

1. 如果已經有vc6的dsp工程,可直接導出nmake腳本文件(.mak)

    “Project - Export Makefile...”

nmake -f nMakeTest.mak CFG="nMakeTest - Win32 Debug"

nmake -f nMakeTest.mak CFG="nMakeTest - Win32 Debug" all

nmake -f nMakeTest.mak CFG="nMakeTest - Win32 Release" clean

     注:如果未指定/F選項,則使用當前目錄下的名為makefile的文件

    【nmake /?】  獲取更多幫助!  vc6:【D:\program files\Microsoft Visual Studio\VC98\Bin】

                                             vs2008:【D:\program files\Microsoft Visual Studio 9.0\VC\bin】

     為了能正確地使用命令行工具及vc6或vs2008下的函數庫,需要對一些環境變量進行設置,最快捷地方式是通過如下方式打開命令行窗口(以vs2008為例):

     

2. vs的c++工程沒有提供導出nmake腳本文件的功能,我們只有借助工具或手動編寫nmake腳本文件了

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

3. rc.exe 【將.rc資源文本轉變成.res二進制文件】

/l 0x804  // 默認語言ID(十六進制數表示)  0x804:簡體中文  0x409:美國  更多...

/fo"nMakeTest.res"  // 指定rc文件輸出的res名稱

例:rc.exe /l 0x804 /fo"nMakeTest.res" /d "_DEBUG" /d "_AFXDLL" “nMakeTest.rc”

4. cl.exe 常見選項 【將.c,.cpp,.cxx編譯成obj文件】  更多...

/nologo   // 不打印版權申明信息

/I "../include"    // 添加頭文件查找路徑(如果路徑中帶有空格,一定要用引號括起來)

/DWIN32  // 預編譯宏定義(win32程序)

/D_CONSOLE  // 預編譯宏定義(控制台程序)

/D "_DEBUG"  // 預編譯宏定義(Debug版本)

/D_CRT_SECURE_NO_DEPRECATE  // 預編譯宏定義(關閉C4996警告。使用strcpy、strcat等不安全函數時會報C4996警告)

/D_CRT_NONSTDC_NO_DEPRECATE  // 預編譯宏定義(關閉C4996警告。使用strcpy、strcat等不安全函數時會報C4996警告)

/Od  // 優化選項:帶入Debug信息

/O2  // 優化選項:最快速度

/O1  // 優化選項:最小尺寸

/W3  // 設置3級警告級別

/WX     // 將Warining視為error

/Fp"nMakeTest.pch"  // 指定預編譯文件名

/Yu"stdafx.h"   // 在生成期間使用預編譯頭文件

/FI "myheader.h" // 在每個源文件的第一行上的#include該文件

/Fd"vcpdb/testpdb" // 會將vc輔助編譯的idb及pdb文件(見下面的/Gm選項)輸入到vcpdb目錄中,

                               並重命名為testpdb.idb與testpdb.pdb(這里的pdb為project database文件,用於存工程的數據庫信息)

/Fo"objFiles" // 將obj文件輸出到objFiles目錄中

/c   // 編譯但不鏈接

/feMyTest  // 編譯后,輸出MyTest.exe可執行文件

/EHsc   // 打開"C++例外(Exceptions)",以免出現編譯器警告

/LD   // 創建動態鏈接庫 
/LDd   // 創建調試動態鏈接庫

/ML   // 使用 libc.lib 創建單線程可執行文件 
/MLd    // 使用 libcd.lib 創建調試單線程可執行文件 
/MT    // 使用 libcmt.lib 創建多線程可執行文件 
/MTd    // 使用 libcmtd.lib 創建調試多線程可執行文件 
/MD    // 使用 msvcrt.lib/msvcrt.dll 創建多線程可執行文件
/MDd    // 使用 msvcrtd.lib/msvcrtd.dll創建調試多線程可執行文件

/Z7   //生成與 C7.0兼容的調試信息 
/Zd   //生成行號 
/Zi    //生成完整的調試信息

/Gm     // 啟用最小重新生成 

          編譯器在.idb文件中存儲源文件和類定義之間的依賴關系。
          使用.idb 文件的信息來確定是否需要編譯某個源文件。
          而不是該源文件只要包含了被修改的.h文件,就必須重新編譯。

/link  // 將/link后指定的選項傳遞給link.exe

// 默認情況下,cl.exe編譯完后,會自動調用link.exe進行連接,
// 所以直接用cl.exe編譯帶main函數的.c或.cpp后,會生成obj與exe文件。

例:cl /c test1.cpp test2.cpp  // 編譯test1.cpp,test2.cpp

例:cl *.cpp /MD /c /I"G:\Visual C++\VC98\PlatformSDK\Include"

5. link.exe常見選項  【將obj、lib、res鏈接成dll或exe等可執行文件】

/dll  // 輸出dll文件

-lib  // 生成lib靜態庫文件  例:link -lib *.obj /out:test.lib 

/libpath:"..\PublicSDK\lib" // 指定外部lib查找路徑(路徑中不能帶有空格,否則鏈接時會報LNK1181的錯誤)

/subsystem:windows[console]   // 指定子系統

/machine 指定目標平台{AM33|ARM|EBC|IA64|M32R|MIPS|SH3|SH3DSP|SH4|SH5|THUMB|X86|X64},等

/NODEFAULTLIB:libcd.lib  // 鏈接時,忽略libcd.lib庫

/debug  // 生成調試信息

/export:myAdd=_Add,@1   // 導出extern "C" Add函數,並將符號名修改為myAdd,同時將導出序號設為1(一種dll動態庫導出符號的方法)

/export:_g_isTest,@2   // 導出extern "C" g_isTest變量,並將導出序號設為2(一種dll動態庫導出符號的方法)

/def:"nMakeTest.def" // 模塊導出文件【如果def文件名稱與dll名稱一致,則不需要顯示地指出】(另外一種dll動態庫導出符號的方法)

;nMakeTest.lib 導出DLL函數
;作者:kekec
LIBRARY nMakeTest.def
EXPORTS
Add @ 1
g_isTest @ 2

注:還可以在代碼中使用__declspec(dllexport)進行符號的導出

#ifdef WIN32DLL_EXPORTS
#define WIN32DLL_API __declspec(dllexport)
#else
#define WIN32DLL_API __declspec(dllimport)
#endif

/************** export.c ***************/ 
#ifdef __cplusplus
extern "C"
{
#endif
    WIN32DLL_API int __stdcall Add(int a, int b)
    {
        return (a + b);
    }

    WIN32DLL_API int g_isTest = 0;
#ifdef __cplusplus
}
#endif

/pdb:"nMakeTest.pdb"  // 重命名生成的pdb文件(Program Debug Database),保存調試符號等信息

/map:"nMakeTest.map" // 重命名生成的map文件

/out:"nMakeTest.exe" // 重命名生成的exe文件

/implib:"test.lib"  // 生成名為test.lib的導出庫

/entry:_DllMainCRTStartup@12   // 指定_DllMainCRTStartup函數dll的起始地址

/incremental:yes   // 開啟增量鏈接

          incremental開關默認是開啟的。
          開啟增量鏈接產生的exe或dll文件的size要大一些。
          因為有代碼和數據的填充,增量鏈接的exe或dll文件會包含跳轉trunk來處理函數重定位到新地址。 
          MSDN上明確指出:為確保最終發布版本不包含填充或者trunk,請關閉增量鏈接。

例:link gdiplus.lib /subsystem:windows /out:test.exe file1.obj file2.lib file3.res // 生成名為test.exe的windows可執行程序
例:link gdiplus.lib /subsystem:console /out:test.exe *.obj file2.lib file3.res // 生成名為test.exe的控制台可執行程序
例:link gdiplus.lib /subsytem:windows /dll /out:test.dll /implib:test.lib /def:test.def *.obj file2.lib file3.res // 生成名為test.dll動態庫

例:link *.obj rc.res /LIBPATH:"G:\Visual C++\lib" /SUBSYSTEM:WINDOWS /MACHINE:X86 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib OpenGL32.Lib

6. nmake指令說明

(1) 符號說明

     #   // 注釋符(命令所在行不能使用注釋符,命令應該與注釋都獨立使用一行進行書寫;如:erase nMakeTest.obj  # 刪除nMakeTest.obj文件【非法】)

     ^#abc  // 表示#abc這個字符串

     \  // 連接符,用於將兩行合並為一行;在宏中,分多行寫時,一定要用"\"進行連接

     %  // 文件說明符,表示其后的字符串為一文件名

---------------------

若文件名為 c:\prog.exe
%s 將為 c:\prog.exe 
%:F 將為 c:\prog.exe
%:dF 將為 c
%:pF 將為 c:\
%:fF 將為 prog
%:eF 將為 exe

---------------------

     @  // 命令修飾符;防止修飾的命令的結果,被打印出來

      !       // 命令修飾符

  $  // 宏引用符

      :  // 依賴符號

  ?【*】  // 通配符支持  

++++++++++++++++++++++++++++++++++++

     $@   // 表示所有目標全名(路徑+文件名稱+擴展名)的挨個值

     $$@  // 與$@用法含義一致,但僅在作為依賴項中的依賴項時有效

     $<   // 表示所有依賴目標的挨個值,僅在推理規則的命令中有效

     $^   // 表示所有依賴目標的集合,以空格分隔,若有重復,會被去重;

     $+   // 與$^含義一致,只是不進行去重處理。
     $?    // 表示所有比目標心的依賴目標的集合,以空格分隔

     $*    // 當前目標的路徑和文件名稱,沒有文件擴展名
     $**  // 當前目標的所有依賴項

----------------------------

修飾符   說明  
D         驅動器和目錄  
B         文件名稱  
F         文件名稱和擴展名  
R         驅動器、目錄和文件名稱

----------------------------

(2) 長文件名用雙引號引起來

  例:ALL : nMakeTest.dll  // 文件名較短時,可不需要引號
  例:ALL : "$(OUTDIR)\nMakeTest.exe" // 文件名較長時,特別是路徑中有空格的情況,一定要用引號

(3) 預定義規則

.c.obj    // 默認操作:cl /c $*.c

也可對默認操作顯示地重寫:

 

.c.obj:
    cl /c /Ox /DWIN32 $<

 

(4) 包含文件

!INCLUDE nmake.opt

include makefile.mak

(5) 條件判斷 - 01

!IF "$(CFG)" == ""
CFG=nMakeTest - Win32 Debug
!MESSAGE No configuration specified. Defaulting to nMakeTest - Win32 Debug.
!ELSE
!MESSAGE Be specified.
!ENDIF

(6) 條件判斷 - 02  【!IFNDEF   !IFDEF】

!IFNDEF PRIVATE_RUNTIMEMODE_DEBUG
RUNTIMEMODE_DEBUG = /MDd 
!ELSE
RUNTIMEMODE_DEBUG = $(PRIVATE_RUNTIMEMODE_DEBUG)
!ENDIF

(7) 輸出消息日志

!MESSAGE Invalid configuration "$(CFG)" specified.

(8) 描述塊 - makefile的核心 【注:在依賴項(或規則)和命令塊之間不能出現空行,commands之前為一個tab字符,多條command之間用;分割】

     只要dependences中任意一個文件比targets新,就執行commands命令

targets... : dependences...
  commands...

(9) ALL / CLEAN

OUTDIR=.\Release
INTDIR=.\Release
ALL : "$(OUTDIR)\nMakeTest.exe"
CLEAN :
  -@erase "$(INTDIR)\nMakeTest.obj"
  -@erase "$(INTDIR)\nMakeTest.pch"
  -@erase "$(INTDIR)\nMakeTest.res"
  -@erase "$(INTDIR)\nMakeTestDlg.obj"
  -@erase "$(INTDIR)\StdAfx.obj"
  -@erase "$(INTDIR)\vc60.idb"
  -@erase "$(OUTDIR)\nMakeTest.exe"
  -@erase "$(OUTDIR)\nMakeTest.map"
"$(OUTDIR)" :
  if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"

(10) 編譯

CPP=cl.exe
CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)\nMakeTest.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
.c{$(INTDIR)}.obj::
  $(CPP) @<<
  $(CPP_PROJ) $< 
<<
.cpp{$(INTDIR)}.obj::
  $(CPP) @<<
  $(CPP_PROJ) $< 
<<
.cxx{$(INTDIR)}.obj::
  $(CPP) @<<
  $(CPP_PROJ) $< 
<<

(11) 鏈接

LINK32=link.exe
LINK32_FLAGS=/nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)\nMakeTest.pdb" /map:"$(INTDIR)\nMakeTest.map" /machine:I386 /out:"$(OUTDIR)\nMakeTest.exe" 
LINK32_OBJS= \
  "$(INTDIR)\nMakeTest.obj" \
  "$(INTDIR)\nMakeTestDlg.obj" \
  "$(INTDIR)\StdAfx.obj" \
  "$(INTDIR)\nMakeTest.res"
"$(OUTDIR)\nMakeTest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
   $(LINK32) @<<
  $(LINK32_FLAGS) $(LINK32_OBJS)
<<

(12) 文件依賴

SOURCE=.\nMakeTest.cpp
"$(INTDIR)\nMakeTest.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\nMakeTest.pch"
SOURCE=.\nMakeTest.rc
"$(INTDIR)\nMakeTest.res" : $(SOURCE) "$(INTDIR)"
$(RSC) $(RSC_PROJ) $(SOURCE)

(13) 預編譯文件

SOURCE=.\StdAfx.cpp
!IF "$(CFG)" == "nMakeTest - Win32 Release"
CPP_SWITCHES=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)\nMakeTest.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
"$(INTDIR)\StdAfx.obj" "$(INTDIR)\nMakeTest.pch" : $(SOURCE) "$(INTDIR)"
  $(CPP) @<<
 $(CPP_SWITCHES) $(SOURCE)
<<
!ELSEIF "$(CFG)" == "nMakeTest - Win32 Debug"
CPP_SWITCHES=/nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)\nMakeTest.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
"$(INTDIR)\StdAfx.obj" "$(INTDIR)\nMakeTest.pch" : $(SOURCE) "$(INTDIR)"
  $(CPP) @<<
 $(CPP_SWITCHES) $(SOURCE)
<<
!ENDIF


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM