怎么着编写二个独门的,编写翻译安装

时间:2020-03-17 11:21来源:2020欧洲杯冠军竞猜官方网站
独立的 PHP 扩展可以独立于 PHP源码之外进行分发。要创建一个这样的扩展,需要准备好两样东西: 因为个性化推荐系统的开发,是架构组与策略组的跨小团队合作,所以策略方不愿意公

独立的 PHP 扩展可以独立于 PHP 源码之外进行分发。要创建一个这样的扩展,需要准备好两样东西:

因为个性化推荐系统的开发,是架构组与策略组的跨小团队合作,所以策略方不愿意公开自己的代码,所以就只能采用我们提供系统功能,对方提供策略部分.so文件来实现(策略团队以C/C 作为主要语言)。

2020欧洲杯冠军竞猜官方网站 1

  • 配置文件 (config.m4)
  • 你的模块源码

一、ext_skel 脚本

PHP 扩展由几个文件组成,这些文件对所有扩展来说都是通用的。不同扩展之间,这些文件的很多细节是相似的,只是要费力去复制每个文件的内容。幸运的是,有脚本可以做所有的初始化工作,名为 ext_skel,自 PHP 4.0 起与其一起分发。

不带参数运行 ext_skel 在 PHP 5.6.24(最新正式版本) 中会产生以下输出:

./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]]
           [--skel=dir] [--full-xml] [--no-help]

 --extname=module   module is the name of your extension
  --proto=file       file contains prototypes of functions to create
  --stubs=file       generate only function stubs in file
  --xml              generate xml documentation to be added to phpdoc-svn
  --skel=dir         path to the skeleton directory
  --full-xml         generate xml documentation for a self-contained extension
                     (not yet implemented)
  --no-help          don't try to be nice and create comments in the code
                     and helper functions to test if the module compiled

通常来说,开发一个新扩展时,仅需关注的参数是 --extname 和 --no-help。除非已经熟悉扩展的结构,不要想去使用 --no-help; 指定此参数会造成 ext_skel 在生成文件里省略很多有用的注释。剩下的 --extname 会将扩展的名称传给 ext_skel。"name" 是一个全为小写字母的标识符,仅包含字母和下划线,在 PHP 发行包的 ext/ 文件夹下是唯一的。*** 官网说了:其它参数不用明白,也不要尝试。 ***

image.png

接下来我们来描述一下如果创建这些文件并组合起来。

执行创建edutest1

 ✘ zhangxuefeng@zhangxuefengdeMac-mini  ~/Developer/php-5.6.24/ext  ./ext_skel --extname=edutest1
Creating directory edutest1
Creating basic files: config.m4 config.w32 .gitignore edutest1.c php_edutest1.h CREDITS EXPERIMENTAL tests/001.phpt edutest1.php [done].

To use your new extension, you will have to execute the following steps:

1.  $ cd ..
2.  $ vi ext/edutest1/config.m4
3.  $ ./buildconf
4.  $ ./configure --[with|enable]-edutest1
5.  $ make
6.  $ ./sapi/cli/php -f ext/edutest1/edutest1.php
7.  $ vi ext/edutest1/edutest1.c
8.  $ make

Repeat steps 3-6 until you are satisfied with ext/edutest1/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writing
code and repeat the last two steps as often as necessary.

前面章节我会先简要说明一下安装过程, 后面章节我会记录在安装期间踩过的坑.
Linux 下编译软件的步骤参见Linux 编译软件的步骤

准备好系统工具

想要扩展能够在系统上编译并成功运行,需要准备转以下工具:

  • GNU autoconf
  • GNU automake
  • GNU libtool
  • GNU m4

以上这些都可以从 获取。

注:以上这些都是类 Unix 环境下才能使用的工具。

二、与 UNIX 构建系统交互: config.m4

扩展的 config.m4 文件告诉 UNIX 构建系统哪些扩展 configure 选项是支持的,你需要哪些扩展库,以及哪些源文件要编译成它的一部分。


改装一个已经存在的扩展

