What have you found for these years?

2011-04-10

cubeat 回顧 (1)

上一篇在這
1016. 2009-07-18 cubeat 回顧 (0)

簡單回顧一下流程... 有錯請指正,感謝 XD

1. Flash prototype

2. Virtools + Virtools SDK + 光線槍

3. Flash prototype + network (Ruby server)

4. Flash prototype + AI

5. Irrlicht3D (patched with freetype + X11 patch) + IrrKlang +
Ruby preprocessing + Ruby puzzle generator + Wiimote

[展出]

[.........a short pause?]

6. Irrlicht3D (patched with freetype + X11 patch) + IrrKlang +
Ruby preprocessing + Ruby puzzle generator + ManyMouse +
AI

[.........a long pause?]

7. Irrlicht3D (patched with freetype) + ALURE (OpenAL) +
Ruby preprocessing + LuaJIT puzzle generator +
AI

整個過程真的是一堆東西加加減減添添刪刪...
我這邊稍微提一下 mac 上的開發狀況。(自 Irrlicht3D 後)

那時的 Irrlicht3D 只有好像可以動的 mac 版..
我不記得過程如何了,總之 mac 版無論如何都 build 不起來。
於是我就非常暴力地,在 make 碰到 error 後,
加個 -U__APPLE__ -U__MACOSX__ 之類的,
讓 make 以為其實現在是在 build linux 版..

跑過之後,又會碰到有些東西是 linux 上才有的,
什麼 byteswap.h 之類的,我不知道那是什麼,
mac/bsd 上好像沒辦法弄出這個東西。於是我只好
讓人「變回」mac 版,就不會 compile 到那部份了...

就這樣中途切換平台,最後還真的 build 出 libIrrlicht.a 了。
當然,也被視為 linux 版,被放到 linux 的目錄下。
如果讓 mac 的程式去 link 這個 linux 版的 Irrlicht3D,
則可以成功讓他跑在 X11 下,相當順利,效能也很不錯。

不過還是有碰到一個問題,就是感覺是 Irrlicht3D 搞錯 X11 的
event queue 的用法,導致有些地方會 block 住整個程式。
我完完全全不記得我當時是怎麼做的了,總之 google 半天後,
成功把他的 X11 程式的這部份修對了...

那時候在想,了解一下 X11 的架構似乎也不錯。
不過把他改到動還真的是 google + trial and error 就可以了。

*

後來 Irrlicht3D 有真正的 mac 版了,還要用 xcodebuild 去 build,
不能用 make 去 build. 我也有點不記得這邊有什麼問題了,總之
弄出來的程式效能非常爛,而且有很多小小怪怪的問題... 喔喔,
我想起來了,好像是程式會吃不到鍵盤事件,弄半天也無法解決這個問題。

因此最後我還是覺得就用 X11 就好了,簡單多了..

* [.........a short pause?]

ManyMouse 我在 mac 上弄不出來,一直 segfault...
不然就是毫無反應,沒記錯的話。

* [.........a long pause?]

由於這是最近幾天的事,因次印象比較深,所以或許可以多說一點。
在之前,我自己是用 macports 的 g++-mp-4.3 去 build 的。
我不記得為什麼,但現在想起來了,因為 apple 的 g++ 4.2 的
TR1 根本就是爛的,沒辦法用。我想起來了,那時 google 就碰到
一堆東西好像都是 apple g++, 還有 ld 的 bug, 那我當然沒辦法解決...

然後用 macports build 出來的 g++ 4.3 就很順利沒什麼問題。
因此我後來一直是用那個版本。而或許也因為這樣,所以我很難
用 mac 上的東西,都只能去 link X11 的東西,包括 OpenGL.

但如今用了 homebrew, 他的政策是不裝 apple 已提供過的東西,
也就是 gcc, g++ 當然也就不會有了。但問題是 apple g++ 就是
有問題啊。最後我找到了 g++ 4.6 binary 可以用。在這裡:
High Performance Computing for Mac OS X
其實也有找到要 build from source 的,在 homebrew-alt 裡。

