Sunday, July 13, 2014

Compiling PDO_OCI in CentOS / RHEL

Background

Similar to the previous post, my yii-framework based PHP application need to access to oracle database tables. Yii requires PDO_OCI PHP extension in order to access oracle database. I will describe steps that I took to compile PDO_OCI extension from php package source SRPMS. 

Preparation

In CentOS, we need to create /etc/yum.repos.d/source.repo because CentOS doesn't come with one :

[base-SRPMS-6.5]
name=CentOS-$releasever – Base SRPMS
baseurl=http://vault.centos.org/6.5/os/Source
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
priority=1
enabled=1

[updates-SRPMS-6.5]
name=CentOS-$releasever – Base SRPMS
baseurl=http://vault.centos.org/6.5/updates/Source
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
priority=1
enabled=1

We also need yum-utils and rpm-build packages
yum install yum-utils rpm-build

Then, download the source package file with yumdownloader :
[root@essdev ~]# yumdownloader --source php
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirror.smartmedia.net.id
 * extras: mirror.smartmedia.net.id
 * updates: mirror.smartmedia.net.id
base-SRPMS-6.5                                           | 1.9 kB     00:00
base-SRPMS-6.5/primary_db                                | 672 kB     00:03
updates-SRPMS-6.5                                        | 2.9 kB     00:00
updates-SRPMS-6.5/primary_db                             | 104 kB     00:00
php-5.3.3-27.el6_5.src.rpm                               |  10 MB     00:49


I want to use a non-root user to do the compile, prepare the directories :
[esscuti@essdev ~]$ cd ~/src/rpm
[esscuti@essdev rpm]$ mkdir BUILD RPMS SOURCES SPECS SRPMS
[esscuti@essdev rpm]$ mkdir RPMS/{i386,i486,i586,i686,noarch,athlon}

Move or copy the src.rpm to the non root user.
[root@essdev ~]# mv php-5.3.3-27.el6_5.src.rpm  /home/esscuti/

Do a test build

First we should be able to build the unchanged php source code.

Install the src rpm onto the src directories
[esscuti@essdev ~]$ rpm -ivh php-5.3.3-27.el6_5.src.rpm
   1:php                    warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
warning: group mockbuild does not exist - using root
warning: user mockbuild does not exist - using root
...

As red hat said in Bug #206277, the mockbuild warnings are benign, ignore them.

Install build dependencies :
sudo yum-builddep php-5.3.3-27.el6_5.src.rpm
Do the build as the non-root user
[esscuti@essdev ~]$ rpmbuild -ba src/rpm/SPECS/php.spec

Oracle Instant Client Installation

1. We need oracle instant client for the OCI library, I have good experiences with instant client 10.2.0.4. You need to download Instant client 10.2.0.4 basic and sdk from OTN (oracle tech network).
2. Extract the instant client files, move them to /opt/instant_client_10_2 and create symbolic links.
ln -s /opt/instantclient_10_2/libclntsh.so.10.1 /opt/instantclient_10_2/libclntsh.so
ln -s /opt/instantclient_10_2/libocci.so.10.1 /opt/instantclient_10_2/libocci.so
ls -s /opt/instantclient_10_2/lib opt/instantclient_10_2

Rebuild with pdo-oci enabled

Insert --with-pdo-oci=shared clause in  src/rpm/SPECS/php.spec to enable pdo_oci extension :
      --enable-pdo=shared \
      --with-pdo-odbc=shared,unixODBC,%{_prefix} \
      --with-pdo-oci=shared,instantclient,/opt/instantclient_10_2,10.2.0.4 \
      --with-pdo-mysql=shared,%{mysql_config} \
      --with-pdo-pgsql=shared,%{_prefix} \
      --with-pdo-sqlite=shared,%{_prefix} \
      --with-sqlite3=shared,%{_prefix} \

Do the build:
rpmbuild -ba src/rpm/SPECS/php.spec

Copy the extension library to php extension directory :
[root@essdev esscuti]# cp src/rpm/BUILDROOT/php-5.3.3-27.el6.x86_64/usr/lib64/php/modules/pdo_oci.so /usr/lib64/php/modules/

create ini file to call the extension :
[root@essdev esscuti]# cat > /etc/php.d/pdo_oci.ini
extension=pdo_oci.so

Refer the instantclient directory for shared object/libraries 
[root@essdev modules]# cat > /etc/ld.so.conf.d/instantclient.conf
/opt/instantclient_10_2

[root@essdev modules]# ldconfig 
[root@essdev modules]# ldconfig -v

Change selinux label in instantclient files :
[root@essdev instantclient_10_2]# restorecon -Fv *.so
restorecon reset /opt/instantclient_10_2/libclntsh.so context unconfined_u:object_r:admin_home_t:s0->system_u:object_r:lib_t:s0
restorecon reset /opt/instantclient_10_2/libclntsh.so.10.1 context unconfined_u:object_r:lib_t:s0->system_u:object_r:lib_t:s0
restorecon reset /opt/instantclient_10_2/libnnz10.so context unconfined_u:object_r:lib_t:s0->system_u:object_r:lib_t:s0
restorecon reset /opt/instantclient_10_2/libocci.so context unconfined_u:object_r:admin_home_t:s0->system_u:object_r:lib_t:s0
restorecon reset /opt/instantclient_10_2/libocci.so.10.1 context unconfined_u:object_r:lib_t:s0->system_u:object_r:lib_t:s0

Change some other SELinux contexts  :
[root@essdev instantclient_10_2]# chcon -v system_u:object_r:lib_t:s0 /opt/instantclient_10_2
changing security context of `/opt/instantclient_10_2'
[root@essdev instantclient_10_2]# chcon -v system_u:object_r:textrel_shlib_t:s0 libnnz10.so
changing security context of `libnnz10.so'
[root@essdev instantclient_10_2]# chcon -v system_u:object_r:textrel_shlib_t:s0 libclntsh.so.10.1
changing security context of `libclntsh.so.10.1'

Restart apache :
service httpd restart

Check using command line and info.php :
php -r "phpinfo();"
cat > /var/www/html/info.php
<?php phpinfo(); ?>



No comments: