64位动态php扩展库的编译

 

64位动态php扩展库的编译


 工作上需要,这个问题折腾了一阵子。不过当编译成功之后,心里还是相当的兴奋,感受到了一种成就感。也是工作中的一种乐趣。

 

现在将整个过程写下来,以备后续之需。

a.shared object
(1) download and install the apache
从网络中下载apache-2.0.48.tar.gz
存至/home/tmp

cd /home/tmp
tar -xvzf apache-2.0.48.tar.gz  /usr/local
cd /usr/local/apache-2.0.48
./configure --prefix=/usr/local/apache  --enable-module=so
make
make install
cd /usr/local/apache/conf
vi httpd.conf
ServerName localhost
port 80
DirectoryIndex default.php default.phtml default.php3 default.html default.htm
AddType application/x-httpd-php .php .phtml .php3 .inc
AddType application/x-httpd-php-source .phps


(2)download and install the php
从网络中下载php-4.3.4.tar.gz
存至/home/tmp

cd /home/tmp
tar -xvzf php-4.3.4.tar.gz  /usr/local
cd /usr/local/php-4.3.4
./buildconf --force
./configure --with-apache2=/usr/local/apache/bin/apxs
make
make install
cp php.ini-dist /usr/local/lib/php.ini

(3)install the DM DBMS
参考DM安装手册,假定安装到/usr/local/DMDBMS
(4) install the DM PHP
cp dm_php   /home
cd /home/dm_php
#执行
/usr/local/bin/phpize
./configure
make


cd /usr/local/lib
vi php.ini
#修改下面配置
register_globals=on
extension_dir=/home/dm_php/modules  #dm_php.so所在路径
#添加下面语句
extensions=dm_php.so

 


;php.ini中有关连接的配置
[dm]
; 是否允许持久性连接
dm.allow_persistent = 1

; 允许建立持久性连接的最大数.  -1 为没有限制.
dm.max_persistent = -1

; 允许建立连接的最大数(包括持久性连接).  -1 为没有限制.
dm.max_links = -1

; 默认的主机地址
dm.default_host = localhost

; 默认登录的数据库
dm.default_db = SYSTEM

; 默认的连接用户名
dm.default_user = SYSDBA

; 默认的连接口令.
dm.default_pw = SYSDBA

;连接超时,这个参数未实际的用到,等待服务器支持
dm.connect_timeout = 10

;对于各种变长数据类型,每列最大读取的字节数。如果它设置为0或是小于0,那么,读取变长字段时,将显示NULL值
dm.defaultlrl = 4096

; 是否读取二进制类型数据,如果它设置为0,那么二进制将被NULL值代替
dm.defaultbinmode = 1

;是否允许检察持久性连接的有效性,如果设置为ON,那么当重用一个持久性连接时,会检察该连接是否还有效
dm.check_persistent = ON

 


关键点,也就是值得注意的2个地方:

1. 编译php源码的时候
查看configure参数后发现可以有参数直接指定lib目录
使用–with-libdir=/usr/lib64
加入configure后重新make通过

2. 编译扩展库的时候
开始一直没有连接到dmapi库,
ldd nm命令查可以发现这点。
最后找了下libtool工具的使用方法才搞定。

automake 生成的Mkefile之中修改的内容。
增加链接时的路径和链接的动态库dmapi

./php5_dm.la: $(shared_objects_php5_dm) $(PHP5_DM_SHARED_DEPENDENCIES)
 $(LIBTOOL) --mode=link $(CC) $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) -o $@ -export-dynamic -avoid-version -prefer-pic -module -rpath $(phplibdir) $(EXTRA_LDFLAGS) $(shared_objects_php5_dm) $(PHP5_DM_SHARED_LIBADD) $LIBDIR -L/lib64 -ldmapi

 

 

附libtool用法:(以下为转载)

 

作者:刘军涛 系所:微处理器研发中心 日期:2006-1-6
1 libtool的工作原理
libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中;使用libtool的标准方法,可以在不同平台上创建并调用动态库。可以认为libtool是gcc的一个抽象,其包装了gcc(或者其他的编译器),用户无需知道细节,只要告诉libtool需要编译哪些库即可,libtool将处理库的依赖等细节。libtool只与后缀名为lo、la为的libtool文件打交道。

libtool主要的一个作用是在编译大型软件的过程中解决了库的依赖问题;将繁重的库依赖关系的维护工作承担下来,从而释放了程序员的人力资源。libtool提供统一的接口,隐藏了不同平台间库的名称的差异等细节,生成一个抽象的后缀名为la高层库libxx.la(其实是个文本文件),并将该库对其它库的依赖关系,都写在该la的文件中。该文件中的dependency_libs记录该库依赖的所有库(其中有些是以.la文件的形式加入的);libdir则指出了库的安装位置;library_names记录了共享库的名字;old_library记录了静态库的名字。

