Vincents blog: Visual C 編譯器選項設置
VC6的參數設定是一門很深奧的學問,很少有書會去教怎麼設定,所以再寫程式的時候有時會遇到一些莫名的問題,搞了辦天才知道是參數沒設好。前一陣子收到同事寄的一些相關資料,其中關於vc6的參數設定寫的還蠻不錯的,值得參考。來源:中國IT實驗室編譯參數的設置。主要通過IDE的功能表項Project->Settings->C/C++頁來完成。我們可以看到這一頁的最下面Project Options中的內容,一般如下:/nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D"_WINDOWS" /D"_AFXDLL" /D "_MBCS" /Fp"Debug/WritingDlgTest.pch"/Yu"stdafx.h"/Fo"Debug/"/Fd"Debug/"/FD /GZ /c各個參數代表的意義,可以參考Msdn。比如/nologo表示編譯時不在輸出窗口顯示這些設置(我們可以把這個參數去掉來看看效果)等等。一般我們不會直接修改這些設置,而是通過這一頁最上面的Category中的各項來完成。(1)General:一些總體設置。Warning level用來控制警告資訊,其中Level 1是最嚴重的級別;Warnings aserrors將警告資訊當作錯誤處理;Optimizations是代碼優化,可以在Category的Optimizations項中進行更細的設置;Generate browse info用以生成.sbr文件,記錄類、變數等符號資訊,可以在Category的ListingFiles項中進行更多的設置。Debug info,生成調試資訊:None,不產生任何調試資訊(編譯比較快);Line NumbersOnly,僅生成全局的和外部符號的調試資訊到.OBJ文件或.EXE文件,減小目標文件的尺寸;C 7.0-Compatible,記錄調試器用到的所有符號資訊到.OBJ文件和.EXE文件;ProgramDatabase,創建.PDB文件記錄所有調試資訊;Program Database for "Edit &Continue",創建.PDB文件記錄所有調試資訊,並且支援調試時編輯。(2) C++ Language:pointer_to_memberrepresentation用來設置類定義/引用的先後關係,一般為Best-CaseAlways表示在引用類之前該類肯定已經定義了;Enable Exception Handling,進行同步的異常處理;EnableRun-Time Type Information迫使編譯器增加代碼在運行時進行對象類型檢查;Disable ConstructionDisplacements,設置類構造/析構函數調用虛函數問題。(3) Code Generation:Processor表示代碼指令優化,可以為80386、80486、Pentium、Pentium Pro,或者Blend表示混合以上各種優化。Userun-timelibrary用以指定程式運行時使用的運行時庫(單線程或多線程,Debug版本或Release版本),有一個原則就是,一個進程不要同時使用幾個版本的運行時庫。Single-Threaded,靜態連接LIBC.LIB庫;DebugSingle-Threaded,靜態連接LIBCD.LIB庫;Multithreaded,靜態連接LIBCMT.LIB庫;DebugMultithreaded,靜態連接LIBCMTD.LIB庫;Multithreaded DLL,動態連接MSVCRT.DLL庫;DebugMultithreadedDLL,動態連接MSVCRTD.DLL庫。連接了單線程庫就不支援多線程調用,連接了多線程庫就要求創建多線程的應用程式。Callingconvention可以用來設定調用約定,有三種:__cdecl、__fastcall和__stdcall。各種調用約定的主要區別在於,函數調用時,函數的參數是從左到右壓入堆棧還是從右到左壓入堆棧;在函數返回時,由函數的調用者來清理壓入堆棧的參數還是由函數本身來清理;以及在編譯時對函數名進行的命名修飾(可以通過Listing Files看到各種命名修飾方式)。Struct memberalignment用以指定數據結構中的成員變數在記憶體中是按幾位元組對齊的,根據電腦數據總線的位數,不同的對齊方式存取數據的速度不一樣。這個參數對數據包網路傳輸等應用尤為重要,不是存取速度問題,而是數據位的精確定義問題,一般在程式中使用#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 minimalrebuild,通過保存關聯資訊到.IDB文件,使編譯器只對最新類定義改動過的源文件進行重編譯,提高編譯速度;EnableIncremental Compilation,同樣通過.IDB文件保存的資訊,只重編譯最新改動過的函數;Suppress StartupBanner and Information Messages,用以控制參數是否在output窗口輸出。(5) Listing Files:Generatebrowse info的功能上面已經提到過。這裡可以進行更多的設置。Exclude Local Variables from BrowseInfo表示是否將局部變數的資訊放到.SBR文件中。Listing filetype可以設置生成的列表資訊文件的內容:Assembly-Only Listing僅生成彙編代碼文件(.ASM擴展名);AssemblyWith Machine Code生成機器代碼和彙編代碼文件(.COD擴展名);Assembly With SourceCode生成源代碼和彙編代碼文件(.ASM擴展名);Assembly, Machine Code,andSource生成機器碼、源代碼和彙編代碼文件(.COD擴展名)。Listing filename為生成的資訊文件的路徑,一般為Debug或Release目錄下,生成的文件名自動取源文件的文件名。(6)Optimizations:代碼優化設置。可以選擇Maximize Speed生成最快速的代碼,或Minimize Size生成最小尺寸的程式,或者Customize定製優化。定製的內容包括: Assume No Aliasing,不使用別名(提高速度); Assume Aliasing Across Function Calls,僅函數內部不使用別名; Global Optimizations,全局優化,比如經常用到的變數使用寄存器保存,或者迴圈內的計算優化,如 i = -100; while( i < i =" -100;" t =" x">Settings->Link頁來完成。我們可以看到這一頁的最下面Project Options中的內容,一般如下:/nologo /subsystem:windows /incremental:yes /pdb:"Debug/WritingDlgTest.pdb" /debug /machine:I386/out:"Debug/WritingDlgTest.exe" /pdbtype:sept 下面我們分別來看一下Category中的各項設置。(1)General:一些總體設置。可以設置生成的文件路徑、文件名;連接的庫文件;Generate debuginfo,生成Debug資訊到.PDB文件(具體格式可以在Category->Debug中設置);Ignore All DefaultLibraries,放棄所有默認的庫連接;Link Incrementally,通過生成.ILK文件實現遞增式連接以提高後續連接速度,但一般這種方式下生成的文件(EXE或DLL)較大;GenerateMapfile,生成.MAP文件記錄模組相關資訊;Enable Profiling,這個參數通常與GenerateMapfile參數同時使用,而且如果產生Debug資訊的話,不能用.PDB文件,而且必須用Microsoft Format。(2)Customize:這裡可以進行使用程式數據庫文件的設置。Force File Output ,強制產生輸出文件(EXE或DLL);Print Progress Messages,可以將連接過程中的進度資訊輸出到Output窗口。(3)Debug:設置是否生成調試資訊,以及調試資訊的格式。格式可以有Microsoft Format、COFF Format(Common ObjectFile Format)和Both Formats三種選擇;SeparateTypes,表示將Debug格式資訊以獨立的.PDB文件存放,還是直接放在各個源文件的.PDB文件中。選中的話,表示採用後者的方式,這種方式調試啟動比較快。(4)Input:這裡可以指定要連接的庫文件,放棄連接的庫文件。還可以增加額外的庫文件目錄,一般是相對於本項目的目錄,如..Lib。Force Symbol References,可以指定連接特定符號定義的庫。(5)Output:BaseAddress可以改變程式默認的基地址(EXE文件默認為0x400000,DLL默認為x10000000),作業系統裝載一個程式時總是試著先從這個基地址開始。Entry-PointSymbol可以指定程式的入口地址,一般為一個函數名(且必須採用__stdcall調用約定)。一般Win32的程式,EXE的入口為WinMain,DLL的入口為DllEntryPoint;最好讓連接器自動設置程式的入口點。默認情況下,通過一個C的運行時庫函數來實現:控制臺程式採用mainCRTStartup (或wmainCRTStartup)去調用程式的main(或wmain)函數;Windows程式採用WinMainCRTStartup (或wWinMainCRTStartup)調用程式的WinMain (或wWinMain,必須採用__stdcall調用約定);DLL採用_DllMainCRTStartup調用DllMain函數(必須採用__stdcall調用約定)。Stack allocations,用以設置程式使用的堆棧大小(請使用十進位),默認為1兆位元組。VersionInformation告訴連接器在EXE或DLL文件的開始部分放上版本號。值得注意的是,上面各個參數是大小寫敏感的;在參數後加上「-」表示該參數無效;各個參數值選項有「*」的表示為該參數的默認值;可以使用頁右上角的「Reset」按鈕來恢復該頁的所有默認設置。其他一些參數設置(1)Project->Settings->General,可以設置連接MFC庫的方式(靜態或動態)。如果是動態連接,在你的軟體發佈時不要忘了帶上MFC的DLL。(2)Project->Settings->Debug,可以設置調試時運行的可執行文件,以及命令行參數等。(3)Project->Settings->Custom Build,可以設置編譯/連接成功後自動執行一些操作。比較有用的是,寫COM時希望IDE對編譯通過的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路徑。 一些小竅門(針對Visual C++)(1)有時候,你可能在編譯的時候,電腦突然非法關機了(可能某人不小心碰了電源或你的記憶體不穩定等原因)。當你重啟機器後打開剛才的項目,重新進行編譯,發現IDE會崩掉。你或許以為你的編譯器壞了,其實不然(你試試編譯其他項目,還是好的!),你只要將項目的.ncb、.opt、.aps、.clw文件以及Debug、Release目錄下的所有文件都刪掉,然後重新編譯就行了。(2)如果你想與別人共用你的源代碼項目,但是把整個項目做拷貝又太大。你完全可以刪掉以下文件:.dsw、.ncb、.opt、.aps、.clw、. plg文件以及Debug、Release目錄下的所有文件。(3)當你的Workspace中包含多個Project的時候,你可能不能直觀地、一眼看出來哪個是當前項目。可以如下設置:Tools->Options->Format,然後在Category中選擇Workspacewindow,改變其默認的字體(比如設成Fixedsys)就行了。(4)如何給已有的Project改名字?將該Project關掉。然後以文本格式打開.dsp文件,替換原來的Project名字即可。(5)VC6對類成員的智慧提示功能很有用,但有時候會失靈。你可以先關掉項目,將.clw和.ncb刪掉,然後重新打開項目,點擊功能表項View->ClassWizard,在彈出的對話方塊中按一下「Add All」按鈕;重新Rebuild All。應該可以解決問題。
推薦閱讀:
※機器學習與編譯優化的入門介紹
※記一次golang中的賦值覆蓋錯誤
※MSBuild
※[新聞] 大部分Intel hardware intrinsic 將在 .NET Core 2.1 中啟用
※C#的編譯過程