Please note: This article has been translated into Spanish by Maria Ramos: Compilar PHP

Compiling PHP with OCI8/Oracle on Mac OS X Snow Leopard

My motivation for this tutorial was mostly to get Oracle/OCI support compiled into PHP.

Mac OS X comes with Apache and PHP, so why should I go through the hassle of compiling it myself? Well, there are several reasons:

Not all extensions can be built using pecl and phpize.

This tutorial is for Mac OSX 10.6 “Snow Leopard”. For 10.5 “Leopard” see Compiling PHP with OCI8/Oracle, Apache and MySQL on Mac OS X Leopard

Update 2010-07-26

PHP 5.3.3 has been released and it fixes both the iconv and the autoconf Bug. Smooth sailing!

Libs have been updated: Freetype 2.4.1, JPEG v8b, PNG 1.4.3, gettext 0.18.1.1.

Update 2010-04-10

PHP 5.3.2 was released some time ago and compiles against libpng 1.4.x now. Included instructions to set up the dynamic library load path for Apache using launchctl.

Update 2010-02-21

PHP 5.3.1 is out and some Libraries have been updated.

Note

The most significant changes moving from Leopard to Snow Leopard and PHP 5.3: We will use the Apache web server already shipping with Mac OS X and the mysqlnd extension for PHP. Compiling Apache and MySQL is no longer part of the tutorial. All binaries will be compiled as 64bit.

Setup

From here on you will be using the Terminal. In Finder navigate from “Applications” to “Utilities” and start Terminal.

I have to put a disclaimer notice in here. From the Terminal it is easy to delete all kinds of files, like system files or your important data. I can not be held responsible for the outcome when you follow and especially when you do not follow my instructions below.

Basic knowledge

You might have set up a password for your user account. To install software you have to be superuser (root) and you will have to enter your password for that. This is what the sudo command does. It runs the command specified as argument as superuser. It is needed in step 5 below.

The steps to install programs and libraries are as follows:

  1. Downloading the source code

    Downloading from the Terminal is easy with the curl command. You just give it the URL and tell it to save the file instead of displaying it. Example: curl -O ftp://ftp.gnu.org/gnu/gettext/gettext-0.17.tar.gz This will create a file gettext-0.17.tar.gz in the current directory.

  2. Extracting the source code

    All the packages you will download are archived. Usually as .tar.gz or .tar.bz2 files. Unarchiving the files is easy with the tar command. Example: tar xzf gettext-0.17.tar.gz. This will extract the directory structure from that archive in the current directory. in most cases it will create a folder with the same name of the archive file w/o the extension: gettext-0.17 in this case.

  3. Configuring

    Here you can/must set up arguments and (de)activate features of the program to be installed. These are specific to every program. The command used to do this is in most cases ./configure. It will check your system capabilities and set up the program the way you specify.

  4. Compiling & Linking

    make. This is the phase where you just let the computer compile the source code to create the program and relax.

  5. Installing

    This basically just means copying the compiled program and its documentation and library files to the correct places on your system. This has to be done as superuser, hence sudo make install.

Configuring is generally the hard part.

/usr/local

The best way to install custom software is putting it somewhere it won’t disturb the other programs on your system. You do not want to overwrite e.g. the PHP version OS X shipped with (it is located in /usr/bin/php). Other applications/programs might depend on it.

So now go and create /usr/local. Most configure scripts will use /usr/local as prefix if it exists. In Terminal enter the following.

sudo mkdir -p /usr/local

Next we have to tell the computer to actually look for programs in /usr/local (e.g. when you type php in Terminal you want the correct PHP version to run) and to prioritize them to the built-in ones. That means setting the search path. To do this open or create a file called .bash_login in your home directory with the following command.

touch ~/.bash_login
open -a TextEdit ~/.bash_login

Or if you have TextMate installed:

mate ~/.bash_login

If you follow my example throughout the tutorials on where to install the programs you will compile then these are the corrects paths. If you change the path for, say Apache, you might need to adapt it in this file, too. For now paste the line

export PATH="/usr/local/bin:/usr/local/php5/bin:$PATH" 

to the file or alter an existing entry accordingly and save the changes. Now you just need Terminal (actually, the shell) to interpret that file right now:

. ~/.bash_login

When you start a new shell, that is a Terminal window or tab this file will be loaded automatically.

For more in-depth information see Dan Benjamin’s great article: Using /usr/local.

Last preparations

Create a new directory where all the program source code will be downloaded and compiled.

mkdir ~/src
cd ~/src

Compiling

PHP becomes much more useful with some extensions. Extensions depend on certain libraries for functionality. Some of those libraries ship with Mac OS X, some need to be installed/compiled separately. The extensions I need are as follows:

bcmath, bz2, calendar, curl, exif (incl. jpeg*), ftp, gd (incl. freetype*, jpeg*, png*), gettext*, iconv, ldap, libxml, mbstring, mcrypt*, mysql, mysqli, oci8*, openssl, pdo (including the drivers pdo_mysql, pdo_oci, pdo_sqlite), shmop, snmp, soap, wddx, xmlrpc, xsl, zip, zlib, dbase, sysvmsg/sysvsem/sysvshm

