Linux 上で Windows のモジュールをコンパイルする方法は Google 先生に聞くと結構出てくるけど、その逆がなかなか出てこない。 ということで Windows 上で Linux のモジュールをコンパイルする方法をメモ。 #contents * クロスコンパイラを使う方法 [#vc6aacf2] 他のプラットフォームのモジュールを作成できるコンパイラを使う方法。もうそのまんま。 ** Windows 上に UNIX 環境を構築 [#b84e6734] Cygwin か MinGW/msys ということになると思う。導入に関する詳細は下記ページで。 - [[UNIX on Windows]] ここでは Cygwin を使ってみる。 ** クロスコンパイラの作成 [#kb724182] 理屈としては、ターゲットとなる Linux の C++ 環境をターゲットとして、Cygwin で gcc をコンパイルすれば良いということになる。 と思ったけど、上手くいかないので、とりあえず以下のサイトからコンパイル済みのクロスコンパイラをいただいて使用することにする。 - [[NEC の SDDSE 紹介サイト:http://www.nec.co.jp/cced/SDDSE]] -- [[サンプルダウンロード:http://www.nec.co.jp/cced/SDDSE/sampledl.html]] 上記サイトの クロスコンパイラ をいただく。 *** クロスコンパイラを自前でつくる場合 [#jb8fc3e2] 実は、私もやろうとしたけど、挫折した。 一応、こうすればできるらしいということを、今後の為にメモしておく。 + まず、ターゲットとなる Linux 上で、作業用のディレクトリをつくる。 -- ここでは /tmp/linux-runtime とする。&br; $ mkdir /tmp/linux-runtime + C/C++ コンパイルに必要なライブラリ(依存関係も全て)をコピーする。 -- これが、どれが必要なのかよくわからないので、以下のディレクトリを全部コピー。&br; $ cp -r /lib /tmp/linux-runtime $ cp -r /usr/lib /tmp/linux-runtime $ cp -r /usr/include /tmp/linux-runtime -- 環境によっては 500MB 超える。1GB くらいになることも。 -- あからさまに C/C++ に関係ないディレクトリは削除しても良いと思う。&br; python とか mozilla とか。 + linux-runtime を samba か scp か何かで Windows へ送る。 -- サイズが結構あるので、tar.gz とか lzma あたりで固めて移動すると良いかも。 + ここから Windows 側の作業。Cygwin はインストール済みという前提で。 -- Cygwin は C:\Cygwin にインストールされているとする。 + GNU の binutils と gcc のソースをゲットする。 -- [[GNU(ftp):ftp://ftp.gnu.org/gnu]] のサイトから以下を取得。 --- [[binutils:ftp://ftp.gnu.org/gnu/binutils]] --- [[gcc:ftp://ftp.gnu.org/gnu/gcc]] -- 今回は下記を使うものとする。 --- [[binutils-2.19:ftp://ftp.gnu.org/gnu/binutils/]] --- [[gcc-3.3.4:ftp://ftp.gnu.org/gnu/gcc/gcc-3.3.4/]] + 上記を Cygwin で適当なところに展開。 -- ここは /home/user/work に展開したとする。&br; $ tar zxvf binutils-2.19.tar.gz $ tar zxvf gcc-3.3.4.tar.gz + インストール先ディレクトリを作成。 -- ここは /usr/local/linux とする。&br; $ mkdir /usr/local/linux + Linux でつくった linux-runtime 配下のファイルを /usr/local/linux に配置。 $ mv -R (どこか)/linux-runtime /usr/local/linux $ ls /usr/local/linux lib include + /usr/local/linux/lib にある libc.so のパスを修正。 /* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a ) ↓&br; /* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ GROUP ( /usr/local/linux/lib/libc.so.6 /usr/local/linux/lib/libc_nonshared.a ) + binutils をコンパイル、インストール。 $ cd /home/user/work/binutils-2.19 $ mkdir build $ cd build $ ../configure --prefix=/usr/local/linux \ --target=i686-linux \ --host=i686-pc-cygwin \ --build=i686-pc-cygwin (略) $ make $ make install + ここまでで /usr/local/linux/bin が作成されているはずなので、パスを通しておく。 $ PATH=/usr/local/linux/bin:$PATH + gcc をコンパイル、インストール。 $ cd /home/user/work/binutils-2.19 $ mkdir build $ cd build $ ../configure --prefix=/usr/local/linux \ --target=i686-linux \ --host=i686-pc-cygwin \ --build=i686-pc-cygwin \ --enable-languages=c,c++ \ --enable-shared \ --enable-threads \ --includedir=/usr/local/linux/include (略) $ make $ make install ※ オプション不要なものや足りないものがあるかもしれない。&br; ※ make で [configure-target-libiberty] 的なエラーが出るかも。とりあえず無視する。 + ここまでで、以下のフォルダが作成されているはず。 /usr/local/linux/bin /usr/local/linux/include /usr/local/linux/lib /usr/local/linux/man /usr/local/linux/share + bin の中に以下が出来上がっていればとりあえずコンパイラ完成。 i686-linux-as i686-linux-gcc i686-linux-g++ + 試しに簡単なソースをコンパイルしてみる。 $ i686-linux-gcc hello.c -o hello これで hello が出力される。が、Windows 上では実行できない。&br; Linux に hello を持っていって実行できれば、成功! となるはずが、私は上手くいかない。何か手順が足りないんだと思うけど。。 ** Cygwin で動作確認 [#k8527278] Cygwin 環境で、以下の構成になっているとする。 - C:/Cygwin -- /bin/make -- /usr/local/linux/bin/i686-linux-as -- /usr/local/linux/bin/i686-linux-gcc -- /usr/local/linux/bin/i686-linux-g++ 試しに Cygwin のみでコンパイルしてみる。 + 作業用ディレクトリを作成して移動。 -- ここでは /home/user/work/hello というディレクトリにする。&br; $ mkdir /home/user/work/hello $ cd /home/user/work/hello + ソースを書いて、hello.c という名前で保存。&br; #include <stdio.h> int main(int argc, char* argv[]) { printf("Hello World!\n"); return 0; } + クロスコンパイラでコンパイルしてみる。 $ i686-linux-gcc hello.c -o hello ※ gcc で起動すると Cygwin の gcc が動くので、i686-linux-gcc を指定すること。 + これで hello というファイルができて実行できれば OK。 $ ls hello hello.c $ ./hello Hello World! ** Eclipse を使う [#o514c93e] Eclipse は CDT を使うよ。 - [[Eclipse:http://www.eclipse.org/]] -- [[Eclipse IDE for C/C++ Developers:http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/galileo/SR2/eclipse-cpp-galileo-SR2-win32.zip]] 特にインストーラなどはなくて、適当なディレクトリに展開するだけ。 次に、日本語化する。英語のままでも良いならここは不要。&br; ※ ただ、下の説明は日本語化したのを前提に書いてマス。 - [[Eclipse 日本語化言語パック (サードパーティ版):http://www.igapyon.jp/blanco/nlpack/eclipse/index.html]] これも特にインストーラはなくて、展開したフォルダやファイルたちを Eclipse を展開した場所に上書きするだけ。 早速 Eclipse を使ってみる。 + Eclipse 起動。 + 「ファイル」→「新規」→「C++ プロジェクト」で、プロジェクト名「hello」、実行ファイル形式を選んで「完了」。 -- 「Hello World C++ Project」があればそっちで。&br; 最初からお決まりのサンプルがつく。 + Hello World がなかった場合はソースを作成。 -- 左ペインのプロジェクトを右クリックして「新規」→「フォルダ」で「src」フォルダ作成。 -- 「src」フォルダを右クリックして「新規」→「ソースファイル」で「hello.c」を作成。 -- 「hello.c」をダブルクリックして、以下を記述。&br; #include <stdio.h> int main(int argc, char* argv[]) { printf("Hello World!\n"); return 0; } + 左ペインのプロジェクトを右クリックして「プロパティ」を開く。 + 「C++ ビルド」下にある「ツール・チェーン・エディタ」を選択。 -- 構成はどちらでも良いけど、ここは「Release」をアクティブにする。 -- 現在のツールチェーン : Cygwin GCC -- 現在のビルダー : GNU Make ビルダー + 「C++ ビルド」下にある「環境」を選択。 -- 「設定する環境変数」に以下を追加。 --- 名前 : PATH --- 値 : C:\Cygwin\bin;C:\Cygwin\usr\local\linux\bin + 「C++ ビルド」下にある「設定」を選択。 -- 「ツール設定」に以下を設定。 --- GCC Assembler コマンド : i686-linux-as --- Cygwin C++ Compiler コマンド : i686-linux-g++ --- Cygwin C Compiler コマンド : i686-linux-gcc --- Cygwin C++ Linker コマンド : i686-linux-g++ -- 「成果物」に以下を設定。 --- 成果物タイプ : 実行可能 --- 成果物の名前 : hello --- あとは空白。 -- 「バイナリパーサー」に以下を設定。 --- 「Cygwin PE パーサー」と「Elf パーサー」にチェック。 --- あとは チェックをはずす。 + 「OK」でプロパティを閉じる。 + 「プロジェクト」→「すべてビルド(Ctrl + B)」でビルドしてみる。 + 画面下コンソールに特にエラーがなければ、Release フォルダに hello というファイルができる。 + その hello を Linux に持っていって実行してみる。 $ ./hello + 「Hello World!」と表示されれば、Windows 上で Linux のモジュールができたことになる! * リモートでやる方法 [#pab5683c] といっても、telnet や rlogin でコマンド叩くのは、直接 Linux 上で作業するのと変わらないので、ここは Eclipse を使ってリモートでコンパイルする方法を書く。 ** rsh の設定 [#bf6a0709] rsh を使うので、ホストとなる Linux 側で以下の設定をする。rsh は大抵デフォルトで入ってるけど、最近はセキュリティ性を考慮して無効になっていることが多い。 + rsh サーバが入っているか確認。 $ rpm -qa rsh-server rsh-server-0.17-58.fc12.i686 ※ ↑私の環境の場合の例。とにかく入っていれば何かヒットする。 + rsh サーバはなかった場合はインストール。(あれば、次の手順へ) $ su # yum install rsh-server + rsh がインストールされると、以下のファイルが作成されるので確認。 /etc/xinetd.d/rexec /etc/xinetd.d/rsh + /etc/xinetd.d/rexec を開いて disable = no に変更する。 service exec { disable = no # ← ここ。他はいじらない。 socket_type = stream wait = no user = root log_on_success += USERID log_on_failure += USERID server = /usr/sbin/in.rexecd } + /etc/xinetd.d/rsh を開いて disable = no に変更する。 service shell { disable = no # ← ここ。他はいじらない。 socket_type = stream wait = no user = root log_on_success += USERID log_on_failure += USERID server = /usr/sbin/in.rshd } + ファイアウォールの設定で 514 を許可する。 -- GNOME で「システム」→「管理」→「ファイアウォール」で「その他のポート」に追加しても良いし、/etc/sysconfig/iptables に追加するでも良い。 -- もしかしたら、512 番とか 513 番かもしれない。でも shell は多分 514 のはず。 + xinetd を再起動する。 $ su # /etc/rc.d/init.d/xinetd restart xinetd を停止中: [ OK ] xinetd を起動中: [ OK ] + ログインするユーザのホームディレクトリへ移動。 $ cd ~ $ pwd /home/(ユーザ名) + .rhosts というファイルをつくって、ログインを許可するクライアントとユーザ名を書く。 -- クライアントが 192.168.1.255、 ユーザが hogehoge の場合の例。 $ vi .rhosts 192.168.1.255 hogehoge # ← スペースで区切る。 + できたファイルのパーミッションを確認する。 $ ls -l -a | grep .rhosts -rw-rw-r--. 1 hogehoge group1 28 2010-05-20 16:02 .rhosts 多分、グループに書き込み許可がついてる。不思議なことに、所有者以外に書き込み許可があると、rsh でパーミッションエラーが出る。ので、自分だけ書き込み許可をする。 $ chmod 644 .rhosts $ ls -l -a | grep .rhosts -rw-r--r--. 1 hogehoge group1 28 2010-05-20 16:02 .rhosts -rw-r--r-- になっていれば OK。 ここまでで、rsh の設定は終わり。 Windows 側に戻って Cygwin の rsh で繋いでみる。&br; ちなみに、最近の Cygwin は rsh がデフォルトで入ってこないので、入れてない場合はまずインストールしておく。Setup.exe からいつもの感じで入れればいい。「Net」カテゴリの下あたりにあるはず。 ということで、つないでみる。 接続先 Linux マシンが 192.168.1.1、ユーザ名 hogehoge とすると、 $ rsh -l hogehoge 192.168.1.1 -n "hostname" これで Linux マシンのホスト名が返ってくれば設定は OK。 ** samba の設定 [#o3a6a0aa] samba も使うので、その設定。下記を参考にどうぞ。 - [[Linux メモ - Samba の設定:http://www.mlexp.com/wiki/index.php?Linux%20%A5%E1%A5%E2#a22ee286]] samba を設定したら下記設定をしておく。 + 共有ディレクトリをネットワークドライブに設定しておく。 -- ここは、以下のように設定したとする。 -- Linux 側 --- 共有ディレクトリ : /var/samba/share -- Windows 側 --- ネットワークドライブ : \\(Linux ホスト名)\share → Z:\ ドライブ + Z ドライブの下に Z:\workspace\hello\src というフォルダを作成しておく。 -- Linux 側で mkdir しても良いし、Windows 側でフォルダをつくっても OK。 + Linux 側で ビルドするディレクトリとシェルを作成しておく。 $ cd ~ $ mkdir rmake $ cd rmake $ vi rmake.sh #!bin/bash cd /var/samba/workspace/hello/src make $1 ※ フォルダやシェルの名前は何でも良い。&br; ※ cd の先は make する場所。つまり Makefile を配置する予定地。 ** Eclipse の設定 [#kf13644d] Eclipse でリモートコンパイルの設定をする。 + Eclipse 起動。 + 「ファイル」→「新規」→「C プロジェクト」を選択。 + 下記を設定して「完了」。 -- プロジェクト名 : hello(何でも良い) -- プロジェクトタイプ : Makefile プロジェクト → 空のプロジェクト -- あとはデフォルトのままで。 + 画面左ペインのプロジェクトを右クリックして「新規」→「フォルダ」を選択して「src」という名前でフォルダ作成。 -- フォルダ名 : src -- 「拡張」ボタンを押して、「ファイルシステム内のフォルダにリンク」にチェックを入れて、上記で作成したネットワークドライブの src フォルダを指定する。 --- Z:\workspace\hello\src + 画面左ペインのプロジェクトを右クリックして「新規」→「フォルダ」を選択して「make」という名前でフォルダ作成。 + 「make」フォルダを右クリックして「新規」→「ファイル」で「Makefile」という名前のファイルを作成。 + 画面左ペインで「make」→「Makefile」をダブルクリックして下記のように記述。 all : rsh 192.168.1.1 -l hogehoge -n "~/rmake/rmake.sh" .PHONY : clean clean : rsh 192.168.1.1 -l hogehoge -n "~/rmake/rmake.sh" + 「src」フォルダを右クリックして「新規」→「ソースファイル」で「hello.c」という名前のファイルを作成。 + 画面左ペインで「src」→「hello.c」をダブルクリックして下記のように記述。 #include <stdio.h> int main(int argc, char* argv[]) { printf("Hello World!\n"); return 0; } + 「src」フォルダを右クリックして「新規」→「ファイル」で「Makefile」という名前のファイルを作成。 + 画面左ペインで「src」→「Makefile」をダブルクリックして下記のように記述。 hello: hello.c gcc -o hello hello.c + 画面左ペインのプロジェクトを右クリックして「プロパティ」を選択。 + 下記を設定して「OK」。 -- 「C/C++ ビルド」の「ビルダー設定」タブで下記を設定。 --- ビルドロケーション : ${workspace_loc:/hello/make}&br; ※プロジェクトの make フォルダを指定する。 -- 「C/C++ ビルド」下の「環境」で、次の環境変数を追加。 --- 名前 : PATH --- 値 : C:\Cygwin\bin ※ Cygwin の bin にパスを通すということ。 -- 「C/C++ ビルド」下の「設定」の「バイナリパーサー」タブで下記を設定。 --- 「GNU Elf パーサー」にチェック。 --- それ以外は OFF で。 + 「プロジェクト」→「すべてビルド(Ctrl + B)」でビルドしてみる。 -- ちょっと時間がかかるかも。 + いろいろ警告が出るかもしれないけど、src フォルダに hello というファイルができていればとりあえず OK。 + その hello を Linux 側で実行してみる。動けば、一応成功。 $ /var/samba/share/workspace/hello/src/hello Hello World! でも、これは速度的にあんまり実用的じゃないかなぁ。 ----- [[Linux メモ]]