
Google+
編譯zlib
以用 Mircosoft Visual Studio 2012 完整編過 OpenSenceGraph (OSG) 裡面所有擴充功能為主的教學。
之會有英文版。
最近看到猴子靈藥的作者之前出的一本書,App遊戲製作人的1000日告白,
覺得自己應該分享一下什麼,幫助一下大家,
想了一想,覺得自己目前最會大家最不會的就是編譯這些開源的 library 了,
這個技能對學生或是小RD應該是沒什麼用吧?
學生時代的C++課程只要寫一些資料結構或演算法的小實作,
小RD也沒辨法依自己的意思加入自己要加的 library ,
需要權力更大,或是資深專業的 RD 來評估決定,
不過相信有一天大家都會需要編譯別人的程式庫的~
學生時代我的感覺是大部份的高手都在 linux 世界玩,
windows 世界的高手相對少了很多,
希望這系列的文章可以讓大家沒高手可問時,
看看文章就會舉一反三編譯以前不會編譯的程式庫。
選擇 OSG 來做開頭,
主要是因為這個程式庫用到很多別人的程式庫,
大家都知道,站在巨人的肩牓上,但這些巨人也都是站在別的巨人上,
大家的專精領域如此窄,身為一個繪圖引擎的作者,
去實作 ZLIB 的演算法, 讀 PNG 的程式,
不一定會比 這些程式庫的作者好, 而且重造輪子很花時間,
尤其這些輪子還是作者不熟的領域,
這時他選擇了相依於其它人的程式庫,
就是沒有他(ZLIB, LibPNG, ...) 我(OSG) 就不讓你用,
或是我的部份功能你不能使用,
這就是相依程式庫的意義,
而OSG相依了很多的程式庫,
這些程式庫也叫作第三方程式庫(3rd Party)
你需要好好的了解為什麼?
配合這個OSG,大家也可以了解如何編譯過別的程式庫,
來讓自己真正需要用的程式庫編譯過,
對於第一次編譯程式庫的人,
我想說的是,人總是貪心的,
我們總是會希望編譯過這個程式庫的所有功能,
就算今天用不上,說不定明天會用上,
不過每一個功能都相依不同的3rd Party。
基本介紹:
在微軟的編譯器裡,
針對c語言的runtime做了 N 個版本,
這裡給一下官方說法
http://msdn.microsoft.com/en-us/library/2kzt1wy3%28v=vs.71%29.aspx
基本上現在已經沒有單執行緒的程式了,
所以組態基本上剩下 /MTd /MT /MDd /MD
這部份的詳細說法可以到 猴子靈藥 的 blog 查看
http://blog.monkeypotion.net/gameprog/beginner/love-and-hate-between-msvc-and-crt
我只簡單說一下,
MTd 與 MT 是靜態,
MDd 與 MD 是動態,
差別在 MT 與 MTd 可以在自己的電腦編過後,
直接在別人的電腦上執行,
不需要 runtime 支援,不需要額外的 dll ,
代價是 exe 會比較大,連結時間較長。
而 MDd, MD 在執行時會用到 MSVCRT.DLL, MSVCRT.DLL
而且編譯器版本不同的話有機會 runtime error
甚至無法執行。
身為一個 "專業" 的程式工作者,
你一定是四個組態都要會編譯,
還有就是動態程式庫跟靜態程式庫的差異,
雖然我很想叫讀者直接去看組語學,
不過本著分享的心情,就簡單說一下吧~
要真正的熟悉理解,還是去組語練習MASM幾個小程式才是最快的,
要省時間的話就去看 程式員的自我修養 ,
Windows 環境下32 位元組合語言程式設計 這本是我的組語啟蒙
http://books.google.com.tw/books/about/Windows%E7%92%B0%E5%A2%83%E4%B8%8B32%E4%BD%8D%E5%85%83%E7%B5%84%E5%90%88%E8%AA%9E%E8%A8%80%E7%A8%8B.html?id=HVwFPwAACAAJ&redir_esc=y
現在寫組語都用 WinASM 真的是超好用的~~~
http://www.winasm.net/
有點離題了,好~
在 windows 下,
大家都知道要把程式編譯成exe需要經過下列步驟
.c/.c++ => .o/.obj => .exe
上面是c語言的方式
而 fortran 跟 pascal 是
.f/.pp => .o/.obj => .exe
聰明的大家有注意到嗎?
第二個步驟以後都是一樣的,
這裡的意義是,如果你會設定 linker 參教跟宣告別的語言的 函數簽名(function signature)
就可以讓這三個語言互通有無,
那那 這些東西跟我們的 MT MTd MD MDd 四大runtime有什麼關係嗎?
當然有呀~
今天你用到的標準函式宣告只定義在 .c/.c++ ,
但是實際連結是透過 linker 把這些 .obj 連在一起,
由於你的標準函式宣告都是一樣的,
所以這四大 runtime 的符號大部份都是重複定義的,
當 a.obj 用到 MDd 而 b.obj 用到 MTd 時,
由於 libcmtd.lib 與 libcmdd.lib 的符號相同,
a.obj 要連結時會不知道他的標準函式庫函數如 printf
到底是要用 libcmtd.lib 裡的,還是 libcmdd.lib ,
就像你問誰是我們國家的領導人,可能對某些雙重國籍的人要思考一下是一樣的道理?
所以最好的方法就是 a.obj 跟 b.obj 在編譯時就要決定一樣的 runtime library,
但是由於每個人會有不同的需求,
所以常常會用不同的 runtime 來編譯,
說了那麼多很棒很有意思對大家很有幫助的廢話,
最好的方式就是,把四個 runtime 的程式庫都編出來吧~~~ (4
再把動態跟靜態都編出來吧~~~ (2
再把 x86 & x64 都編出來吧~~~ (2
再把 vc9 vc10 vc11 都分別編出來吧~~~ (3
幫大家簡單分析一下會有幾種組合
4 x 2 x 2 x 3 = 48 種不同的程式庫,
好啦,你可能會說我只用最新的 vc11,
其它都不用,那還是有 16 種不同的程式庫,
如果你願意放棄 x86 轉投 x64 的陣營,
還是有 8 種組合要面對,
就算全部只編 靜態程式庫 也要4種,
不過這個世界還是有美好的地方,
mingw 是 gcc在windows 上的 porting,
如果你用 vc 連結 mingw 編譯好的程式庫,只要連結一種就好了喔~~~
頂多分為動態與靜態兩種,超爽的~~~
說了那麼多還是先跟大家說一下怎麼設定 runtime library 吧~
對專案右鍵
選屬性
組態屬性 => c/c++ => 程式碼產生
在執行階段程式庫 依據您的個人心情選一個喜歡的選項 ^ ^
接下來要說到 cmake 了
http://www.cmake.org/
這是一個高手苦於 windows, linux, openbsd
x86 x64 gcc2.x 3.x 4.x mingw vc6 7 8 9 10 11
等不同的平台編譯而發明出來的產物
想要讓跨平台編譯更輕鬆一點,
而OSG也使用了他來編譯,
以下來試試吧~
我用的是 OpenSceneGraph-3.1.5
他一開始會問兩個問題,
一個是你的程式碼在哪?
另一個是你專案檔要產生在哪?
這次的專案檔我設在程式碼下的 build.test 資料夾下,
按下左下角的 configure 後
會問你要用什麼編譯器?
本人理所當然的選了 vs11 win64 了呀~~
哈哈哈~~~ 選 win64 的人都可以體會大記憶體 new不完的快感喔~~~
超爽的~~~ 羨幕嗎?XXXXXXXDDDDDDD
好,炫耀完了,
接下來他會開始檢測你的編譯器是不是符合這個程式庫的規定,
跑完後結果如下:
接下來就是高手跟新手的差別了,
你會看到裡面一堆紅色領域,
左邊是變數名,右邊表示變數的值,
變數名就代表著變數的生命意義,
不過這不會有人跟你說他的意義,要自己舉一反三領悟,
不過我既然要教學了,自然會跟你說一下:
//Location of 3rdparty dependencies
ACTUAL_3RDPARTY_DIR:PATH=c:/clibrary/vc11-x64/3rdparty
第三方程式庫目錄
OSG官方合作的公司提供的不完整的第三方程式庫的資料夾路徑
//Path to a file.
ASIO_INCLUDE_DIR:PATH=ASIO_INCLUDE_DIR-NOTFOUND
asio 聲音程式庫的 include 路徑
//Set to ON to activate reporting of OpenSceneGraph builds here
// http://cdash.openscenegraph.org/index.php?project=OpenSceneGraph
BUILD_DASHBOARD_REPORTS:BOOL=OFF
建立回報機制將你的編譯結果回報給社群網站
//Build OpenSceneGraph reference documentation using doxygen (use:
// make DoxygenDoc)
BUILD_DOCUMENTATION:BOOL=OFF
建立Doxygen文件
//Enable to build OSG Applications (e.g. osgviewer)
BUILD_OSG_APPLICATIONS:BOOL=ON
編譯 osg 的公用程式
//Enable to build OSG Examples
BUILD_OSG_EXAMPLES:BOOL=OFF
編譯 osg 的範例程式
//Set to ON to generate CPack configuration files and packaging
// targets
BUILD_OSG_PACKAGES:BOOL=OFF
產生 cpack 檔一種cmake產生的安裝檔
不過只有一種組態 不是 debug 就是 release
相信我你不會想用它的
//The directory containing a CMake configuration file for Boost.
Boost_DIR:PATH=Boost_DIR-NOTFOUND
設定 boost 的路徑,但是通常設定了也會被清空,可能是沒用到的關係
//Path to a file.
Boost_INCLUDE_DIR:PATH=Boost_INCLUDE_DIR-NOTFOUND
設定boost的 include 路徑
//Boost diagnostic define
Boost_LIB_DIAGNOSTIC_DEFINITIONS:STRING=-DBOOST_LIB_DIAGNOSTIC
設定boost的前置處理
//For backwards compatibility, what version of CMake commands and
// syntax should this version of CMake try to support.
CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4
cmake的最低相容版本
//Semicolon separated list of supported configuration types, only
// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything
// else will be ignored.
CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo
要編譯的組態,建議砍掉MinSizeRel;RelWithDebInfo
就算快的跟我的電腦一樣,通常還是很少用到,尤其是我們編LIBRARY這種的
//Flags used by the compiler during all build types.
CMAKE_CXX_FLAGS:STRING= /DWIN32 /D_WINDOWS /W3 /Zm1000 /GR /EHsc
vc 的 通用編譯設定
//Flags used by the compiler during debug builds.
CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Zi /Ob0 /Od /RTC1
vc給 debug 組態的特化設定
//Flags used by the compiler during release minsize builds.
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /D NDEBUG
vc給 MinSizeRel 組態的特化設定