当编译过程到link阶段的时候,如果有下面的命令:

$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la

libtool会到/usr/lib路径下去寻找liba.la,然后从中读取实际的共享库的名字(library_names中记录了该名字,比如liba.so)和路径(lib_dir中记录了,比如libdir=’/usr/lib’),返回诸如/usr/lib/liba.so的参数给激发出的gcc命令行。

如果liba.so依赖于库/usr/lib/libb.so,则在liba.la中将会有dependency_libs=’-L/usr/lib -lb’或者dependency_libs=’/usr/lib/libb.la’的行,如果是前者,其将直接把“-L/usr/lib –lb”当作参数传给gcc命令行;如果是后者,libtool将从/usr/lib/libb.la中读取实际的libb.so的库名称和路径,然后组合成参数“/usr/lib/libb.so”传递给gcc命令行。

当要生成的文件是诸如libmylib.la的时候,比如:

$libtool --mode=link gcc -o libmylib.la -rpath /usr/lib –L/usr/lib –la

其依赖的库的搜索基本类似,只是在这个时候会根据相应的规则生成相应的共享库和静态库。

注意:libtool在链接的时候只会涉及到后缀名为la的libtool文件;实际的库文件名称和库安装路径以及依赖关系是从该文件中读取的。

2 为何使用 -Wl,--rpath-link -Wl,DIR?
使用libtool解决编译问题看上去没什么问题:库的名称、路径、依赖都得到了很好的解决。但下结论不要那么着急,一个显而易见的问题就是:并不是所有的库都是用libtool编译的。

比如上面那个例子,

$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la

如果liba.so不是使用libtool工具生成的,则libtool此时根本找不到liba.la文件(不存在该文件)。这种情况下,libtool只会把“–L/usr/lib –la”当作参数传递给gcc命令行。

考虑以下情况:要从myprog.o文件编译生成myprog,其依赖于库liba.so(使用libtool生成),liba.so又依赖于libb.so(libb.so的生成不使用libtool),而且由于某种原因,a对b的依赖并没有写入到liba.la中,那么如果用以下命令编译:

$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la

激发出的gcc命令行类似于下面:

              gcc –o myprog /usr/lib/liba.so

由于liba.so依赖于libb.so(这种依赖可以用readelf读liba.so的ELF文件看到),而上面的命令行中,并没有出现libb.so,于是,可能会出现问题。

      说“可能”,是因为如果在本地编译的情况下,gcc在命令行中找不到一个库(比如上面的liba.so)依赖的其它库(比如libb.so),链接器会按照某种策略到某些路径下面去寻找需要的共享库:

1. 所有由'-rpath-link'选项指定的搜索路径.

2. 所有由'-rpath'指定的搜索路径. '-rpath'跟'-rpath_link'的不同之处在于,由'-rpath'指定的路径被包含在可执行文件中,并在运行时使用, 而'-rpath-link'选项仅仅在连接时起作用.

3. 在一个ELF系统中, 如果'-rpath'和'rpath-link'选项没有被使用, 会搜索环境变量'LD_RUN_PATH'的内容.它也只对本地连接器起作用.

4. 在SunOS上, '-rpath'选项不使用, 只搜索所有由'-L'指定的目录.

5. 对于一个本地连接器,环境变量'LD_LIBRARY_PATH'的内容被搜索.

6. 对于一个本地ELF连接器,共享库中的`DT_RUNPATH'和`DT_RPATH'操作符会被需要它的共享库搜索. 如果'DT_RUNPATH'存在了, 那'DT_RPATH'就会被忽略.

7. 缺省目录, 常规的,如'/lib'和'/usr/lib'.

8. 对于ELF系统上的本地连接器, 如果文件'/etc/ld.so.conf'存在, 这个文件中有的目录会被搜索.

从以上可以看出,在使用本地工具链进行本地编译情况下,只要库存在于某个位置,gcc总能通过如上策略找到需要的共享库。但在交叉编译下,上述八种策略,可以使用的仅仅有两个:-rpath-link,-rpath。这两个选项在上述八种策略当中优先级最高,当指定这两个选项时,如果链接需要的共享库找不到,链接器会优先到这两个选项指定的路径下去搜索需要的共享库。通过上面的描述可以看到:-rpath指定的路径将被写到可执行文件中;-rpath-link则不会;我们当然不希望交叉编译情况下使用的路径信息被写进最终的可执行文件,所以我们选择使用选项-rpath-link。

      gcc的选项“-Wl,--rpath-link –Wl,DIR”会把-rpath-link选项及路径信息传递给链接器。回到上面那个例子,如果命令行中没有出现libb.so,但gcc指定了“-Wl,--rpath-link –Wl,DIR”,则链接器找不到libb.so的时候,会首先到后面-rpath-link指定的路径去寻找其依赖的库。此处我们使用的编译命令的示例是使用unicore平台的工具链。