* extensions marked require additional libraries to be compiled/installed.

Other, already built-in extensions: ctype, date, dom, fileinfo, filter, hash, json, pcre, phar, posix, Reflection, session, SimpleXML, Sockets, SPL, SQLite, tokenizer, xml, xmlreader, xmlwriter

If the list does not include a certain extension you need, I either did not care enough about it (e.g. I have never used PostgreSQL).

Oracle instant client

Instant Client downloads for Mac OS X (Intel x86)

Download the 64bit version of “Instant Client Package - Basic”, unarchive it to and copy the unarchived directory to e.g. /usr/local/instantclient. Download “Instant Client Package - SDK” (64bit), unarchive it and copy the sdk directory so that it lies within /usr/local/instantclient). Also, you need to issue the following command inside the instantclient directory.

ln -s libclntsh.dylib.10.1 libclntsh.dylib
ln -s libclntsh.dylib libclntsh.so

This will create a less version-specific symbolic link for one of the libraries and is needed by the PHP configure command. The second line will fix a bug in the configure script. PHP searches for a .so file but on Mac OSX those files are called .dylib.

Oracle needs some variables set up before you can call ./configure for PHP:

export NLS_LANG="American_America.UTF8"
export DYLD_LIBRARY_PATH="/usr/local/instantclient"

This should then be set system-wide, or at least in the shell you use to start Apache or PHP cli.

MySQL

PHP 5.3.0 comes with a “MySQL Native Driver” mysqlnd so there is no need to install MySQL client libraries or server on your machine.

For a tutorial on how to compile MySQL server yourself, see Installing MySQL on Mac OS X.

freetype

FreeType Downloads

A Free, High-Quality, and Portable Font Engine. This is needed for GD.

curl -O http://mirrors.zerg.biz/nongnu/freetype/freetype-2.4.1.tar.bz2
tar xjf freetype-2.4.1.tar.bz2
cd freetype-2.4.1/
./configure
make
sudo make install
cd ..

gettext

gettext download