为了显示出创建一个独立的扩展是很容易的事情,我们先将一个已经内嵌到 PHP 的扩展改成独立扩展。安装 PHP 并且执行以下命令:

$ mkdir /tmp/newext
$ cd /tmp/newext

现在你已经有了一个空目录。我们将 mysql 扩展目录下的文件复制过来:

$ cp -rp php-4.0.X/ext/mysql/* .
# 注:看来这篇 README 真的需要更新一下了
# PHP7 中已经移除了 mysql 扩展部分

到这里扩展就完成了,执行:

$ phpize

现在你可以独立存放这个目录下的文件到任何地方,这个扩展可以完全独立存在了。

用户在编译时需要使用以下命令:

$ ./configure 
       [--with-php-config=/path/to/php-config] 
       [--with-mysql=MYSQL-DIR]
$ make install

这样 MySQL 模块就可以使用内嵌的 MySQL 客户端库或者已安装的位于 MySQL 目录中的 MySQL。

注:意思是说想要编写 PHP 扩展,你既需要已经安装了 PHP,也需要下载一份 PHP 源码。

autoconf 语法简介

config.m4 文件使用 GNU autoconf 语法编写。简而言之,就是用强大的宏语言增强的 shell 脚本。注释用字符串 dnl 分隔,字符串则放在左右方括号中间(例如,[ 和 ])。字符串可按需要多次嵌套引用。

服务器环境

  • CentOS 7
  • PHP 7.0.20
  • Nginx 1.10.1

定义一个新扩展

我们给示例扩展命名为 “foobar”。

新扩展包含两个资源文件:foo.c 和 bar.c(还有一些头文件,但这些不只重要)。

示例扩展不引用任何外部的库(这点很重要,因为这样用户就不需要特别指定一些编译选项了)。

LTLIBRARY_SOURCES 选项用于指定资源文件的名字,你可以有任意数量的资源文件。

注:上面说的是 Makefile.in 文件中的配置选项,可以参考 xdebug。

根据需要修改config.m4

  1. 切换到ext/edutest1/目录。
  2. vi config.m4
  3. 将下面的第一、三行取消注释,并删掉第二行:
16 dnl PHP_ARG_ENABLE(edutest1, whether to enable edutest1 support,
 17 dnl Make sure that the comment is aligned:
 18 dnl [  --enable-edutest1           Enable edutest1 support])

修改为:

16 PHP_ARG_ENABLE(edutest1, whether to enable edutest1 support,
 17     [  --enable-edutest1           Enable edutest1 support])
  1. PHP_SUBST一行的注释打开:
19 if test "$PHP_EDUTEST1" != "no"; then
……
59   PHP_SUBST(EDUTEST1_SHARED_LIBADD)
60
61   PHP_NEW_EXTENSION(edutest1, edutest1.c, $ext_shared)
62 fi

简要说明:

安装 PHP 扩展的通用流程

  • 1.下载解压

cd /usr/local/src #一般把第三方软件的源码放在这个目录
wget http://xxx.com/ #软件源码下载地址
tar -zxvf 压缩包 #解压缩. 根据不同类型的压缩包,使用不同的解压缩命令, 比如 ".gz 压缩包"使用 -zx , ".bz 压缩包"使用 -jx
```

  • 2.编译安装

cd /解压缩后/的文件夹
/usr/local/bin/phpize #用 phpize 命令生成 configure 配置文件
./configure --with-php-config=/usr/local/php/bin/php-config #配置
make #编译
sudo make install #安装
```

  • 3.修改 php.ini

    在 php.ini 中添加:

extension=名称.so # "名称"为扩展的名称. 或者可以用重定向的命令修改 php.ini sudo echo extension=名称.so >> /etc/php.ini
```

  • 4.重启服务

php -m | grep 扩展名称 #验证是否正确安装上了扩展
sudo systemctl reload php-fpm nginx #systemctl 是 CentOS 7 的命令
```


修改 m4 后缀的配置文件

m4 配置文件可以指定一些额外的检查。对于一个独立扩展来说,你只需要做一些宏调用即可。

PHP_ARG_ENABLE(foobar,whether to enable foobar,
[  --enable-foobar            Enable foobar])

if test "$PHP_FOOBAR" != "no"; then
  PHP_NEW_EXTENSION(foobar, foo.c bar.c, $ext_shared)
fi

PHP_ARG_ENABLE 会自动设置好正确的变量以保证扩展能够被 PHP_NEW_EXTENSION 以共享模式启动。

PHP_NEW_EXTENSION 的第一个参数是扩展的名称,第二个参数是资源文件。第三个参数 $ext_shared 是由 PHP_ARG_ENABLE/WITHPHP_NEW_EXTENSION 设定的。

请始终使用 PHP_ARG_ENABLEPHP_ARG_WITH 进行设置。即使你不打算发布你的 PHP 模块,这些设置也可以保证让你的模块和 PHP 主模块的接口保持一体。

注:PHP_ARG_ENABLEPHP_ARG_WITH 应该是用于定义模块是动态扩展还是静态编译进 PHP 中,就跟编译 PHP 时使用的 --enable-xxx--with-xxx 一样。

宏PHP_ARG_ENABLE,含有三个参数:

第一个参数,extest1./configure建立了名为enable-edutest1的选项
第二个参数将会在./configure命令处理到该扩展的配置文件时,显示该参数的内容
第三个参数是./configure命令的帮助,在使用./configure --help的时候显示

编译安装 Memcached 扩展

  • 1.安装 memcached

    • 编译安装 memcached 依赖的 libevent 库

cd /usr/local/src
wget https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz
tar -zxvf libevent-2.1.8-stable.tar.gz
cd libevent-2.1.8-stable
./configure --prefix=/usr/local/libevent
make && make test && sudo make install
```

- **编译安装 memcached**

```shell

cd /usr/local/src
wget http://memcached.org/files/memcached-1.4.39.tar.gz
tar -zxvf memcached-1.4.39.tar.gz
cd memcached-1.4.39.tar.gz
./configure --prefix=/usr/local/memcached
make && make test && sudo make install
```

  • 2.安装 PHP 的 Memcached 扩展

    • 编译安装 Memcached 扩展插件依赖的 libmemcached 库

cd /usr/local/src
wget https://launchpad.net/libmemcached/1.0/1.0.18/ download/libmemcached-1.0.18.tar.gz
tar -zxvf libmemcached-1.0.18.tar.gz
cd libmemcached-1.0.18.tar.gz
./configure --prefix=/usr/local/libmemcached --with-memcached=/usr/local/memcached/bin/memcached
make && make test && sudo make install
```

- **编译安装 PHP PECL 的 Memcached 扩展**

```shell

cd /usr/local/src
wget https://pecl.php.net/get/memcached-3.0.3.tgz
2020欧洲杯冠军竞猜官方网站,tar -zxvf memcached-3.0.3.tgz
cd memcached-3.0.3
/usr/local/bin/phpize #用 phpize 命令生成 configure 配置文件
./configure --with-php-config=/usr/bin/php-config --with-libmemcached-dir=/usr/local/libmemcached
make && make test && sudo make install
```

验证一下 memcached 插件是否正确安装:

ls /usr/lib64/php/modules | grep memcached
  • 3.修改 php.ini
vim /etc/php.ini #可以通过 whereis php 来查看 php.ini 文件的位置

在 php.ini 中添加:

extension=memcached.so
  • 4.重启服务
sudo systemctl reload php-fpm

创建资源文件

ext_skel 可以为你的 PHP 模块创建一些通用的代码,你也可以编写一些基本函数定义和 C 代码来处理函数的参数。具体信息可以查看 READNE.EXT_SKEL。

不要担心没有范例,PHP 中有很多模块供你参考,选择一个简单的点开始,添加你自己的代码。

注:ext_skel 可以生成好基本模块需要的资源文件和配置文件,不需要自己创建。

宏PHP_NEW_EXTENSION

该宏声明了扩展的模块和必须要编译作为扩展一部分的源码文件。如果需要多个源文件,则使用空格分隔,第三个参数$ext_shared与调用PHP_SUBST(EDUTEST1_SHARED_LIBADD)有关。

编译 Memcached 过程中踩过的坑

修改自定义模块

将 config.m4 文件和资源文件放到同一个目录中,然后执行 phpize (PHP 4.0 以上的版本编译 PHP 的时候都安装了 phpize)。

如果你的 phpize 不在系统环境变量中,你需要指定绝对路径,例如:

$ /php/bin/phpize

这个命令会自动复制必需的构建文件到当前目录并根据 config.m4 创建配置文件。

通过以上的步骤,你已经有了一个独立的扩展了。

三、phpize、配置、编译

因为我的Mac上已经自带了PHP的环境,就不采取全套PHP源码编译的方法了。使用命令行工具phpize对扩展进行编译。

phpize 命令是用来准备 PHP 扩展库的编译环境的工具。如果系统中没有 phpize 命令并且使用了预编译的包(例如 RPM),那要安装 PHP 包相应的开发版本,此版本通常包含了 phpize 命令以及相应的用于编译 PHP 及其扩展库的头文件。使用 phpize --help 命令可以显示此命令用法。

使用root权限执行phpize:

 zhangxuefeng@zhangxuefengdeMac-mini  ~/Developer/php-5.6.24/ext/edutest1  sudo /usr/bin/phpize
Password:
Configuring for:
PHP Api Version:         20121113
Zend Module Api No:      20121212
Zend Extension Api No:   220121212

configure,需要使用php-config工具:

php-config 是一个简单的命令行脚本用于获取所安装的 PHP 配置的信息。在编译扩展时,如果安装有多个 PHP 版本,可以在配置时用 --with-php-config 选项来指定使用哪一个版本编译,该选项指定了相对应的 php-config 脚本的路径。

 ✘ zhangxuefeng@zhangxuefengdeMac-mini  ~/Developer/php-5.6.24/ext/edutest1  sudo ./configure --enable-edutest1 --with-php-config=/usr/bin/php-config
checking for grep that handles long lines and -e... /usr/bin/grep
checking for egrep... /usr/bin/grep -E
checking for a sed that does not truncate output... /usr/bin/sed
checking for cc... cc
……

Make 编译:

 zhangxuefeng@zhangxuefengdeMac-mini  ~/Developer/php-5.6.24/ext/edutest1  sudo make
Password:
/bin/sh /Users/zhangxuefeng/Developer/php-5.6.24/ext/edutest1/libtool --mode=compile cc  -I. -I/Users/zhangxuefeng/Developer/php-5.6.24/ext/edutest1 -DPHP_ATOM_INC -I/Users/zhangxuefeng/Developer/php-5.6.24/ext/edutest1/include -I/Users/zhangxuefeng/Developer/php-5.6.24/ext/edutest1/main -I/Users/zhangxuefeng/Developer/php-5.6.24/ext/edutest1 -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /Users/zhangxuefeng/Developer/php-5.6.24/ext/edutest1/edutest1.c -o edutest1.lo
mkdir .libs
……
……
……
Build complete.
Don't forget to run 'make test'.

Make Install:

 zhangxuefeng@zhangxuefengdeMac-mini  ~/Developer/php-5.6.24/ext/edutest1  sudo make install
Installing shared extensions:     /usr/lib/php/extensions/no-debug-non-zts-20121212/

添加完整路径到php.ini中:

 zhangxuefeng@zhangxuefengdeMac-mini sudo vim /etc/php.ini
……
899 extension=/usr/lib/php/extensions/no-debug-non-zts-20121212/edutest1.so
……

总共需要编译哪些软件?

总共需要编译安装 4 个软件:

  • 先安装 Memcached 依赖的 libevent;
  • 然后安装 Memcached 库;
  • 再安装 PHP PECL 的 Memcached 插件依赖的 libmemcached 库;
  • 最后安装 PHP PECL 的 Memcached 插件.

咳咳. 我曾经因为混淆了 Memcached 和 PHP 的 memcached 插件, 而浪费了很多时间. 囧


安装扩展

扩展可以通过以下命令编译安装:

$ ./configure 
            [--with-php-config=/path/to/php-config]
$ make install

四、重启HTTP服务:

2020欧洲杯冠军竞猜官方网站 2

phpinfo截图.png

如何寻找 phpize 命令和 php-config 命令?

使用 whereis 命令, 比如:

whereis phpize #会显示类似路径, 像这样 phpize: /usr/bin/phpize /usr/share/man/man1/phpize.1.gz
whereis php-config #会显示类似路径, 像这样 php-config: /usr/bin/php-config /usr/share/man/man1/php-config.1.gz

或者使用 find 命令:

sudo find / -name phpize
sudo find / -name php-config

PS. php-config 是获取所安装的 PHP 配置信息的命令行脚本.
在编译扩展时,如果安装有多个 PHP 版本,可以在配置时用 --with-php-config 选项来指定使用哪一个版本编译,该选项指定了相对应的 php-config 脚本的路径.


给模块添加共享支持

有时候独立扩展需要是共享的已供其他模块加载。接下来我会解释如何给已经创建好的 foo 模块添加共享支持。

  1. 在 config.m4 文件中,使用 PHP_ARG_WITH/PHP_ARG_ENABLE 来设定扩展,这样就可以自动使用 --with-foo=shared[,..]--enable-foo=shared[,..] 这样的指令作为编译参数了。
  2. 在 config.m4 文件中,使用 PHP_NEW_EXTENSION(foo,.., $ext_shared) 使扩展可以被构建。
  3. 添加以下代码到你的 C 语言资源文件中:
   #ifdef COMPILE_DL_FOO
   ZEND_GET_MODULE(foo)
   #endif

这一段讲的上面都提到过了,这里只是又强调了一下。

成功!

没有 php-config 命令怎么办?

如果 PHP 是通过编译安装的, php-config 命令会在 PHP 安装目录的 bin 目录下.
但是如果 PHP 是用 yum 安装的, 是没有 php-config的. 需要额外安装相应版本的 php-devel 包:

# 因为我是用 yum 安装的 php70u, 所以
yum search php70u-devel
sudo yum install php70u-devel.x86_64

之后 whereis php-config, 就会发现已经出现在 /usr/bin/php-config.

PS. "devel" 表示库的源码.
提醒: 用 yum 安装库, 不光要安装库本身(可执行文件), 往往还需要安装库的源码 xxx-devel

注意:
网上有些建议直接安装 php-devel:

yum install php-devel

但是我执行这个命令碰到这样的报错(估计由于这台服务器之前安装过 PHP 5.4):

Error: php70u-cli conflicts with php-cli-5.4.16-42.el7.x86_64
Error: php70u-common conflicts with php-common-5.4.16-42.el7.x86_64
Error: php70u-json conflicts with php-common-5.4.16-42.el7.x86_64
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest

所以建议还是用 yum 搜索安装对应 PHP 版本的 devel 为妥.


PECL 网站约定

如果你打算发布你的扩展到 PECL 的网站,需要考虑以下几点:

  1. 添加 LICENSE 或 COPYING 到 package.xml
  2. 需要在扩展头文件中定义好版本信息,这个宏会被 foo_module_entry 调用来声明扩展版本:
   #define PHP_FOO_VERSION "1.2.3"

用 yum 搜索不到高版本的 php-devel 怎么办?

官方的 yum 仓库可能没有比较新的库文件, 可以添加公认不错的 ius 仓库:

如果是 CentOS 7:

sudo yum install https://centos7.iuscommunity.org/ius-release.rpm -y

如果是 CentOS 6:

sudo yum install https://rhel6.iuscommunity.org/ius-release.rpm -y

也可以参考这篇文章 -- Centos/RedHat 7/6/5切换阿里云源并安装EPEL/IUS/REMI仓库.


在 PECL 中搜索 "memcached" 有 3 个结果, 如何选择?

在 PECL 中搜索 "memcached" 有 3 个结果:

2020欧洲杯冠军竞猜官方网站 3

image.png

  • mysqlnd_memcache 是将 SQL 语句转化成 MySQL InnoDB memcached Daemon, 可以排除;
  • memcache 最近的 stable 版本 是在 2012-09-22, 说明已经停止维护, 排除;
  • memcached 插件, 需要依赖 libmemcached 库, 安装比较麻烦, 不过更新更频繁, 而且最新的 stable 版本是 2017-02-20. 所以选择这个插件.

为什么 PHP 的 memcached 插件需要 phpize 命令来生成 configure 文件?

因为 PHP 插件和 PHP 是深度耦合的.
而每个人的 PHP 环境是不一样的(PHP 版本不同), 所以需要根据环境来定制 configure.

比如分别在我的服务器和笔记本上执行 phpize 命令, 会获得这样结果:

2020欧洲杯冠军竞猜官方网站 4

image.png

2020欧洲杯冠军竞猜官方网站 5

image.png

两者是不同的


编译时报错

编译时报错:

make -j2  all-am
make[1]: Entering directory `/usr/local/src/libmemcached-1.0.18'
  CXX      libhashkit/libhashkit_libhashkit_la-aes.lo
./libtool: line 1125: g  : command not found
make[1]: *** [libhashkit/libhashkit_libhashkit_la-aes.lo] Error 1
make[1]: Leaving directory `/usr/local/src/libmemcached-1.0.18'
make: *** [all] Error 2

根据高人指点, 安装编译时可以一股脑装上这些依赖库:

yum -y install gcc gcc-c   autoconf libjpeg libjpeg-devel 
libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel 
zlib zlib-devel glibc glibc-devel glib2 glib2-devel 
bzip2 bzip2-devel ncurses ncurses-devel 
curl curl-devel e2fsprogs e2fsprogs-devel 
krb5 krb5-devel libidn libidn-devel 
openssl openssl-devel openldap openldap-devel 
nss_ldap openldap-clients openldap-servers gd gd2 
gd-devel gd2-devel perl-CPAN pcre-devel

如果报错中包含 permission denied, 表示是用户组的权限问题, 说明你在 make install 前面忘了加 sudo, 或者你可以 su 进入管理员帐号再进行编译操作.


安装后, 如何在 PHP 中使用 Memcached?

给个小例子:

在服务器中启动 Memcached:

/usr/local/memcached/bin/memcached -m 64 -p 11211 -u nobody -d
参数 说明 默认值
-m 最大使用内存量(单位 MB) 64
-p 端口号 11211
-u 用户名(在使用 root 运行的时候) nobody
-d 做为后台程序(Daemon)启动 -

然后写个简单的 PHP 文件:

<?php
$mem = new Memcached(); //实例化一个 Memcached 的对象
$mem->addServer('127.0.0.1', 11211) or die ('Could not connect'); //连接 Memcached 服务器
$mem->set('name', 'phper'); //设置 key - value 值
echo $mem->get('name'); //通过 key 取 value

PS. 其它详细的用法, 可以参考 PHP 官方文档的 Memcached 章节


参考文章

  • PHP 官方文档 - Memcached
  • 手动为php安装memcached扩展模块
  • StackOverflow - not able to install php-devel in aws centos ec2 instance for php version 5.6.22
  • Linux 编译 常用PHP 扩展
  • Linux下 config/configure/Configure、make 、make test/make check、sudo make install 的作用
  • Centos/RedHat 7/6/5切换阿里云源并安装EPEL/IUS/REMI仓库
  • Linux 编译软件的步骤

文章历史

  • 2017/07/09 (第一次发布);
  • 2017/07/09 写了个 PHP 使用 Memcached 的小例子;
  • 2017/07/10 修正拼写错误(将 ./configure误写成了 .configure). 修正编译 PHP 的 Memcached 插件时的编译配置错误; 增加章节 -- "为什么 PHP 的 memcached 插件需要 phpize 命令来生成 configure 文件";

如果我的文章对你有用, 希望给些改进的建议, 或者打个"喜欢" _

编辑:2020欧洲杯冠军竞猜官方网站 本文来源:怎么着编写二个独门的,编写翻译安装

关键词: 欧洲杯竞猜