ビルド

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を読むか、この記事のちょいと下のほうを見てからはじめると少しは幸せになります。
記事の内容は次の通り。

  1. 準備(ダウンロード元のURLなど)
  2. ソースコード改竄(patchも有ります)
  3. ライブラリのビルド(out-of-placeビルド方式です)
  4. サンプルのビルド
  5. 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 ビルドするということになります)。
  • オプション
    • --with-msw : Microsoft WindowsGUIツールにする。付けなくても既定でOnだと思います。
    • --enable-debug:デバッグ用コードを活性化します。
    • --enable-debug_gdbGDBデバッグ版でビルド。
    • --disable-shared:DLLにしない。これを付けないとビルドに失敗しました。

オプションの--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 で実行します。

HelloWorld.zip

// -*- 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にこだわるのもおかしな話です、と自己否定ですね。

wxLuaWindows(Unicode)バイナリ配布されてます。日本語の入力・表示も扱えます。Lua.exe(5.1)も同梱されているので、すぐに使えます。
では、なぜ、cygwinなのか?・・・今のところ明確な答えは持ち合わせていません。

*1:fd0さんからもらった情報を調べてみたら、記事の信頼性が著しく低いと判明したので、「下の下の下」に改めます