沒記錯的話,這兩個版本的 g++ 都沒問題。但仍然,似乎不能使用
-framework 那些 apple extension, 就只能用 X11 的東西了。

我原本是覺得就 X11 啦,X11, 雖然還有很多細節要調整,而且
在 mac 上用 X11 真的就是很難用,一堆毛病,一堆東西要調整。
但老林似乎還是覺得有個 native Aqua 介面是比較好的方式.. XD

那麼很不幸地,就得遷就於 apple 的 outdated and broken g++.

除了一些比較新的功能要拿掉,很多 TR1 的東西,也得改用 boost.
折騰了許久,總算最後成功把 apple 有問題的 TR1 都換成 boost 了。
結果現在換 MinGW 出事。g++ 4.5 以降似乎有個很蠢的 bug, 他的
mutex 沒有 destructor, 因此 mutex 會 leak 某些 resource...

一些討論在 buzz 上。libstdc++ 的 bug:
resource leaks due to missing destructors for mutexes and condvars

看起來意思是只有 g++ 4.6+ 才能解決這個問題!
也就是說這個 bug 其實存在很久了..。平常都不會碰到的原因是,
大概很少人在用 mutex 吧,要嘛就 single thread, 要嘛就是
atomic operation, 很少真的直接在用 mutex.

而 MingGW g++ 4.5 不知為何,預設使用 mutex, 也就碰到這個問題。
反而 MinGW g++ 4.4 因為不是用 mutex, 倒是沒這個問題。

*

說真的,用 C++ 真的是問題和麻煩都很多呀!

在這之間,我也想試著用 clang++ 看看。結果 clang++
去吃系統的 libstdc++, 而 apple 的 TR1 是爛的,所以還是爛的,
光換 compiler 是沒有用的。於是只好去看 libcxx, 是 llvm 自己做的
standard c++ library. 無奈雖然裝得起來,卻不知道怎麼叫 clang++
去用那套 library, 而不是系統的。說明上的作法沒有效果哩。

前幾天出了 llvm 2.9, 說不定現在可以用了?
but i don't care now..... since it's already working on
apple's broken g++ 4.2.

這些全搞定後,最後又回到那個鍵盤事件吃不到的問題。
這又是一個非常繁複的過程... 我常常在想,其實只要問個
比較熟悉 mac 程式開發的人,大概就可以獲得答案了吧。
偏偏我對特定系統的程式並沒有興趣 (e.g. windows only,
mac only, or linux only), 實在一點頭緒都沒有。

和老林 google 了很久,也試了各種方法,都沒有效果。

最後最後,決定開一個全新的 xcode project 試試,
因此而找到答案。感覺好像是廢話似的?但其實這跟
xcode project 真的一點關係都沒有說。

因為 xcode project 預設會做出一個 .app, 然後發現
執行那個 .app 的話,就吃得到鍵盤事件了!

得到的結論是,只要有個 .app 的結構,鍵盤事件就會很神奇地
吃得到。不需要 plist, 不需要 nib, 也不需要什麼 PkgInfo,
沒有特殊的 compile option, 跟 xcode 也沒有任何關係。

更有趣的是,就算我直接從 terminal 去執行 .app 裡面的執行檔,
結果也是一樣的。例如跑 ./CuBeat.app/Contents/MacOS/CuBeat
這樣也吃得到鍵盤事件!不過 working directory 倒是跟跑 .app 不同。
直接跑 .app 時,working directory 會是 / 也就是跟 daemon 一樣。
但如果是直接跑執行檔,就不會這樣。可是執行檔也要放在 .app 裡面,
不然鍵盤事件會吃不到。

也就是說,mac 在執行 binary 程式時,會去偷看他是不是存在一個
.app 裡面!說真的這我覺得還滿莫名其妙的。

不過仔細想想,其實我覺得這樣的設計還滿不錯的。
原因很簡單,因為他的 .app 的 layout 其實很單純,
我可以很輕易寫一些簡單的 (ruby) script 就能弄出來,
也不用因此把執行檔加入一堆莫名其妙的東西,不管是
compile option 或是奇怪的 resource file.