$ unicore32-linux-gcc –o myprog /usr/lib/liba.so /

-Wl,--rpath-link -Wl,/home/UNITY_float/install/usr/lib

这样,编译器会首先到“/home/UNITY_float/install/usr/lib”下面去搜索libb.so

      libtool如何把选项“-Wl,--rpath-link –Wl,DIR”传递给gcc?libtool中有一个变量“hardcode_libdir_flag_spec”,该变量本来是传递“-rpath”选项的,但我们可以修改它,添加我们需要的路径,传递给unicore32-linux-gcc。

      “hardcode_libdir_flag_spec”原来的定义如下:

hardcode_libdir_flag_spec="/${wl}--rpath /${wl}/$libdir"

我们修改后的定义如下:

hardcode_libdir_flag_spec="/${wl}—rpath-link /${wl}/$libdir /

-Wl,--rpath-link -Wl,/home/UNITY_float/install/usr/lib /

                    -Wl,--rpath-link -Wl,/home/UNITY_float/install/usr/X11R6/lib "

这样,当libtool在“--mode=link”的模式下,就会把选项“-Wl,--rpath-link –Wl,DIR”传递给gcc编译器了。

 

 

附2:

网上的资料

 

 

PHP在64位系统下编译出错
make后报错
/usr/lib/libltdl.so: could not read symbols: File in wrong format
发现其调用32位lib
如果我们直接将调用的文件
ln -s /usr/lib64/libltdl.so.3.1.4 /usr/lib/libltdl.so
PHP可以正常编译
但是为了防止可能出现的问题
我们不使用这种方法
查看configure参数后我发现可以有参数直接指定lib目录
使用–with-libdir=/usr/lib64
加入configure后重新make通过

有个老外也遇见同样问题
[url]http://forums.gentoo.org/viewtopic-p-3926345.html?sid=0c03688539961177d24652f60075387e[/url]

体验64位,在FC4 x86_64上编译Apache,PHP
安装环境:
    Fedora Core 4 x86_64 Release 1
安装系统时选择:
    默认Gnome桌面环境
    默认系统开发工具包
    默认Gnome开发工具包
处理器:
    AMD64 Sempron(R) 2500+
大致安装时间:
    半小时左右,不包括配置时间

前言:
    在Linux下编译安装程序是很费精力的一件事情,对很多初学者来说这是一道门槛.我作为一个与Linux打了几年交道的PHP程序员,也没有几次是通过完全编译来安装PHP开发环境的.现在借助于体验64位系统的机会再次来实践一下,同时也做了简要的记录,和大家分享.

说明:
    在这里没有记录详悉的安装和配置的过程,只是记录了configure命令和它的参数,当然,这些参数是保证可以编译通过的.具体的一些安装要求请大家耐心地看软件的文档,或者是软件包里的INSTALL文档.顺便练一下英语阅读能力喔!在这次安装中MySQL采用的是官方的x86_64二进制包,省去了不少麻烦.

注意:
    所有命令都在一行内输入.

MySQL安装:
    去MySQL官方网站上下载编译好的二进制软件包,并解压缩到/usr/local目录,把解压后的文件夹的名字改成mysql5.

Apache配置命令:
$ ./configure --prefix=/usr/local/apache2
        --enable-ssl
        --enable-dav
        --enable-dav-fs
        --enable-cgi
        --enable-so

PHP配置命令:
$ ./configure --prefix=/usr/local/php5
        --with-apxs2=/usr/local/apache2/bin/apxs
        --with-bz2
        --enable-mbstring
        --with-openssl
        --with-mysql=/usr/local/mysql5
        --with-mysqli=/usr/local/mysql5/bin/mysql_config
        --enable-soap
        --enable-wddx
        --with-xmlreader
        --with-xsl
        --with-zlib

Subversion配置命令:
$ ./configure --prefix=/usr/local/subversion --with-apxs=/usr/local/apache2/bin/apxs

mod_cband配置命令:
$ ./configure --with-apxs=/usr/local/apache2/bin/apxs

mod_perl配置命令:
$ perl Makefile.PL
        MP_APXS=/usr/local/apache2/bin/apxs
        MP_APR_CONFIG=/usr/local/apache2/bin/apr-config

小结:
    安装过程很快,得益于现代的高性能的计算机技术,整个开发环境的后期配置是十分复杂的,我安装大概只用了半个多小时,但是确花了整整一天的时间去配置,所以说还是很麻烦的,当然还包括Java,Eclipse以及相关软件的安装.希望大家能不断的实践,取得更快的进步.

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值