GNU `gettext’ utilities are a set of tools that provides a framework to help other GNU packages produce multi-lingual messages

curl -O ftp://ftp.gnu.org/gnu/gettext/gettext-0.18.1.1.tar.gz
tar xzf gettext-0.18.1.1.tar.gz
cd gettext-0.18.1.1/
./configure
make
sudo make install
cd ..

jpeg

jpeg download

JPEG image compression

curl -O http://www.ijg.org/files/jpegsrc.v8b.tar.gz
tar xzf jpegsrc.v8b.tar.gz
cd jpeg-8b/
./configure --enable-shared
make
sudo make install
cd ..

Note: Some version before v7 might require you to execute these two lines for configure to work:

cp /usr/share/libtool/config.sub .
cp /usr/share/libtool/config.guess .

libpng

libpng download

libpng is the official PNG reference library.

curl -O ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.4.3.tar.gz
tar xzf libpng-1.4.3.tar.gz 
cd libpng-1.4.3/
./configure
make
sudo make install
cd ..

t1lib

Rasterizer library for Adobe Type 1 Fonts.

curl -O ftp://sunsite.unc.edu/pub/linux/libs/graphics/t1lib-5.1.2.tar.gz
tar xzf t1lib-5.1.2.tar.gz
cd t1lib-5.1.2/
./configure
make without_doc
sudo make install
cd ..

mcrypt

mcrypt download

MCrypt is a replacement for the old crypt() package and crypt(1) command, with extensions.

curl -O http://sunet.dl.sourceforge.net/project/mcrypt/Libmcrypt/2.5.8/libmcrypt-2.5.8.tar.bz2
tar xjf libmcrypt-2.5.8.tar.bz2
cd libmcrypt-2.5.8/
./configure
make
sudo make install
cd ..

imap (c-client)

This is kind of nasty. First, you have to compile the IMAP c-client. You can get it here.

curl -O ftp://ftp.cac.washington.edu/mail/imap.tar.Z
tar xZf imap.tar.Z
cd imap-2007e/

For imap-2007e to work you need to patch it first. Edit Makefile, find the rule for oxp and change the line (line 421 for me)

EXTRACFLAGS="$(EXTRACFLAGS) -DMAC_OSX_KLUDGE=1" \

to

EXTRACFLAGS="$(EXTRACFLAGS)" \

This was a workaround for earlier version of MAC OS X and it not needed anymore with 10.6. Then run the following command to compile it.

make oxp

oxp is the identifier for modern Mac OS X systems.

Note: There is no make install! This sucks. So I had a peek at the macports Portfile for cclient. Use the following commands to install c-client manually.

destroot=
prefix=/usr/local
worksrcpath=.
sudo install -m 755 -d ${destroot}${prefix}/include/c-client
cd c-client/
sudo install -m 644 c-client.h dummy.h env.h env_unix.h \
  fdstring.h flockcyg.h flocksim.h flstring.h fs.h ftl.h \
  imap4r1.h linkage.c linkage.h mail.h misc.h netmsg.h \
  newsrc.h nl.h nntp.h osdep.h pseudo.h rfc822.h smtp.h \
  sslio.h tcp.h tcp_unix.h unix.h utf8.h utf8aux.h \
${destroot}${prefix}/include/c-client
cd ..
sudo install -m 644 ${worksrcpath}/c-client/c-client.a \
  ${destroot}${prefix}/lib/libc-client4.a

To update the table of contents of archive libraries you should run the ranlib command. I did it like this.

Note: sudo -s gives a root shell, exit closes it afterwards.

sudo -s
cd /usr/local/lib
ranlib libc-client4.a
exit

PHP

PHP: Get Download

The most important options are the first two ./configure arguments. --prefix says where php will be installed, which is /usr/local/php5 in my case. --with-apxs2 tells the script, where to find Apache. If you changed that when compiling Apache or if you want to compile a php module for a different Apache version then change this argument accordingly. The same goes for the mysql configure options.

curl -O http://de2.php.net/distributions/php-5.3.3.tar.bz2
tar xjf php-5.3.3.tar.bz2
cd php-5.3.3/

My complete ./configure line including mysqlnd and Oracle/OCI8 support (See notes below for PHP < 5.3.3):

./configure \
--prefix=/usr/local/php5 \
--with-apxs2=/usr/sbin/apxs \
--with-bz2=/usr  \
--with-config-file-scan-dir=/usr/local/php5/php.d \
--with-curl \
--with-freetype-dir=/usr/local/php5 \
--with-gd \
--with-gettext \
--with-iconv-dir=/usr \
--with-imap-ssl=/usr/local \
--with-imap=/usr/local \
--with-iodbc=/usr \
--with-jpeg-dir=/usr/local/php5 \
--with-kerberos=/usr \
--with-ldap \
--with-libxml-dir=shared,/usr/local/php5 \
--with-mcrypt \
--with-mhash \
--with-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-oci8=instantclient,/usr/local/instantclient \
--with-pdo-oci=instantclient,/usr/local/instantclient,10.2.0.4 \
--with-openssl=/usr \
--with-png-dir=/usr/local/php5 \
--with-snmp=/usr \
--with-t1lib=/usr/local/php5 \
--with-xmlrpc \
--with-xsl \
--with-zlib-dir=/usr \
--with-zlib=/usr \
--enable-bcmath \
--enable-calendar \
--enable-cgi \
--enable-exif \
--enable-ftp \
--enable-gd-native-ttf \
--enable-mbstring \
--enable-pcntl \
--enable-shmop  \
--enable-soap \
--enable-sockets \
--enable-sqlite-utf8 \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-wddx \
--enable-zip

Now it’s time to finally compile PHP (See notes below for PHP < 5.3.3):

make

To install PHP correctly it is best to open a root shell which keeps your current environment settings, specifically the DYLD_LIBRARY_PATH for Oracle.

sudo -s
make install

Note: PHP versions 5.3.0 - 5.3.2 shipped without complete Mac OS X 10.6 “Snow Leopard” support, so you have to patch the iconv extension before the ./configure script is executed. Edit the file ext/iconv/iconv.c and change the line

#define iconv libiconv

to

#define iconv iconv

This is not the most elegant way, maybe, but the simplest. I filed a bug with the PHP project and hopefully this will be fixed in the next version.

Note: PHP versions 5.3.0 - 5.3.2 brought our old autoconf bug back. Before running make you should edit Makefile and change the line

EXEEXT = .dSYM

to

EXEEXT =

Note: For PHP Version 5.3.0 edit Makefile and add -lresolv to MH_BUNDLE_FLAGS and EXTRA_LIBS. Otherwise the linker will complain about unresolved symbols.

Note: If you are paranoid you should execute make test before make install to make sure PHP works correctly. This will take some time, though. Make sure to configure the tests for database extensions like mysql and oci8, see e.g. ext/oci8/README and ext/mysql/test/connect.inc

Apache setup

The last step is to setup the Apache web server, so PHP loads correctly.

Usually you would edit the file /usr/sbin/envvars and insert the following two lines:

DYLD_LIBRARY_PATH="/usr/lib:/usr/local/instantclient:$DYLD_LIBRARY_PATH"
export DYLD_LIBRARY_PATH

When using the Apple supplied Apache though, you will have to edit the launch control file. Edit /System/Library/LaunchDaemons/org.apache.httpd.plist and add

<key>EnvironmentVariables</key>
<dict>
    <key>DYLD_LIBRARY_PATH</key>
    <string>/usr/lib:/usr/local/instantclient:$DYLD_LIBRARY_PATH</string>
</dict>

to the surrounding dict.

Now restart Apache using

sudo apachectl restart

Finish Line

And you’re done.

Thanks for reading. Feedback is always welcome. You can send me a mail at soryu2@gmail.com.

Credits

Thanks to Dan Benjamin and Marc Liyanage for inspiring me to this tutorial.

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.