也就是說,原本的 build script 都能保留,只要最後加上
這一段去把 .app 的 layout 產生出來就好。當然了,還有
otool -L 和 install_name_tool -change 的部份...
要把用到的 dylib 都搬進去,然後調整讀取的路徑。

*

也因此,build 過程大概就是 ruby preprocess 產生
CMakeLists.txt, 因為 cmake 真的很難用,我需要一些
ruby script 協助我.. 不然很多東西要寫死或是寫得很難看。

接著 cmake . 來產生 Makefile, 就可以 make 了。
make 完後就靠 Rakefile 裡的 task 來:

1. 產生 CuBeat.app/Contents/MacOS 和 CuBeat.app/Contents/Resources
2. 把各種 binary 丟到前者,各種圖檔、聲音檔、設定檔丟到後者
3. 用 otool -L 找到所有應該 bundle 的 .dylib, 丟到 MacOS 裡
4. 同時用 install_name_tool -change 把讀取路徑改成 @loader_path/
5. 最後 tar -zcf CuBeat.app.tgz CuBeat.app

整個過程寫在 `rake build:mac` 中

這邊有的地方目前還寫得有點暴力,就是直接跑 script.
理想上是用 rake 的 file task, 這樣他會有能力判斷檔案是否需要更新,
而不是傻傻地一跑就去覆蓋檔案...

這一堆東西包括 ruby preprocessing 的東西,我可能想另外寫到一個
gem 裡面。之前有些東西是在 ludy 裡,那早已年久失修,而且太亂了。
雖然說他在 1.9 也能動我還滿感動的,證明程式好好寫不要亂搞如 rails,
要升級 ruby 真的一點都不難...

不過我程式風格跟當年也差很多了,所以也想整理一下。

*

大概就這樣吧,在 mac 上的 CuBeat.app 看來是沒問題了!
接下來就是放個 icon 或什麼的可能就能放 beta release...

p.s. 後來所有的程式都是老林寫的,我只有協助在 mac 上弄起來而已

4 retries:

Johnson Lin said...

WTF..... 打了一大串結果送出失敗 -_-

Lin Jen-Shin (godfat) said...

@@"
灌這個..
https://addons.mozilla.org/en-US/firefox/addon/textarea-cache/

Johnson Lin said...

簡短版:

1. 其實我們的 C++ 本來就寫得很保守,4.2.1 一定沒問題的,之前 apple gcc 的問題是它當年根本只有 4.0 XD

2. 針對 apple gcc 修改的部份其實只有我後來加的 variadic template,手動展開沒花什麼時間。

3. 雖然很討厭 apple 上的開發環境,但還是要感謝那份 crash report。

4. 突然想到有用過 apple gcc 去 build manymouse 嗎?32bit 和 64bit 版有差嗎?因為總覺得 mac 只差這點有點殘念,我晚點再查查。

5. 等我把 linux 版 bundle 也做好就真的可以宣稱我們真的有跨三大平台,不再只是「因為都用跨平台的 lib 所以應該有跨」,寫跨平台 C++ 程式真的不難,只是一開始工具要挑對 ... 不能說 irrlicht 很爛,只能說有利有弊,畢竟他對於一個不懂 3D 引擎的人來說確實很好上手。

Lin Jen-Shin (godfat) said...

1. 確實,忘記這件事,可能因為 4.2 也是有一段時間了

3. 這點忘記提了

4. 32/64 bit 也忘記提了.. manymouse 我不記得當時用什麼 build 了

5. 工具挑對,不要直接用 os 上的 api, 我覺得大抵上真的沒那麼難..
還有不少人會說 java 其實要跨平台也沒那麼容易,
我覺得應該也沒那麼難吧,只是一定會要測過,
然後稍微調整一下這個是跑不掉的..

Post a Comment

All texts are licensed under CC Attribution 3.0