ビルド
wxWidgets2.9.4をcygwin1.7.17でビルドしてみました。
MinGWではありません。(MinGW on Cygwinはこちらの記事です)
付属サンプルのめぼしいのを試してみると、動くのもあり、トラップするものもありで、正しいのかどうなのかまったくわかりませんので、記事の信頼性はvery-low very-very-low*1ということでお願いします。
この記事ではデバッグビルドの顛末が書かれていますが、リリースビルドもできます。cygwinにおける最短は、
$ ./configure --disable-shared $ make
ですが、これだとソースフォルダ内に.oが生成されるので、頭の中もフォルダ内もぐちゃぐちゃになります。install.txt で示される out-of-placeビルドの方法ならばソースフォルダとは別のフォルダにライブラリ、オブジェクトがビルドされます。install.txtを読むか、この記事のちょいと下のほうを見てからはじめると少しは幸せになります。
記事の内容は次の通り。
- 準備(ダウンロード元のURLなど)
- ソースコード改竄(patchも有ります)
- ライブラリのビルド(out-of-placeビルド方式です)
- サンプルのビルド
- HelloWorld(世界の国からこんにちは♪。HelloWorld.zip あります。)
準備
$ uname -a CYGWIN_NT-6.1-WOW64 etcpc 1.7.17(0.262/5/3) 2012-10-19 14:39 i686 Cygwin
$ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-cygwin/4.5.3/lto-wrapper.exe Target: i686-pc-cygwin コンフィグオプション: /gnu/gcc/rel... スレッドモデル: posix gcc version 4.5.3 (GCC)
src/generic/dirctrlg.cppの改竄
ビルドエラーに対応して、3箇所の改竄をしました。この改竄の影響は・・・わかりません。
- 67〜69行:direct.h はcygwinでは使えないので削除します。
#if !defined(__WXWINCE__) // #include <direct.h> #endif
- 297〜299行:_chdrive はcygwinでは使えないので削除します。
//#elif defined(__GNUWIN32__) && \ // (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) // return _chdrive(drive);
- 340〜357行:_getdriveはcygwinでは使えないので削除します。
wxString dirNameLower(dirName.Lower()); //#if defined(__GNUWIN32__) && !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) success = wxDirExists(dirNameLower); /*#else #if defined(__OS2__) // Avoid changing to drive since no media may be inserted. if (dirNameLower[(size_t)0] == 'a' || dirNameLower[(size_t)0] == 'b') return success; #endif int currentDrive = _getdrive(); int thisDrive = (int) (dirNameLower[(size_t)0] - 'a' + 1) ; int err = setdrive( thisDrive ) ; setdrive( currentDrive ); if (err == -1) { success = false; } #endif*/
- diff -u で作成したpatchです。src/generic/cygwin.patch などと保存して、pacthを実行します。
$ patch -u <cygwin.patch
--- dirctrlg.original.cpp 2012-07-08 19:28:27.000000000 +0900 +++ dirctrlg.cpp 2013-01-12 02:34:36.578036700 +0900 @@ -65,7 +65,7 @@ // accordingly. #if !defined(__GNUWIN32__) || (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) #if !defined(__WXWINCE__) - #include <direct.h> +// #include <direct.h> #endif #include <stdlib.h> #include <ctype.h> @@ -294,9 +294,9 @@ { #ifdef __WXWINCE__ return 0; -#elif defined(__GNUWIN32__) && \ - (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) - return _chdrive(drive); + //#elif defined(__GNUWIN32__) && \ + // (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) + // return _chdrive(drive); #else wxChar newdrive[4]; @@ -337,9 +337,9 @@ if (dirName.length() == 3 && dirName[(size_t)1] == wxT(':')) { wxString dirNameLower(dirName.Lower()); -#if defined(__GNUWIN32__) && !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) + //#if defined(__GNUWIN32__) && !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) success = wxDirExists(dirNameLower); -#else + /*#else #if defined(__OS2__) // Avoid changing to drive since no media may be inserted. if (dirNameLower[(size_t)0] == 'a' || dirNameLower[(size_t)0] == 'b') @@ -354,7 +354,7 @@ { success = false; } -#endif + #endif*/ } #ifdef __WIN32__ (void) SetErrorMode(errorMode);
(やっと)ビルド
$ cd wxWidgets-2.9.4 $ mkdir build-debug $ cd build-debug $ ../configure --with-msw --enable-debug --enable-debug_gdb --disable-shared $ make
- tar.bz2を展開した wxWidgets-2.9.4フォルダに、build-debugフォルダを作成し、そこで、configure、makeします。.oや.aはこのフォルダ以下に作成されます(ソースと一緒なin-placeではなくて、out-of-place ビルドするということになります)。
- オプション
オプションの--enable_debugを付けると、--enable_debug_infoと--enable_debug_flagがconfigure内部で自動的に設定されます。
あと、--with-opengl はビルドに失敗しました。こちらに解決法らしきものがありますが、よく理解できませんでした。
サンプルのビルド
$ cd wxWidgets2.9.4/build-debug/samples $ make
サンプルのauidemoで試した限りでは、日本語の入力、表示はOKだし、半分ずつ削除されるとかもありません。サンプルのtextで試した限りでは、UTF-8でビルドされているようです。ファイルダイアログでの日本語ファイル名、フォルダ名もOKでした。いわゆるダメ文字の「ソースコード表示」とかOKでした。
HelloWorld
- ソース、Makefile、実行形式をzipしたものです。./HelloWorld.exe で実行します。
// -*- coding: utf-8-unix -*- // wxWidgets "Hello world" Program // For compilers that support precompilation, includes "wx/wx.h". #include <wx/wxprec.h> #ifndef WX_PRECOMP #include <wx/wx.h> #endif class MyApp: public wxApp { public: virtual bool OnInit(); }; class MyFrame: public wxFrame { public: MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); private: void OnHello(wxCommandEvent& event); void OnExit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); wxDECLARE_EVENT_TABLE(); }; enum{ ID_Hello = 1 }; wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(ID_Hello, MyFrame::OnHello) EVT_MENU(wxID_EXIT, MyFrame::OnExit) EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) wxEND_EVENT_TABLE() wxIMPLEMENT_APP(MyApp); bool MyApp::OnInit() { MyFrame *frame = new MyFrame( wxT("Hello World♪こんにちは〜こんにちは〜世界の窓から〜"), wxPoint(50, 50), wxSize(450, 340) ); frame->Show( true ); return true; } MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, wxID_ANY, title, pos, size) { wxMenu *menuFile = new wxMenu; menuFile->Append(ID_Hello, wxT("こんにちは(&H)...\tCtrl-H"), "Help string shown in status bar for this menu item"); menuFile->AppendSeparator(); menuFile->Append(wxID_EXIT); wxMenu *menuHelp = new wxMenu; menuHelp->Append(wxID_ABOUT); wxMenuBar *menuBar = new wxMenuBar; menuBar->Append( menuFile, wxT("ファイル(&F)") ); menuBar->Append( menuHelp, "&Help" ); SetMenuBar( menuBar ); CreateStatusBar(); SetStatusText( wxT("ようこそwxWidgetsへ!") ); } void MyFrame::OnExit(wxCommandEvent& event) { Close( true ); } void MyFrame::OnAbout(wxCommandEvent& event) { wxMessageBox( wxT("これはwxWidgetsの「こんにちは世界よ!」サンプルです。"), "About Hello World", wxOK | wxICON_INFORMATION ); } void MyFrame::OnHello(wxCommandEvent& event) { wxLogMessage("Hello World!"); }
# -*- coding: utf-8-unix -*- CXX = $(shell wx-config --cxx) PROGRAM = HelloWorld OBJECTS = $(PROGRAM).o # implementation .SUFFIXES: .o .cpp .cpp.o : $(CXX) -c `wx-config --cxxflags` -o $@ $< all: $(PROGRAM) $(PROGRAM): $(OBJECTS) $(CXX) -o $(PROGRAM) $(OBJECTS) `wx-config --libs` -mwindows clean: rm -f *.o $(PROGRAM)
- ちなみに、日本語リテラルを扱うために使っているwxT()は_T()と同じものです。
- ちなみに、HelloWorld.exeが依存するDLLは、つぎのとおりです。
$ objdump.exe -x HelloWorld.exe|grep DLL vma: Hint Time Forward DLL First DLL Name: cygwin1.dll DLL Name: cygz.dll DLL Name: cyggcc_s-1.dll DLL Name: cygstdc++-6.dll DLL Name: ADVAPI32.dll DLL Name: COMCTL32.DLL DLL Name: COMDLG32.DLL DLL Name: GDI32.dll DLL Name: KERNEL32.dll DLL Name: ole32.dll DLL Name: OLEAUT32.dll DLL Name: SHELL32.DLL DLL Name: USER32.dll DLL Name: WINSPOOL.DRV
蛇足
リリース、デバッグのそれぞれのビルドで生成されるライブラリ名が変わるということがinstall.txtに書かれていますが、当家では変わりませんでした。configureが生成したMakefileをみると、
#WXDEBUGFLAG = d
とデバッグ用Makefileでもコメントアウトされていました。これを活性化すると、'u' UNICODEに加えて、'd' DEBUG 識別も付くようにはなりますが、下位ディレクトリにもMakefileがあるので泥沼状態になります。configureで生成されたMakefileをいじるのは躊躇します。
この件は忘れることにします。
蛇足2
cygwinのフォルダ(/usr/local)へのインストールは、
$ make install
で行います。どのようなウィジェットがインストールされたかは、サンプルを動かせばわかりますが、「読みたい!」という場合は、「wxWidgets-2.9.4/include/wx/msw/setup.h」に書かれています。setup.hにはユーティリティクラスの説明もあるようです。
蛇足3
こんなことをしなくても、Lua スクリプトから使う wxLua というのもありますし、他にもさまざまな言語、スクリプトにポーティングされてますので、わざわざcygwinにこだわるのもおかしな話です、と自己否定ですね。
wxLuaでWindows(Unicode)バイナリ配布されてます。日本語の入力・表示も扱えます。Lua.exe(5.1)も同梱されているので、すぐに使えます。
では、なぜ、cygwinなのか?・・・今のところ明確な答えは持ち合わせていません。
*1:fd0さんからもらった情報を調べてみたら、記事の信頼性が著しく低いと判明したので、「下の下の下」に改めます