それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Cygwinでgccをcygwin.1.dll非依存にする(CygwinでWindowsアプリのコンパイル)

CygwinでWindows専用アプリをコンパイルしたり出来ると便利です。Cygwin/gccで作ったプログラム はcygwin.dllに依存してしまうので、ちょっと嬉しくなかったりします。*1

gcc -mno-cygwinは使えない。

-mno-cygwinが非Cygwin依存のコンパイルだったけど、いまは使えない。(というかgcc4以前をインストールしたら使える)

昔のやり方でも構わないという人は→過去エントリ参照

いまは mingwを使ったりクロスコンパイルターゲットを入れるほうがいいらしい。

今回は cygwinmingwコンパイラを入れてコンパイルしてみた。

mingwgccコンパイラ。mingw64-i686-gcc-coreをインストール

apt-cyg install mingw64-i686-gcc-core

で入れた。もちろんsetup.exeでもいい。

win32apiを使ってみる。

コンパイルは簡単。

i686-w64-mingw32-gcc test.c が動けばいい。( windowsが 32ビット版のとき)


今回はダイアログを表示と、Windowを作ってみた。

コンパイル方法。

コンパイラの使い方は次の通り。

Windowsアプリケーションを作るには

 i686-w64-mingw32-gcc-4.5.3.exe win.c  -mwindows

ヘッダファイル「windows.h」をインクルードするエントリポイントは、main関数ではなく「WinMain関数」である
gccコマンドによるコンパイル&リンク時に「-mwindowsオプション」を付加する

とのこと。


とりあえずダイアログボックスを表示してみた

/* WinMain.c */
#include <windows.h>
////////////////////////////////////////////////////////////////////
// Windowsアプリケーションは、WinMainからはじまる。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, "Hello World!", "Test", MB_OK);
    return 0;
}

コンパイル&&実行

i686-w64-mingw32-gcc test.c
./a.exe

次に、Windowを表示する。

Windowを表示する。こんな感じ。


プログラムのソースコードは参考資料からのコピーです。

#include <windows.h>
#include <tchar.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

/* エントリポイント */
int WINAPI WinMain(
  HINSTANCE hCurInst,
  HINSTANCE hPrevInst,
  LPSTR lpsCmdLine,
  int nCmdShow)
{
  HWND hWnd;
  WNDCLASSEX wc;
  MSG msg;
  BOOL bRet;
  /* ウィンドウクラスの定義 */
  wc.cbSize = sizeof(WNDCLASSEX);
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = WndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hCurInst;
  wc.hIcon = (HICON)LoadImage(
    NULL,
    IDI_APPLICATION,
    IMAGE_ICON,
    0,
    0,
    LR_DEFAULTSIZE | LR_SHARED);
  wc.hCursor = (HCURSOR)LoadImage(
    NULL,
    IDC_ARROW,
    IMAGE_CURSOR,
    0,
    0,
    LR_DEFAULTSIZE | LR_SHARED);
  wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wc.lpszMenuName = NULL;
  wc.lpszClassName = _T("SampleClass");
  wc.hIconSm = (HICON)LoadImage(
    NULL,
    IDI_APPLICATION,
    IMAGE_ICON,
    0,
    0,
    LR_DEFAULTSIZE | LR_SHARED);
  /* ウィンドウクラスの登録 */
  if(RegisterClassEx(&wc) == 0)
    return FALSE;
  /* ウィンドウの作成 */
  hWnd = CreateWindow(
    wc.lpszClassName,
    _T("Window App Sample"),
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    NULL,
    NULL,
    hCurInst,
    NULL);
  /* ウィンドウの表示 */
  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);
  /* メッセージループ */
  while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
    if (bRet == -1)
      break;
    else {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
  return (int)msg.wParam;
}
/* ウィンドウプロシージャ */
LRESULT CALLBACK WndProc(
  HWND hWnd,
  UINT msg,
  WPARAM wp,
  LPARAM lp)
{
  switch (msg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProc(hWnd, msg, wp, lp);
  }
  return 0;
}

コンパイルと実行

i686-w64-mingw32-gcc test.c -mwindows
./a.exe

感想とか

こんな感じでコンパイルできるので、なんか遊べそう。Makefileもばっちり使えるし
(でもこれで作ったアプリを配布とかしてもコンパイル方法面倒だよねって言われるんだろうなぁ。WindowsならやっぱりVSかも?)

*1:cygwinのdllと一緒にコピーして使えばいいんだけどGNUとかライセンスとかの配布条件が。。。