CL.exe 是控制 Microsoft C 和
C++ 編譯器與連結器的 32 位工具。編譯器産生通用對象檔案格式 (COFF) 對象
(.obj) 檔案。連結器産生可執行檔案 (.exe) 或動态連結庫檔案 (DLL)。
注意,所有編譯器選項都區分大小寫。
若要編譯但不連結,請使用 /c。
使用 NMAKE 生成輸出檔案。
使用 BSCMAKE 支援類浏覽。
以下是一個完整的編譯器選項分類清單。
優化
選項 作用
/O1 建立小代碼
/O2 建立快速代碼
/Oa 假設沒有别名
/Ob 控制内聯展開
/Od 禁用優化
/Og 使用全局優化
/Oi 生成内部函數
/Op 改善浮點數一緻性
/Os 代碼大小優先
/Ot 代碼速度優先
/Ow 假定在函數調用中使用别名
/Ox 使用最大優化 (/Ob1gity /Gs)
/Oy 省略架構指針
代碼生成
/clr 啟用 C++ 的托管擴充并産生在公共語言運作庫上運作的輸出檔案
/EH 指定異常處理模型
/G3 優化代碼以優選 386 處理器。在
Visual C++ 5.0 中已經停用,編譯器将忽略此選項
/G4 優化代碼以優選 486 處理器。在
/G5 優化代碼以優選 Pentium
/GB 與 /G6 等效;将
_M_IX86 的值設定為 600
/Gd 使用 __cdecl 調用約定
/Ge 激活堆棧探測
/GF
/GF 啟用字元串池
/GH 調用挂鈎函數 _penter
/GH 調用挂鈎函數 _pexit
/GL 啟用全程式優化
/Gm 啟用最小重新生成
/Gr 啟用運作時類型資訊 (RTTI)
/Gr 使用 __fastcall 調用約定
/GS 控制堆棧探測
/GT 支援使用靜态線程本地存儲區配置設定的資料的纖程安全
/GX 啟用同步異常處理
/Gy 啟用函數級連結
/GZ 使用 __stdcall 調用約定
/MD 使用 MSVCRT.lib 建立多線程
DLL
/MDd 使用 MSVCRTD.lib 建立調試多線程
/ML 使用 LIBC.lib 建立單線程可執行檔案
/MLd 使用 LIBCD.lib 建立調試單線程可執行檔案
/MT 使用 LIBCMT.lib 建立多線程可執行檔案
/MTd 使用 LIBCMTD.lib 建立調試多線程可執行檔案
輸出檔案
/FA
/FA 建立清單檔案
設定清單檔案名
/Fd 重命名程式資料庫檔案
/Fe 重命名可執行檔案
/Fm 建立映射檔案
/Fo 建立對象檔案
/Fp 指定預編譯頭檔案名
/FR
/FR 生成浏覽器檔案
/Fx 将插入的代碼與源檔案合并
調試
/GS 緩沖區安全檢查
/GZ 與 /RTC1 相同
/RTC 啟用運作時錯誤檢查
/Wp64 檢測 64 位可移植性問題
/Yd 将完整的調試資訊放在所有對象檔案中
/Yl 建立調試庫時插入 PCH 引用
/Z7 生成與 C 7.0 相容的調試資訊
/Zd 生成行号
/Zi 生成完整的調試資訊
預處理器
/AI 指定在解析傳遞到#using 指令的檔案引用時搜尋的目錄
/c 在預處理期間保留注釋
/D 定義常數和宏
/E 将預處理器輸出複制到标準輸出
/EP 将預處理器輸出複制到标準輸出
/Fl 預處理指定的包含檔案
/FU 強制使用檔案名,就像它已被傳遞到#using 指令一樣
/I 在目錄中搜尋包含檔案
/P 将預處理器輸出寫入檔案
/U 移除預定義宏
/U 移除所有的預定義宏
/X 忽略标準包含目錄
/ZI 将調試資訊包含在與“編輯并繼續”相容的程式資料庫中
語言
/noBool 取消 C++ bool、true 和
false 關鍵字
/vd 取消或啟用隐藏的 vtordisp 類成員
/vmb 對指向成員的指針使用最佳的基
/vmg 對指向成員的指針使用完全一般性
/vmm 聲明多重繼承
/vms 聲明單一繼承
/vmv 聲明虛拟繼承
/Za 禁用語言擴充
/Zc 在 /Ze 下指定标準行為
/Ze 啟用語言擴充
/Zg 生成函數原型
/Zl 從 .obj 檔案中移除預設庫名
/Zp n 封裝結構成員
/Zs 隻檢查文法
連結
/F 設定堆棧大小
/LD 建立動态連結庫
/LDd 建立調試動态連結庫
/link 将指定的選項傳遞給 LINK
/MD 使用 MSVCRT.lib 編譯以建立多線程
/MDd 使用 MSVCRTD.lib 編譯以建立調試多線程
/ML 使用 LIBC.lib 編譯以建立單線程可執行檔案
/MLd 使用 LIBCD.lib 編譯以建立調試單線程可執行檔案
/MT 使用 LIBCMT.lib 編譯以建立多線程可執行檔案
/MTd 使用 LIBCMTD.lib 編譯以建立調試多線程可執行檔案
預編譯頭
/Y- 忽略目前生成中的所有其他預編譯頭編譯器選項
/Yc 建立預編譯頭檔案
/Yu 在生成期間使用預編譯頭檔案
/YX 自動處理預編譯頭
雜項
@ 指定響應檔案
/? 列出編譯器選項
/c 編譯但不連結
/H 限制外部(公共)名稱的長度
/HELP 列出編譯器選項
/J 更改預設的 char 類型
/NOLOGO 取消顯示登入版權标志
/QI0f 確定 Pentium 0F 指令沒有問題
/QIfdiv FDIV、FPREM、FPTAN 和
FPATAN 指令有缺陷的 Intel Pentium 微處理器的變通方法
QIfist 當需要從浮點類型轉換為整型時取消 Helper 函數
_ftol 的調用
/showIncludes 在編譯期間顯示所有包含檔案的清單
/Tc
/Tc 指定 C 源檔案
/Tp
/Tp 指定 C++ 源檔案
/V 設定版本字元串
/w 設定警告等級
/w 禁用所有警告
/Wall 啟用所有警告,包括預設情況下禁用的警告
/WL 在從指令行編譯 C++ 源代碼時啟用錯誤資訊和警告消息的單行診斷
/Zm 設定編譯器的記憶體配置設定限制
CL 指令行使用下列文法:
CL [option...] file... [option | file]... [lib...] [@command-file] [/link link-opt...]
下表說明CL 指令的輸入項意義
option 一個或多個 CL 選項。請注意,所有選項都應用于所有指定的源檔案。選項是由一個正斜杠
(/) 或一個短劃線 (–) 指定的。如果某個選項帶有參數,則該選項的說明指定在選項和參數之間是否允許有空格。選項名(/HELP 選項除外)區分大小寫。有關更多資訊,請參閱
CL 選項的順序。
file 一個或多個源檔案、.obj 檔案或庫的名稱。CL 編譯源檔案并将
.obj 檔案和庫的名稱傳遞給連結器。有關更多資訊,請參閱 CL 檔案名文法。
lib 一個或多個庫名。CL 将這些名稱傳遞給連結器。
command-file 包含多個選項和檔案名的檔案。有關更多資訊,請參閱 CL 指令檔案。
link-opt 一個或多個連結器選項。CL 将這些選項傳遞給連結器。
您可以指定任意數目的選項、檔案名和庫名,條件是指令行上的字元數不超過 1024,該限制是作業系統指定的。
<a target="_blank" href="http://www.52rd.com/Blog/Detail_RD.Blog_zjhfqq_13084.html">vc 編譯連接配接選項(</a>
大家可能一直在用VC開發軟體,但是對于這個編譯器卻未必很了解。原因是多方面的。大多數情況下,我們隻停留在“使用”它,而不會想去“了解”它。因為它隻是一個工具,我們甯可把更多的精力放在C++語言和軟體設計上。我們習慣于這樣一種“模式”:建立一個項目,然後寫代碼,然後編譯,反反複複調試。但是,所謂:“公欲善其事,必先利其器”。如果我們精于VC開發環境,我們是不是能夠做得更加遊刃有餘呢?
閑話少說。我們先來看一下VC的處理流程,大緻分為兩步:編譯和連接配接。源檔案通過編譯生成了.obj檔案;所有.obj檔案和.lib檔案通過連接配接生成.exe檔案或.dll檔案。下面,我們分别讨論這兩個步驟的一些細節。
編譯參數的設定。主要通過VC的菜單項Project->Settings->C/C++頁來完成。我們可以看到這一頁的最下面Project
Options中的内容,一般如下:
/nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_M
BCS" /Fp"Debug/WritingDlgTest.pch" /Yu"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
各個參數代表的意義,可以參考Msdn。比如/nologo表示編譯時不在輸出視窗顯示這些設定(我們可以把這個參數去掉來看看效果)等等。一般我們不會直接修改這些設定,而是通過這一頁最上面的Category中的各項來完成。
1) General:一些總體設定。Warning level用來控制警告資訊,其中Level
1是最嚴重的級别;Warnings as errors将警告資訊當作錯誤處理;Optimizations是代碼優化,可以在Category的Optimizations項中進行更細的設定;Generate
browse info用以生成.sbr檔案,記錄類、變量等符号資訊,可以在Category的Listing
Files項中進行更多的設定。Debug info,生成調試資訊:None,不産生任何調試資訊(編譯比較快);Line
Numbers Only,僅生成全局的和外部符号的調試資訊到.OBJ檔案或.EXE檔案,減小目标檔案的尺寸;C
7.0- Compatible,記錄調試器用到的所有符号資訊到.OBJ檔案和.EXE檔案;Program
Database,建立.PDB檔案記錄所有調試資訊;Program Database for "Edit & Continue",建立.PDB檔案記錄所有調試資訊,并且支援調試時編輯。
2) C++ Language:pointer_to_member representation用來設定類定義/引用的先後關系,一般為Best-Case
Always表示在引用類之前該類肯定已經定義了;Enable Exception Handling,進行同步的異常處理;Enable
Run-Time Type Information迫使編譯器增加代碼在運作時進行對象類型檢查;Disable Construction Displacements,設定類構造/析構函數調用虛函數問題。
3) Code Generation:Processor表示代碼指令優化,可以為80386、80486、Pentium、Pentium
Pro,或者Blend表示混合以上各種優化。Use run-time library用以指定程式運作時使用的運作時庫(單線程或多線程,Debug版本或Release版本),有一個原則就是,一個程序不要同時使用幾個版本的運作時庫。Single-Threaded,靜态連接配接LIBC.LIB庫;Debug
Single-Threaded,靜态連接配接LIBCD.LIB庫;Multithreaded,靜态連接配接LIBCMT.LIB庫;Debug
Multithreaded,靜态連接配接LIBCMTD.LIB庫;Multithreaded DLL,動态連接配接MSVCRT.DLL庫;Debug
Multithreaded DLL,動态連接配接MSVCRTD.DLL庫。連接配接了單線程庫就不支援多線程調用,連接配接了多線程庫就要求建立多線程的應用程式。
Calling convention可以用來設定調用約定,有三種:__cdecl、__fastcall和__stdcall。各種調用約定的主要差別在于,函數調用時,函數的參數是從左到右壓入堆棧還是從右到左壓入堆棧;在函數傳回時,由函數的調用者來清理壓入堆棧的參數還是由函數本身來清理;以及在編譯時對函數名進行的命名修飾(可以通過Listing
Files看到各種命名修飾方式)。Struct member alignment用以指定資料結構中的成員變量在記憶體中是按幾位元組對齊的,根據計算機資料總線的位數,不同的對齊方式存取資料的速度不一樣。這個參數對資料包網絡傳輸等應用尤為重要,不是存取速度問題,而是資料位的精确定義問題,一般在程式中使用#pragma
pack來指定。
4) Customize:Disable Language Extensions,表示不使用微軟為标準C做的語言擴充;Eliminate
Duplicate Strings,主要用于字元串優化(将字元串放到緩充池裡以節省空間),使用這個參數,使得
char *sBuffer = "This is a character buffer";
char *tBuffer = "This is a character buffer";
sBuffer和tBuffer指向的是同一塊記憶體空間;Enable
Function-Level Linking ,告訴編譯器将各個函數按打包格式編譯;Enables minimal rebuild,通過儲存關聯資訊到.IDB檔案,使編譯器隻對最新類定義改動過的源檔案進行重編譯,提高編譯速度;Enable
Incremental Compilation,同樣通過.IDB檔案儲存的資訊,隻重編譯最新改動過的函數;Suppress
Startup Banner and Information Messages,用以控制參數是否在output視窗輸出。
5) Listing Files:Generate browse info的功能上面已經提到過。這裡可以進行更多的設定。Exclude
Local Variables from Browse Info表示是否将局部變量的資訊放到.SBR檔案中。Listing
file type可以設定生成的清單資訊檔案的内容:Assembly-Only Listing僅生成彙編代碼檔案(.ASM擴充名);Assembly
With Machine Code生成機器代碼和彙編代碼檔案(.COD擴充名);Assembly With Source
Code生成源代碼和彙編代碼檔案(.ASM擴充名);Assembly, Machine Code,and Source生成機器碼、源代碼和彙編代碼檔案(.COD擴充名)。Listing
file name為生成的資訊檔案的路徑,一般為Debug或Release目錄下,生成的檔案名自動取源檔案的檔案名。
6) Optimizations:代碼優化設定。可以選擇Maximize Speed生成最快速的代碼,或Minimize
Size生成最小尺寸的程式,或者Customize定制優化。定制的内容包括:
Assume No Aliasing,不使用别名(提高速度);
Assume Aliasing Across Function Calls,僅函數内部不使用别名;
Global Optimizations,全局優化,比如經常用到的變量使用寄存器儲存,或者循環内的計算優化,如
i = -100;
while( i < 0 ){ i += x + y;}
會被優化為
t = x + y;
while( i < 0 ){i += t;}
Generate Intrinsic Functions,使用内部函數替換一些函數調用(提高速度);
Improve Float Consistency,浮點運算方面的優化;
Favor Small Code,程式(exe或dll)尺寸優化優先于代碼速度優化;
Favor Fast Code,程式(exe或dll)代碼速度優化優先于尺寸優化;
Frame-Pointer Omission,不使用幀指針,以提高函數調用速度;
Full Optimization,組合了幾種參數,以生成最快的程式代碼。
Inline function expansion,内聯函數擴充的三種優化(使用内聯可以節省函數調用的開銷,加快程式速度):Disable不使用内聯;Only
__inline,僅函數定義前有inline或__inline标記使用内聯;Any
Suitable,除了inline或__inline标記的函數外,編譯器“覺得”應該使用内聯的函數,都使用内聯。
7) Precompiled Headers:預編譯頭檔案的設定。使用預編譯可以提高重複編譯的速度。VC一般将一些公共的、不大變動的頭檔案(比如afxwin.h等)集中放到stdafx.h中,這一部分代碼就不必每次都重新編譯(除非是Rebuild
All)。
8) Preprocessor:預編譯處理。可以定義/解除定義一些常量。Additional
include directories,可以指定額外的包含目錄,一般是相對于本項目的目錄,如../Include。
連接配接參數的設定。主要通過VC的菜單項Project->Settings->Link頁來完成。我們可以看到這一頁的最下面Project
/nologo /subsystem:windows /incremental:yes /pdb:"Debug/WritingDlgTest.pdb" /debug /machi
ne:I386 /out:"Debug/WritingDlgTest.exe" /pdbtype:sept
下面我們分别來看一下Category中的各項設定。
1) General:一些總體設定。可以設定生成的檔案路徑、檔案名;連接配接的庫檔案;Generate debug info,生成Debug資訊到.PDB檔案(具體格式可以在Category->Debug中設定);Ignore
All Default Libraries,放棄所有預設的庫連接配接;Link Incrementally,通過生成. ILK檔案實作遞增式連接配接以提高後續連接配接速度,但一般這種方式下生成的檔案(EXE或DLL)較大;Generate
Mapfile,生成.MAP檔案記錄子產品相關資訊;Enable Profiling,這個參數通常與Generate
Mapfile參數同時使用,而且如果産生Debug資訊的話,不能用.PDB檔案,而且必須用Microsoft
Format。
2) Customize:這裡可以進行使用程式資料庫檔案的設定。Force File Output,強制産生輸出檔案(EXE或DLL);Print
Progress Messages,可以将連接配接過程中的進度資訊輸出到Output視窗。
3) Debug:設定是否生成調試資訊,以及調試資訊的格式。格式可以有Microsoft Format、COFF
Format(Common Object File Format)和Both Formats三種選擇;Separate
Types,表示将Debug格式資訊以獨立的.PDB檔案存放,還是直接放在各個源檔案的.PDB檔案中。選中的話,表示采用後者的方式,這種方式調試啟動比較快。
4) Input:這裡可以指定要連接配接的庫檔案,放棄連接配接的庫檔案。還可以增加額外的庫檔案目錄,一般是相對于本項目的目錄,如../Lib。Force
Symbol References,可以指定連接配接特定符号定義的庫。
5) Output:Base Address可以改變程式預設的基位址(EXE檔案預設為0x400000,DLL預設為x10000000),作業系統裝載一個程式時總是試着先從這個基位址開始。Entry-Point
Symbol可以指定程式的入口位址,一般為一個函數名(且必須采用__stdcall調用約定)。一般Win32的程式,EXE的入口為WinMain,DLL的入口為DllEntryPoint;最好讓連接配接器自動設定程式的入口點。預設情況下,通過一個C的運作時庫函數來實作:控制台程式采用mainCRTStartup
(或wmainCRTStartup)去調用程式的main (或wmain)函數;Windows程式采用WinMainCRTStartup
(或 wWinMainCRTStartup)調用程式的WinMain (或
wWinMain,必須采用__stdcall調用約定);DLL采用_DllMainCRTStartup調用DllMain函數(必須采用__stdcall調用約定)。Stack
allocations,用以設定程式使用的堆棧大小(請使用十進制),預設為1兆位元組。Version Information告訴連接配接器在EXE或DLL檔案的開始部分放上版本号。
值得注意的是,上面各個參數是大小寫敏感的;在參數後加上“-”表示該參數無效;各個參數值選項
有“*”的表示為該參數的預設值;可以使用頁右上角的“Reset”按鈕來恢複該頁的所有預設設定。
其它一些參數設定
1) Project->Settings->General,可以設定連接配接MFC庫的方式(靜态或動态)。如果是動态連
接,在你的軟體釋出時不要忘了帶上MFC的DLL。
2) Project->Settings->Debug,可以設定調試時運作的可執行檔案,以及指令行參數等。
3) Project->Settings->Custom Build,可以設定編譯/連接配接成功後自動執行一些操作。比較有
用的是,寫COM時希望VC對編譯通過的COM檔案自動注冊,可以如下設定:
Description: Register COM
Commands: regsvr32 /s /c $(TargetPath)
echo regsvr32 exe.time > $(TargetDir)/$(TargetName).trg
Outputs: $(TargetDir)/$(TargetName).trg
4) Tools->Options->Directories,設定系統的Include、Library路徑。
一些小竅門
1) 有時候,你可能在編譯的時候,計算機突然非法關機了(可能某人不小心碰了電源或你的記憶體不穩定等原因)。當你重新開機機器後打開剛才的項目,重新進行編譯,發現VC會崩掉。你或許以為你的VC編譯器壞了,其實不然(你試試編譯其它項目,還是好的!),你隻要将項目的.ncb、.opt、.aps、.clw檔案以及Debug、Release目錄下的所有檔案都删掉,然後重新編譯就行
了。
2) 如果你想與别人共享你的源代碼項目,但是把整個項目做拷貝又太大。你完全可以删掉以下檔案:.dsw、.ncb、.opt、.aps、.clw、.
plg檔案以及Debug、Release目錄下的所有檔案。
3) 當你的Workspace中包含多個Project的時候,你可能不能直覺地、一眼看出來哪個是目前項目。可以如下設定:Tools->Options->Format,然後在Category中選擇Workspace
window,改變其預設的字型(比如設成Fixedsys)就行了。
4) 如何給已有的Project改名字?将該Project關掉。然後以文本格式打開.dsp檔案,替換原來的Project名字即可。
5) VC6對類成員的智能提示功能很有用,但有時候會失靈。你可以先關掉項目,将.clw和.ncb删掉,然後重新打開項目,點選菜單項View->ClassWizard,在彈出的對話框中按一下“Add
All”按鈕;重新Rebuild All。應該可以解決問題。