VS中的 MD/MT设置 【转】
VS系列工具作為目前微軟主打的集成開發環境,在歷經了近20多年的發展后,到如今已經可以 說是Windows平臺上各種IDE環境中的翹楚了。很多別的開發工具已經難望其項背了,如今VS2010也已經面市很長時間了,但是因為筆者囊中羞澀, 無法升級硬件,所以也沒有辦法去進行那個180天的VS2010體驗之旅了,實為憾事。當然這是別話,現在我主要使用的依然是VS2008,用它來開發我 想要的東西。當然主要指使用其中的VC++部分了。
在用VS2005或VS2008的VC++開發產品時,經常遇到的一個問題就是最終編譯出的可執行文件Exe、Dll、Ocx之類會需要 MSVCR90.dll、MSVCR80.dll等C庫函數運行時Dll的支持,在一些較老的系統,如XP中,經常不具備這些新版本的運行庫,導致產品發 布推廣成為一個嚴重的問題。在2008年我還在開發一款網游時,也遇到了同樣的問題,雖然想盡了辦法,也無法屏蔽對這個動態庫的引用,不得已,客戶端就又 返回老的VS2003環境中進行編譯開發,最終發布。
本著刨根問底的精神,我仔細琢磨了一下這個問題,貌似可以通過與最終產品一起發布MicrosoftVisual C++ 2005/2008 RedistributablePackage庫來解決這個問題,但是這個庫的個頭有可能是你最終產品的n倍(n>=5),這就像買了一部手機,卻 給你了一座核電站來支持,最終用戶是否能接受是個很糾結的問題。
再后來,我發現可以使用VS2008自帶的安裝程序制作工具,生成一個最簡的VC++Redistributable包,體積也很小,但是一樣需要一個額外的安裝包來支持你的最終產品,很多產品經理是不太喜歡這種形式的,所以此問題還是很糾結。
在一次與一位網友討論這個問題時,他興奮的告訴我,他的總監解決了這個問題,方法就是修改一下編譯選項,將/MD選項改為/MT選項,最終的可執行文 件就不會包含對那些VC運行時DLL的引用了,可以很方便的發布和部署。真是個非常棒的消息,讓一個糾結了我兩年多的問題得到了徹底解決。首先讓我們來看 下這個云遮霧罩的編譯開關究竟是干什么的?MSDN中的描述如下:
/MD
使應用程序使用運行時庫的多線程并特定于DLL 的版本。定義 _MT 和 _DLL,并使編譯器將庫名 MSVCRT.lib 放入 .obj文件中。
用此選項編譯的應用程序靜態鏈接到MSVCRT.lib。該庫提供允許鏈接器解析外部引用的代碼層。實際工作代碼包含在 MSVCR90.DLL, 中,該庫必須在運行時對于與MSVCRT.lib 鏈接的應用程序可用。
當/MD 與 _STATIC_CPPLIB 預處理器定義 (/D_STATIC_CPPLIB)一起使用時,您的應用程序將與靜態多線程標準 C++ 庫 (libcpmt.lib) 而非動態版本 (msvcprt.lib)鏈接,但仍通過 msvcrt.lib 動態鏈接到主 CRT。
請注意,不支持_STATIC_CPPLIB 預處理器定義和 /clr 或 /clr:pure 編譯器選項的組合。有關 /clr選項的限制的更多信息,請參見 /clr 限制。
/MDd
?定義_DEBUG、_MT 和 _DLL,并使應用程序使用運行時庫的調試多線程并特定于 DLL 的版本。它還使編譯器將庫名MSVCRTD.lib 放入 .obj 文件中。
/MT
?使應用程序使用運行時庫的多線程靜態版本。定義_MT 并使編譯器將庫名 LIBCMT.lib 放入 .obj 文件中,以便鏈接器使用 LIBCMT.lib解析外部符號。
/MTd
?定義_DEBUG 和 _MT。此選項還使編譯器將庫名 LIBCMTD.lib 放入 .obj 文件中,以便鏈接器使用LIBCMTD.lib 解析外部符號。
/LD
創建DLL。
將/DLL 選項傳遞到鏈接器。鏈接器查找 DllMain 函數,但并不需要該函數。如果沒有編寫 DllMain 函數,鏈接器將插入返回TRUE 的 DllMain 函數。
鏈接DLL 啟動代碼。
如果命令行上未指定導出(.exp) 文件,則創建導入庫 (.lib);將導入庫鏈接到調用您的 DLL的應用程序。
將/Fe(命名 EXE 文件) 解釋為命名 DLL 而不是 .exe 文件;默認程序名成為基名稱.dll而不是基名稱.exe。
除非顯式指定/MD,否則將暗指 /MT。
/LDd
創建調試DLL。定義 _MT 和 _DEBUG。
看到這里,我恍然大悟,原來這個開關就是控制這個C運行時庫的引用方式的,真是踏破鐵鞋無覓處得來全不費工夫。
當然到這里先別忙著去修改你的項目屬性中關于這個開關的選項,因為當你的項目也是一個LIB時,如果使用了/MT或/MTd選項時,最終的靜態LIB中就 會出現LIBCMT.lib中的大量符號,導致在別的項目引用你的這個靜態LIB時出現重復定義符號而無法鏈接的錯誤,怎么解決呢?其實繼續看MSDN中 的幫助就可以得到答案:傳遞給鏈接器的給定調用的所有模塊都必須使用相同的運行時庫編譯器選項(/MD、/MT、/LD)進行編譯。
呵呵,原來如此,所有的模塊保持一致就完了,但是靜態的LIB貌似還是無法引用,問題依舊怎么辦呢?那就是在引用了你自己的使用/MT或/MTd選項編譯生成的靜態LIB的項目中,不但指定對應的/MT或/MTd選項,而且需要忽略LIBCMT.lib庫即可。
到這里這個很糾結的問題,總算是有一個非常完滿的解決方法了。總結下來,其實也怪自己,《VC++語言參考手冊》中其實早就描述過這個問題了,而我沒有注 意,導致為這個非常基礎的問題糾結了這么長的時間,實在是汗顏。在這里也非常感謝那位總監高手,輕松的解決了這個問題。也為以后大家也不再為這個問題發 愁,所以寫成這篇文章,讓大家作為參考。
轉載于:https://www.cnblogs.com/mazhenyu/p/4722298.html
總結
以上是生活随笔為你收集整理的VS中的 MD/MT设置 【转】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dev机上数据库中批量生成table
- 下一篇: Android基于mAppWidget实