こんにちは、高木です。
前回まで、PHPで前処理する話題からは少し横道にそれました。PHPを使ってコンパイルするには、今回話題にする「オートリンク」を実現するためです。
オートリンクというのは、使用したヘッダーファイルに応じて、必要なライブラリを自動的にリンクする仕組みのことです。Visual C++であれば、次のように書くことでオートリンクを実現することができます。
0 1 2 |
#pragma comment(lib, ライブラリ名) |
この機能は非常に便利ですが、残念ながら利用できる処理系が限られています。GCCなどではこの方法でオートリンクを実現することができません。
そこで、独自にオートリンクを実現しようと思います。PHPで前処理するソースファイルに、次に挙げるPHPの関数autolinkの呼び出しを埋め込むことで、リンクすべきライブラリの一覧がautolink.txtというファイルに書き出されます。空白区切りでライブラリ名が並んでいますので、ビルド時のコマンドライン引数に追加すればOKです。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php function autolink(string $lib): void { $path = 'autolink.txt'; $libs = []; // autolink.txtが存在すれば、内容を読み込む。 if (file_exists($path)) { $autolink = file_get_contents($path); $libs = explode(' ', trim($autolink)); } // すでに$libが含まれているのでなければ、追加する。 if (!in_array($lib, $libs)) $libs[] = $lib; // 空白区切りの文字列に直してautolink.txtに書き込む。 $autolink = implode(' ', $libs); file_put_contents($path, $autolink); } ?> |
なお、ビルドの開始前には、Makefile等でautolink.txtを削除しておく必要があります。前回使ったautolink.txtが残っていると、すでに存在しないライブラリをリンクしようとしてしまうなど、誤動作の原因になります。
Visual C++向けの#pragma comment指令もautolink関数の中で出力するという手も考えられますが、ライブラリ名は処理系ごとに異なるので、C言語やC++のコードの中で#if指令等を使って場合分けする方がいいでしょう。
それでは、autolink関数が生成したautolink.txtを反映する処理を、以前作ったコンパイル用のPHPコードの最後の部分に反映します。
0 1 2 3 4 5 6 7 8 9 10 11 12 |
// コンパイル要求フラグが立っている場合だけコンパイルする。 if ($compile_request) { $libs = ''; $autolink_path = 'autolink.txt'; if (file_exists($autolink_path)) $libs = file_get_contents($autolink_path); $command = "g++ -MMD -o $target_file $source_file $libs"; passthru($command); } |
これでGCCでもオートリンクができるようになりました。
このように、ビルドもPHPから行うようにすることで、いろいろ融通が利くようになります。この程度の内容であれば、autolink.txtさえ作ってしまえばMakefileでも何とかなりますが、PHPを使った方がより高度なことができる可能性があります。