Zend Engineを読む① | php-srcをビルドする

phpカテゴリ記事のアイキャッチ PHP

はじめに

今回php-srcをビルドした環境は下記の通りです。MacOSでビルドしております。

mac 15.4.1(24E263)
プロセッサ 1.4 GHz クアッドコアIntel Core i5
メモリ 8GB
GitHub – php/php-src: The PHP Interpreter
The PHP Interpreter. Contribute to php/php-src development by creating an account on GitHub.

今回は 上記の php-src をクローンしてビルドしています。Zend Engine は php-src の内部に含まれている PHP の実行エンジンです。

なぜ、php-srcを読むかというと私は趣味でプログラミング言語を自作しています。Zend Engine の内部構造を参考にさせていただきたく、デバッグをしながら解析をしたいと思い、ビルドを実行しました。ビルド手順などを備忘録として、残しますので、Zend Engine の内部構造について興味がある方の参考になればと思います。以前、Zend Engine の内部構造の概要について説明した記事もあるので、こちらもよかったら、参考にしてください。

Zend Engineとは?PHPの内部処理(コンパイル〜実行)を解説
PHPの内部構造を学習してみた

ビルドに必要なもの

さて、ここからは、実際にビルドを進めていきたいと思います。

まず初めに、ビルドに必要なライブラリなどをインストールしていきます。念のため、入っているか、確認します。

//環境に合わせて、configファイルを自動生成してくれるライブラリ
autoconf --version

//構文解析器(Parser)を生成するためのツールです。Zend Engine では PHP の文法解析に利用されています。
bison --version

//ZendEngineが字句解析器(Lexer) で使用しているツールです。
re2c --version

入っていなければ、インストールします。

brew install re2c
brew install bison
brew install autoconf

buildconf

必要なツールがインストールできたら、実際にビルドをしていきます。

./buildconf --force

上記コマンド(シェルスクリプト) で初期化をします。↓シェルスクリプト内の説明に記載がありました。

*nixシステム上でPHPをビルドするためのファイル(configureおよびmain/php_config.h.in)を生成するautoconfおよびautoheaderのラッパーです。configureスクリプトは、指定されたオプションとシステムに基づいてPHPビルドをカスタマイズするために使用されます。
buildconfは新しいconfigureスクリプトと必要なファイルを生成するために使用されます。

PHP の configure は最初から存在するわけではなく、buildconf が autoconf を利用して configure を生成します。

あとは、キャッシュの削除なども行います。

configure

./configure --enable-debug

buildconf によって生成された configure を実行します。configure を実行すると

OS確認
コンパイラ確認
ライブラリ確認
オプション解析

などが実行されます。configure が何をやっているの気になって中身を見てみましたが、10万行以上ありました、、、

ちなみに、オプションの –enable-debug ですが、内部的には

デバッグビルドにする
↓
CFLAGSにデバッグ用オプション追加
↓
ZendのASSERT有効化

などの設定が行われます。

General settings:
  --enable-gcov           Enable GCOV code coverage - FOR DEVELOPERS ONLY!!
  --enable-debug          Compile with debugging symbols

make

実際にコンパイルする際にmake コマンドを使用します。

わかりやすくするために、コンパイルする前にいくつか、デバッグを仕込んでおきます。

//  /クローンした場所/php-src/sapi/cli/php_cli.c

static int php_cli_startup(sapi_module_struct *sapi_module_ptr) /* {{{ */
{
	printf("php_cli_startup\n");
	return php_module_startup(sapi_module_ptr, NULL);
}
//  /クローンした場所/php-src/main/main.c

zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module)
{
	zend_utility_functions zuf;
	zend_utility_values zuv;
	zend_result retval = SUCCESS;
	int module_number = 0;
	zend_module_entry *module;

	printf("php_module_start_up\n");

実行するphpファイルを作ります。

//テスト用ファイル

<?php

$a = 10;
$b = 20;

if ($a < $b) {
    echo "hello\n";
}

Zend Engine にデバッグを仕込んだので、コンパイルします。

make -j8

configure が生成した Makefile を元に実際のコンパイルを実行します。

-j8 は並列ビルド数を指定するオプションです。CPU コア数に応じて変更してください。

これにより、先ほど作成したテスト用のphpファイルを実行すると仕込んだデバッグが表示されるかと思います。

//実行結果
hello@test php-src % ./sapi/cli/php test.php
php_cli_startup
php_module_start_up
hello

最後に

//今回実行したコマンドの流れ
buildconf
↓
configure
↓
Makefile生成
↓
make

今回 php-src をビルドをしましたが、Zend Engine の構造はとても複雑で読むのに苦労しますが、実際にデバッグしながら解析を行うことで、より解析しやすくなると思います。私もZend Engine を参考に自作の言語の開発をこれからも進めていきたいと思います。最後まで読んでくださり、ありがとうございました。よければ、自作言語シリーズも読んでいただけると嬉しいです。

そして次回は Zend Engine のエントリポイントである main() から、PHP コードがどのように実行されるのかを追ってみたいと思います。

自作プログラミング言語
「自作プログラミング言語」の記事一覧です。

コメント

タイトルとURLをコピーしました