MinGWというフリーのコンパイラがあります。 一般にUNIX系OSで使われているGCCというC言語を中心としたパッケージ(Cの他、C++、Objective-C、Objective-C++、FORTRAN、Javaなど)を、Windowsでも使えるようにしてあるのがこのMinGWです。 なのでこのMinGWを使えばWindowsアプリケーション開発がタダでできるというわけです。お得ですな ただ、お得である代わりに何から何まで自力で作っていく必要はありますがこの過程も楽しみましょ ちゅーことで、最終的にはC言語(あるいはC++)を駆使してWindowsアプリケーションを自在に作れるようになる為にいろいろもがいてみます。 Windowsプログラムは、ウィンドウを持たずにコマンドを直打ちして実行させるプログラム(CUI)と、ウィンドウを持つプログラム(GUI)の2種類に大別することができます。 先にウィンドウを持たない方でC言語を勉強してから、ウィンドウを持つアプリケーション作りの勉強に進みたいと思います。 めっちゃすごい勢いで開発しているイメージ図
MinGWというフリーのコンパイラがあります。
一般にUNIX系OSで使われているGCCというC言語を中心としたパッケージ(Cの他、C++、Objective-C、Objective-C++、FORTRAN、Javaなど)を、Windowsでも使えるようにしてあるのがこのMinGWです。 なのでこのMinGWを使えばWindowsアプリケーション開発がタダでできるというわけです。お得ですな
ただ、お得である代わりに何から何まで自力で作っていく必要はありますがこの過程も楽しみましょ
ちゅーことで、最終的にはC言語(あるいはC++)を駆使してWindowsアプリケーションを自在に作れるようになる為にいろいろもがいてみます。
Windowsプログラムは、ウィンドウを持たずにコマンドを直打ちして実行させるプログラム(CUI)と、ウィンドウを持つプログラム(GUI)の2種類に大別することができます。 先にウィンドウを持たない方でC言語を勉強してから、ウィンドウを持つアプリケーション作りの勉強に進みたいと思います。
▽ ダウンロード MinGWはWindowsに最初から付属しているわけではないのでどこか他のアジトに置いてあるはずです。 ということで情報屋グーぐる夫からそのアジトを聴き出した結果、ブツはコチラに置かれていることが判明、今現在(2010/10/10)はmingw-get-inst-20100909.exe(582.1KB)といったブツが置かれています。 フリーなので末端価格は0円、そのままダウンロード開始です。 ▽ インストール ダウンロードしたmingw-get-inst-20100909.exeファイルは実行ファイルなのでこれをダブルクリックで実行してインストールを開始します。 既にチェック済みの「C Compiler」に、「C++ Compiler」と「MSYS Basic System」を追加チェックして次へ進みます。 インストール場所はCドライブ直下「C:\MinGW」でOK ▽ インストールその後 インストールが終われば、今後自分が開発していきやすいように環境を整えておく必要があります。 ということで、MSYSというUNIXライクな使い方ができるものがあるのは知ってはいましたが、使うのは今回が初めてなのでまずはいろいろ眺めていきます。 「プログラム」のスタートメニューには「MinGW Shell」というのがあります。 これ以外は特に使えそうなものはないので恐らくここからMinGWを使っていくことになるようです。 この「MinGW Shell」を実行してみると、 C:\MinGW\msys\1.0\msys.bat を介して C:\MinGW\msys\1.0\bin\sh.exe を起動 させてシェル端末が開く仕掛けになっています。 わざわざ介さなくても直接sh.exeを呼びますよと起動させてみると、必要なパスが通っていないスカスカの端末が起動してしまいました。 つまりバッチからシェル起動させた時に、必要なパスやシェルを設定するからくりということですね。 なので普通にDOS窓を開いて環境変数Pathを確認しても、MinGWの実行ファイル群のある「C:\MinGW\bin」へのパスは通っていないし必要がないわけです。 では正しくシェル起動させてコマンドを打ち込んでみます Username@foo-PC ~ $ dir sh: dir: command not found Username@foo-PC ~ $ ls Username@foo-PC ~ $ pwd /home/Username Username@foo-PC ~ やはりUNIXライクなだけあって、DOSコマンドのdirではなく、lsを使ってディレクトリ内のファイル一覧表示ができるようです。 ただ、まだファイルは1つもなさそうです。 で一体ここはどこでしょう。。。 ということでpwdコマンドを打ったら/home/Usernameと表示されました。 これの実体を探してみると、 C:\MinGW\msys\1.0\home\Username の場所にありました。ホームディレクトリ内には ".bash_history" のようなドットファイルがありました。 これはつまりMSYS内の仮想ディレクトリの "/"(ルート)が C:\MinGW\msys\1.0 ということになります。それと、シェルとしてbashが使われているようです。 で、次は何しようか、、とりあえず自分のホームにファイル作成でもしてみようとviコマンドを打ち込んでみるとそんなコマンドは無いと言われました。 よく分かりませんがテキストエディタは自分で用意せぇということでしょうかね。 でもviコマンドが使えてこそUNIX使ってる感が個人的にはあるので、絶対に使えるようにしたいと思います。 先ほどbashを使っていることがわかったので、起動設定ファイルを作って、普段使っているGVimをテキストエディタとして使える設定にしてみましょ 起動設定ファイル [~/.bashrc] alias vi='C:\Program Files\vim72-kaoriya-w32j\gvim.exe' これでMinGWシェルを起動してviコマンドを打ってみる。。 反応がない… ただの屍のようだ。 調べてみるとなぜか.bashrcは使えないようで、.profileだけが使えるらしい。 Windowsでは直接ファイル[右クリック][名前の変更]からドットファイル名に変更しようとしてもできない場合があります。 その場合は「メモ帳」などのソフトを立ち上げ[名前を付けて保存]メニューを使ってドットファイル名を指定する方法をとるとうまくいきます。 起動設定ファイル [~/.profile] alias vi='/C/"Program Files"/vim72-kaoriya-w32j/gvim.exe' alias ls='ls -aF' alias rm='rm -i' alias cp='cp -i' alias mv='mv -i' viコマンドと、ついでに他のコマンドもエイリアス設定しました。 MSYSでの仮想ディレクトリ構造では、Cドライブは「/C/」という記述になるので上記のような書き方になります。 また、"Program Files"は間にスペースを含んでいるのでダブルクォートで囲まないと認識してくれませんでした。 これで好みのテキストエディタを組み込むことができました。∩( ・ω・)∩ばんじゃーい GVimエディタにはCUI版のvim.exeも付属しているのでこれを指定すれば別ウィンドウを開かずにそのまま作業できますが、作業中にエディタのウィンドウサイズを変えられなかったりするのでGVim.exeの方がいいように感じます。
MinGWはWindowsに最初から付属しているわけではないのでどこか他のアジトに置いてあるはずです。
ということで情報屋グーぐる夫からそのアジトを聴き出した結果、ブツはコチラに置かれていることが判明、今現在(2010/10/10)はmingw-get-inst-20100909.exe(582.1KB)といったブツが置かれています。
フリーなので末端価格は0円、そのままダウンロード開始です。
ダウンロードしたmingw-get-inst-20100909.exeファイルは実行ファイルなのでこれをダブルクリックで実行してインストールを開始します。
インストール場所はCドライブ直下「C:\MinGW」でOK
インストールが終われば、今後自分が開発していきやすいように環境を整えておく必要があります。
ということで、MSYSというUNIXライクな使い方ができるものがあるのは知ってはいましたが、使うのは今回が初めてなのでまずはいろいろ眺めていきます。
「プログラム」のスタートメニューには「MinGW Shell」というのがあります。 これ以外は特に使えそうなものはないので恐らくここからMinGWを使っていくことになるようです。
この「MinGW Shell」を実行してみると、
させてシェル端末が開く仕掛けになっています。
わざわざ介さなくても直接sh.exeを呼びますよと起動させてみると、必要なパスが通っていないスカスカの端末が起動してしまいました。
つまりバッチからシェル起動させた時に、必要なパスやシェルを設定するからくりということですね。 なので普通にDOS窓を開いて環境変数Pathを確認しても、MinGWの実行ファイル群のある「C:\MinGW\bin」へのパスは通っていないし必要がないわけです。
Username@foo-PC ~ $ dir sh: dir: command not found Username@foo-PC ~ $ ls Username@foo-PC ~ $ pwd /home/Username Username@foo-PC ~
やはりUNIXライクなだけあって、DOSコマンドのdirではなく、lsを使ってディレクトリ内のファイル一覧表示ができるようです。 ただ、まだファイルは1つもなさそうです。
で一体ここはどこでしょう。。。
ということでpwdコマンドを打ったら/home/Usernameと表示されました。
これの実体を探してみると、
の場所にありました。ホームディレクトリ内には ".bash_history" のようなドットファイルがありました。
これはつまりMSYS内の仮想ディレクトリの "/"(ルート)が
ということになります。それと、シェルとしてbashが使われているようです。
で、次は何しようか、、とりあえず自分のホームにファイル作成でもしてみようとviコマンドを打ち込んでみるとそんなコマンドは無いと言われました。 よく分かりませんがテキストエディタは自分で用意せぇということでしょうかね。
でもviコマンドが使えてこそUNIX使ってる感が個人的にはあるので、絶対に使えるようにしたいと思います。
先ほどbashを使っていることがわかったので、起動設定ファイルを作って、普段使っているGVimをテキストエディタとして使える設定にしてみましょ
これでMinGWシェルを起動してviコマンドを打ってみる。。 反応がない… ただの屍のようだ。
調べてみるとなぜか.bashrcは使えないようで、.profileだけが使えるらしい。
viコマンドと、ついでに他のコマンドもエイリアス設定しました。
MSYSでの仮想ディレクトリ構造では、Cドライブは「/C/」という記述になるので上記のような書き方になります。 また、"Program Files"は間にスペースを含んでいるのでダブルクォートで囲まないと認識してくれませんでした。
これで好みのテキストエディタを組み込むことができました。∩( ・ω・)∩ばんじゃーい
ではすべての始まりとして、プログラミングのド定番である「Hello world」表示に挑戦してみます。 ホームディレクトリにCソースファイルを作成 Username@foo-PC ~ $ vi hello.c Cソースファイル [~/hello.c] #include int main(void) { printf("Hello world!\n"); return 0; } コンパイルして実行 Username@foo-PC ~ $ gcc hello.c Username@foo-PC ~ $ a Hello world! Username@foo-PC ~ $ うまく「Hello world!」を表示させることができました! gccというコマンドを使ってCソースファイルを指定してコンパイラを走らせました。 作成する実行ファイル名を指定しなかったので、デフォルトのa.exe(UNIXではa.out)で作成され、 a(.exeは省略可)で実行して表示させています。 ところでコンパイラが行う『コンパイル』って一体なにをしているんでしょうか? コンパイルを直訳すると翻訳するという意味になります。 何から何への翻訳をしているかと言うと、Cのソースファイルに書かれたことを解析して、その環境で使用しているCPUが理解できる機械語に翻訳する(置き換える)作業を行っています。 実はコンパイラだけで実行ファイル作成までを完了できるわけではありません。 コンパイラが行う作業は構文解析して機械語への翻訳までを行い、その結果としてオブジェクトファイルが生成されることになります。 その後にリンカを走らせて、オブジェクトファイル(複数の場合あり)に必要なライブラリがあればそれをリンクさせオブジェクトファイル同士を組み合わせて実行ファイルが出来上がります。 なのでCのコンパイラを走らせるgccコマンドは内部でコンパイル以外の工程にもいろいろとちょっかい出しています。 gccが走らせる順番作業内容 [1] cpp(プリプロセッサ)Cの構文が正しいかは一切抜きに、前処理を行う [2] cc1(コンパイラ)構文解析してアセンブラに変換 [3] as(アセンブラ)アセンブラを機械語に変換(この結果オブジェクトファイルが出来る) [4] ld(リンカ)リンク作業を行い実行ファイルを生成する。 このように、gccコマンドは内部でいろいろ呼び出すためのラッパープログラムであると言えます。
ではすべての始まりとして、プログラミングのド定番である「Hello world」表示に挑戦してみます。
Username@foo-PC ~ $ vi hello.c
Username@foo-PC ~ $ gcc hello.c Username@foo-PC ~ $ a Hello world! Username@foo-PC ~ $
うまく「Hello world!」を表示させることができました!
gccというコマンドを使ってCソースファイルを指定してコンパイラを走らせました。 作成する実行ファイル名を指定しなかったので、デフォルトのa.exe(UNIXではa.out)で作成され、 a(.exeは省略可)で実行して表示させています。
ところでコンパイラが行う『コンパイル』って一体なにをしているんでしょうか?
コンパイルを直訳すると翻訳するという意味になります。
何から何への翻訳をしているかと言うと、Cのソースファイルに書かれたことを解析して、その環境で使用しているCPUが理解できる機械語に翻訳する(置き換える)作業を行っています。
実はコンパイラだけで実行ファイル作成までを完了できるわけではありません。 コンパイラが行う作業は構文解析して機械語への翻訳までを行い、その結果としてオブジェクトファイルが生成されることになります。
その後にリンカを走らせて、オブジェクトファイル(複数の場合あり)に必要なライブラリがあればそれをリンクさせオブジェクトファイル同士を組み合わせて実行ファイルが出来上がります。
なのでCのコンパイラを走らせるgccコマンドは内部でコンパイル以外の工程にもいろいろとちょっかい出しています。
このように、gccコマンドは内部でいろいろ呼び出すためのラッパープログラムであると言えます。
▽ makeユーティリティの利用 makeコマンドの持つユーティリティ機能を使って、実行ファイル生成作業を楽にすることを考えます。 どういうことかと言うと、Makefileというファイルに実行ファイル生成の作業工程を書いておき、makeというコマンド一発で作業工程を読み取って実行ファイルを生成させるというものです。 この方法を使えば、実行ファイル作成の度にgccコマンドへ渡すパラメータをいちいち指定しなくて済むようになります。 ソースファイルの依存関係が複雑になってくるとgccコマンドへ渡すパラメータが多くなって大変な作業になってくるのでMakefileを作ってmakeコマンドを使った方が楽です。 Makefileの雛形 SRC=hello.c OBJS=$(SRC:.c=.o) PROG=hello.exe CC=gcc CFLAGS=-Wall -O3 #LDFLAGS=-mwindows RM=rm %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< .PHONY : all all: $(PROG) $(PROG): $(OBJS) $(CC) $(OBJS) $(LDFLAGS) -o $@ .PHONY : clean clean: $(RM) $(OBJS) 雛形となるMakefileを作っておき、今後これを流用して書き足していくことにします。 行頭の空白はタブになります。 このMakefileでは、「make または make all」で実行ファイルを作成し、「make clean」でオブジェクトファイルを削除するように記述しています。 このMakefileには前回作成したときのソースファイルをSRC=hello.cとして指定しています。 そして作成するプログラム名としてPROG=hello.exeという指定もしているのでそのままmakeと打ち込みます。 Username@foo-PC ~ $ make gcc -Wall -O3 -o hello.o -c hello.c gcc hello.o -o hello.exe Username@foo-PC ~ $ hello Hello world! Username@foo-PC ~ $ 期待通りに「Hello world!」を表示させることができました。 Makefileを用意したことで、たったmakeとhello(拡張子.exeは省略可)だけで表示させるところまでができてしまいました。 もしもソースファイルに記述ミスがあった場合には、実行ファイル作成の途中でエラーを表示して終了してしまうことになるのでその度にソースファイルを見直しては修正を繰り返せば、実行ファイル作成は常にmakeだけで済むので大幅に手間が省けます。 実行ファイルの作成まで無事にできました。ここで再びmakeと打ち込んでみます。 Username@foo-PC ~ $ make make: Nothing to be done for `all' Username@foo-PC ~ $ すると今度は実行ファイル作成は行われずに、makeコマンドから「やることがない」というメッセージが返ってきました。 これは既存の実行ファイルhello.exeとオブジェクトファイルhello.oの作成時刻を比べて、実行ファイルが後に作られていれば作成する必要がないと判断しているのでこうなります。 このことはコンパイル作業を最小限に収めて効率的にするために必要なことです。 なのでもう一度実行ファイルを作成したい場合にはオブジェクトファイルを削除する必要があります。 Username@foo-PC ~ $ make clean rm hello.o Username@foo-PC ~ $ make gcc -Wall -O3 -o hello.o -c hello.c gcc hello.o -o hello.exe Username@foo-PC ~ $ 「make clean」でオブジェクトファイルを削除すれば、こんな感じで再び実行ファイル作成ができます。 makeユーティリティに関して基本的なことは以上になります。 ▽ ファイル管理 今後の作業のことを考えて、ファイルがごちゃごちゃにならないようにディレクトリ分けしていきたいと思います。 内容が把握できるディレクトリ名に分けていくのが理想ですが、考える手間や並び順がうまいこといかなくなりそうなので連番で作成していきます。 MSYS付属のfindやgrepコマンドを使えばそのディレクトリ内にどういうものがあるのかを検索できるので、連番分けが無難だと思います。 Makefileは雛形をコピーして使い回していくので、masterというディレクトリを作成してその中に入れておきます。 MSYSの仮想ディレクトリ構造 / +- home/ +- Username/ +- master/ | +- Makefile | +- 001/ | +- Makefile | +- hello.c | +- hello.o | +- hello.exe | +- 002/ +- Makefile : これでガンガン開発していけそうな感じがしてきました。 ある程度ディレクトリ分けが溜まってきたら、機能ごとにディレクトリ分けし直して整理していけばいつでも再確認・再利用できて便利になると思います。 開発環境も整いましたので、あとは心置きなくC言語の勉強に集中できます。
makeコマンドの持つユーティリティ機能を使って、実行ファイル生成作業を楽にすることを考えます。
どういうことかと言うと、Makefileというファイルに実行ファイル生成の作業工程を書いておき、makeというコマンド一発で作業工程を読み取って実行ファイルを生成させるというものです。
この方法を使えば、実行ファイル作成の度にgccコマンドへ渡すパラメータをいちいち指定しなくて済むようになります。 ソースファイルの依存関係が複雑になってくるとgccコマンドへ渡すパラメータが多くなって大変な作業になってくるのでMakefileを作ってmakeコマンドを使った方が楽です。
雛形となるMakefileを作っておき、今後これを流用して書き足していくことにします。
行頭の空白はタブになります。
このMakefileでは、「make または make all」で実行ファイルを作成し、「make clean」でオブジェクトファイルを削除するように記述しています。
このMakefileには前回作成したときのソースファイルをSRC=hello.cとして指定しています。 そして作成するプログラム名としてPROG=hello.exeという指定もしているのでそのままmakeと打ち込みます。
Username@foo-PC ~ $ make gcc -Wall -O3 -o hello.o -c hello.c gcc hello.o -o hello.exe Username@foo-PC ~ $ hello Hello world! Username@foo-PC ~ $
期待通りに「Hello world!」を表示させることができました。
Makefileを用意したことで、たったmakeとhello(拡張子.exeは省略可)だけで表示させるところまでができてしまいました。
もしもソースファイルに記述ミスがあった場合には、実行ファイル作成の途中でエラーを表示して終了してしまうことになるのでその度にソースファイルを見直しては修正を繰り返せば、実行ファイル作成は常にmakeだけで済むので大幅に手間が省けます。
実行ファイルの作成まで無事にできました。ここで再びmakeと打ち込んでみます。
Username@foo-PC ~ $ make make: Nothing to be done for `all' Username@foo-PC ~ $
すると今度は実行ファイル作成は行われずに、makeコマンドから「やることがない」というメッセージが返ってきました。
これは既存の実行ファイルhello.exeとオブジェクトファイルhello.oの作成時刻を比べて、実行ファイルが後に作られていれば作成する必要がないと判断しているのでこうなります。
このことはコンパイル作業を最小限に収めて効率的にするために必要なことです。 なのでもう一度実行ファイルを作成したい場合にはオブジェクトファイルを削除する必要があります。
Username@foo-PC ~ $ make clean rm hello.o Username@foo-PC ~ $ make gcc -Wall -O3 -o hello.o -c hello.c gcc hello.o -o hello.exe Username@foo-PC ~ $
「make clean」でオブジェクトファイルを削除すれば、こんな感じで再び実行ファイル作成ができます。
makeユーティリティに関して基本的なことは以上になります。
今後の作業のことを考えて、ファイルがごちゃごちゃにならないようにディレクトリ分けしていきたいと思います。
内容が把握できるディレクトリ名に分けていくのが理想ですが、考える手間や並び順がうまいこといかなくなりそうなので連番で作成していきます。 MSYS付属のfindやgrepコマンドを使えばそのディレクトリ内にどういうものがあるのかを検索できるので、連番分けが無難だと思います。
Makefileは雛形をコピーして使い回していくので、masterというディレクトリを作成してその中に入れておきます。
/ +- home/ +- Username/ +- master/ | +- Makefile | +- 001/ | +- Makefile | +- hello.c | +- hello.o | +- hello.exe | +- 002/ +- Makefile :
これでガンガン開発していけそうな感じがしてきました。
ある程度ディレクトリ分けが溜まってきたら、機能ごとにディレクトリ分けし直して整理していけばいつでも再確認・再利用できて便利になると思います。
開発環境も整いましたので、あとは心置きなくC言語の勉強に集中できます。