PH(im)P my Zone

31Jan08

Righto, more from the wonderful world of Solaris Zones.

So there I am, attempting to compile enough packages for my development Zone to be called decent.. package after package of wget‘ing, ./configure‘ing, make and make install‘ing.. mainly because I want a custom compile of PHP with a little more features than what we were provided with.

Some tips I’ve learnt from today:

  • The FreeType package really, really wants to be compiled with GNU make.
    • This had me puzzled for quite a while, giving me error messages like that below:
    • ruiwen@zonebox:/usr/local/src/freetype-2.3.5$ ./configure
      GNU make (>= 3.79.1) or makepp (>= 1.19) is required to build FreeType2.
      Please try
      `GNUMAKE= ./configure'.
      or >&2
      `GNUMAKE="makepp --norc-substitution" ./configure'.
    • Until I discovered that GNU make could sometimes be installed on Solaris systems as gmake
    • Running $ GNUMAKE=gmake ./configure worked
  • –with-readline is a very important option to include in your ./configure string if you don’t want to end up tearing your hair out trying to debug your PHP code later on. CLI FTW!
  • –with-readline also seemingly got rid of the error message below:
    • Undefined first referenced
      symbol in file
      mysql_set_character_set ext/mysql/php_mysql.o
      ld: fatal: Symbol referencing errors. No output written to sapi/cli/php
      collect2: ld returned 1 exit status
      gmake: *** [sapi/cli/php] Error 1
    • Thanks to this link
  • A compile of PHP takes quite a long time, so I’ve learnt to keep my coffee handy.

And now, the puzzler of the day.

So. I’ve built up my killer ./configure string, make sure all the libraries were right.. hit Enter.. and…

...
blah blah blah
...
Configuring extensions
checking whether to enable LIBXML support... yes
checking libxml2 install dir... /opt/libxml2
checking for xml2-config path... /opt/libxml2/bin/xml2-config
checking whether libxml build works... yes
checking for OpenSSL support... yes
checking for Kerberos support... no
checking for DSA_get_default_method in -lssl... no
checking for pkg-config... /usr/bin/pkg-config
configure: error: Cannot find OpenSSL's <evp.h>

Hm. Ok. Missing file eh?

Ooh.. but what’s this here?

ruiwen@zonebox:~$ ls -l /usr/sfw/include/openssl/evp.h
-rw-r--r-- 1 root bin 31450 Jan 22 2005 /usr/sfw/include/openssl/evp.h
ruiwen@zonebox:~$

The file’s there, but it’s like it’s invisible or something. (No period in front of the filename though. And no funky permissions either.) So why is my compile failing at this step?

Here’s my ./configure string for those who want a look-see

root@zonebox:/usr/local/src/php-5.2.5# ./configure --prefix=/usr/local/ --with-config-file-path=/usr/local/apache/conf/ --with-apxs2=/opt/apache/bin/apxs --with-libxml-dir=/opt/libxml2 --with-mysql=/opt/mysql --with-gd --enable-gd-native-ttf --with-pear --enable-soap --enable-mbstring --with-mcrypt --with-png-dir=/usr/include/png --enable-exif --enable-calendar --enable-bcmath --with-freetype-dir=/usr/local/ --with-curl=/usr/local/ --with-curlwrappers --with-mysqli --enable-embedded-mysqli; gmake

Any thoughts anyone?

[Updates]

Further along, I got the error below. Something about a MySQL library version not being right.

...
checking for MySQL support... yes
checking for specified location of the MySQL UNIX socket... no
checking for MySQL UNIX socket location... no
checking for mysql_close in -lmysqlclient... yes
checking for MySQLi support... yes
checking whether to enable embedded MySQLi support... no
checking for mysql_set_server_option in -lmysqlclient... no
configure: error: wrong mysql library version or lib not found. Check config.log for more information.
gmake: *** No targets specified and no makefile found. Stop.

Turns out it was my fault for not reading the –help section of ./configure properly. There it clearly states

--with-mysqli[=FILE] Include MySQLi support. FILE is the optional pathname
to mysql_config [mysql_config]

And since the MySQL libraries on the Zone were located at /opt/mysql instead of the usual /usr or /usr/local, all I needed to do was to specify the location of mysql_config, like so:

… –with-mysqli=/opt/mysql/bin/mysql_config

.. and it’s building happily now.

[Update 2]

.. aaannndd…. it failed. Like the village idiot at college it failed.

So what should I do? I know. It’s failing at MySQL right? Maybe the administrators gave me a bum install.

I’ll compile my own!

One more cha-cha with the wget, gunzip, tar -xvf trio, and I was set to go. Cue ./configure!

And get hit with this:

cannot compute sizeof (char), 77

Solving this took me about 2 days.. until I found this forum thread. And the reply gave me the clue I needed to carry on.

So, I’m guessing that it can
find the lbi to link, but not to run. (run path problem). As a note:

-W1,-rpath=/usr/local/lib

Should likely be:

-Wl,-rpath=/usr/local/lib

Turns out, ./configure was looking for it’s dependent files in the wrong place. Adding the LDFLAG options below in front of the ./configure string helped it find the header files it needed.

LDFLAGS="-L/usr/lib -I/usr/include"

So that worked. I managed to successfully build and install MySQL (5.0.41).

However, pointing PHP to that installation instead of /opt/mysql, results in this error near the end of the build

Undefined first referenced
symbol in file
mysql_stmt_param_count ext/mysqli/.libs/mysqli_api.o
mysql_set_character_set ext/mysql/.libs/php_mysql.o
mysql_stmt_send_long_data ext/mysqli/.libs/mysqli_api.o
mysql_stmt_data_seek ext/mysqli/.libs/mysqli_api.o
mysql_stmt_insert_id ext/mysqli/.libs/mysqli_api.o
mysql_stmt_store_result ext/mysqli/.libs/mysqli_api.o
mysql_stmt_reset ext/mysqli/.libs/mysqli_api.o
mysql_stmt_close ext/mysqli/.libs/mysqli.o
mysql_stmt_fetch ext/mysqli/.libs/mysqli_api.o
mysql_stmt_error ext/mysqli/.libs/mysqli_api.o
mysql_stmt_errno ext/mysqli/.libs/mysqli_api.o
mysql_commit ext/mysqli/.libs/mysqli_api.o
mysql_get_server_version ext/mysqli/.libs/mysqli_api.o
mysql_stmt_attr_set ext/mysqli/.libs/mysqli_api.o
mysql_stmt_attr_get ext/mysqli/.libs/mysqli_api.o
mysql_next_result ext/mysqli/.libs/mysqli_api.o
mysql_stmt_free_result ext/mysqli/.libs/mysqli_api.o
mysql_stmt_bind_result ext/mysqli/.libs/mysqli_api.o
mysql_stmt_num_rows ext/mysqli/.libs/mysqli_api.o
mysql_warning_count ext/mysqli/.libs/mysqli_api.o
mysql_stmt_prepare ext/mysqli/.libs/mysqli.o
mysql_rollback ext/mysqli/.libs/mysqli_api.o
mysql_stmt_bind_param ext/mysqli/.libs/mysqli_api.o
mysql_sqlstate ext/mysqli/.libs/mysqli_api.o
mysql_stmt_sqlstate ext/mysqli/.libs/mysqli_api.o
mysql_get_character_set_info ext/mysqli/.libs/mysqli_nonapi.o
mysql_more_results ext/mysqli/.libs/mysqli_api.o
mysql_stmt_field_count ext/mysqli/.libs/mysqli_api.o
mysql_stmt_execute ext/mysqli/.libs/mysqli_api.o
mysql_stmt_affected_rows ext/mysqli/.libs/mysqli_api.o
mysql_stmt_result_metadata ext/mysqli/.libs/mysqli_api.o
mysql_autocommit ext/mysqli/.libs/mysqli_api.o
mysql_stmt_init ext/mysqli/.libs/mysqli.o
mysql_set_local_infile_handler ext/mysqli/.libs/mysqli.o
mysql_set_server_option ext/mysqli/.libs/mysqli_api.o
ld: fatal: Symbol referencing errors. No output written to sapi/cli/php
collect2: ld returned 1 exit status
gmake: *** [sapi/cli/php] Error 1

Any clues? Nothing I’m trying seems to work.

[Update 3]

Good stuff. Looks like the build completed.

Apparently the issue was with using the MySQL libraries as shared (or something like that. I’m not exactly sure of the cause of this. But if you know please drop a comment!).

Checked out this bug report on PHP.

There were a few pointers that I took from this page.

The first was by a ‘rjanson’ who posted at 5 Oct 2004 11:33pm UTC

OK, finally an answer!

I checked Makefile and found the following line:

EXTRA_LIBS = -lcrypt -lcrypt -lmysqlclient -lpng -lz -lz -lresolv -lm
-ldl -lnsl -lxml2 –
lz -lm -lxml2 -lz -lm -lmysqlclient -lcrypt -lnsl -lm -lz -lnss_files
-lnss_dns -lresolv -lnss_files
-lnss_dns -lresolv -lxml2 -lz -lm -lcrypt -lxml2 -lz -lm -lcrypt

By removing one of the -lmysqlclient entries on this line I was able to
successfully make and make install with both mysql and mysqli. As
confirmed by phpInfo().

I’m not sure why the other libs have multiple entries and don’t cause
make to crash.

So I tried that. Didn’t work though.

Tearing my hair out again after another unsuccessful build (one build/fail cycle takes close to an hour, easy), I re-read the comments on the bug, to find this comment from francis, who posted on [2 Jun 2006 4:22pm UTC].

I had the same problem, but I solve it with this options:

./configure \
–with-mysql=shared,/path/to/mysql_config \
–with-mysqli=shared,/path/to/mysql_config

specifying “shared” tag, make and make install finish good. You must
take care, you get 2 modules mysql.so and mysqli.so that you must
include in your php.ini with extension=mysql.so and extension=mysqli.so

(Emphasis mine)

So I followed the tip and added the shared, option in front of the mysql paths.

And the build just completed.

Just a comment on the side though. From rjanson‘s to francis‘ post, there were a little less than 2 years in between. PHP devs! Hellloooooo… What’s happening there? 2 years and a bug is still in existence? If I hadn’t found that bug report I could still be spending my time in compile limbo! Please, please, please fix it?

[ Updates 4]

Oh and before I forget.. I followed another tip to get PHP to build too.

Look here.

Near the bottom of the “Configure and Compiling” section, there’s a bit that says

If you add in mysql, you may need to do

# (cd /opt/sfw/mysql/lib/mysql ; ln -s . .libs)

because libtool is a stupid broken linux-specific piece of $H!7.
Happily, if you have /opt/sfw/mysql/lib/mysql in LD_RUN_PATH, you can remove /opt/sfw/mysql/lib/mysql/.libs after the compile, and you’ll be just fine.

I did that too, symlinking (on my system) /usr/local/mysql/lib/mysql to a hidden directory .libs within itself. Boy! Talk about jumping through hoops!

[Updates 5]

Never thought I’d need so many update sections.. but here goes anyway.

Now after getting PHP to build properly, you’ll need to install it.

The problem in this case was that to compile the PHP-Apache module, you need to call Apaches apxs to build it. apxs is a handy little utility that makes it easy to build Apache extension modules. There’s more on the apxs man page, but essentially apxs provides critical information about the current Apache installation that the extension modules are to be built for. Handy stuff, like the various installation directories. See where I’m headed?

In the usual case, using apxs (–with-apxs2=/path/to/apxs) to build the PHP-Apache module works fine, especially if you are root. In this case however, even through I was root within my own Zone, there was a larger root in the Global Zone. And this larger root happened to install apache under /opt, and mount it read-only. So now, building the PHP-Apache module with /opt/apache/bin/apxs, meant that the module would want to be installed with the rest of the apache installation at /opt/apache. And I couldn’t complete the install because I couldn’t write to anything under /opt.

After being warned not to meddle with apxs on #apache on irc.freenode.net (“hack the build file. remove the -i option from the apxs call. but don’t touch apxs”, the dude on the channel said), I went to do just that. I mean, seriously. Do you really want to trawl through an 11,000-line odd configure script to change every occurrence of apxs? If there was a chance of solving this problem at the cause I was willing to take my chances.

Anyways, looking through apxs, I noticed these lines:

my $installbuilddir = "/usr/local/apache/build";
get_config_vars("$installbuilddir/config_vars.mk",\%config_vars);

Great! apxs was actually getting its configuration information from config_vars.mk under /usr/local/apache/build! I could write to that.

Opening config_var.mk showed:

OS = unix
SHLIBPATH_VAR = LD_LIBRARY_PATH
AP_BUILD_SRCLIB_DIRS = apr apr-util pcre
AP_CLEAN_SRCLIB_DIRS = apr-util apr pcre
bindir = ${exec_prefix}/bin
sbindir = ${exec_prefix}/bin
cgidir = ${datadir}/cgi-bin
logfiledir = ${localstatedir}/logs
exec_prefix = /opt/apache
datadir = ${prefix}
localstatedir = ${prefix}
mandir = ${exec_prefix}/man
libdir = ${exec_prefix}/lib
libexecdir = /opt/apache/modules
htdocsdir = ${datadir}/htdocs
manualdir = ${exec_prefix}/manual
includedir = ${exec_prefix}/include
errordir = ${datadir}/error
iconsdir = ${datadir}/icons
sysconfdir = ${prefix}/conf
installbuilddir = ${datadir}/build

(Emphasis mine)

Remember I said apxs provided critical information about the apache build? Well here’s where it drew its information from.

Now that I knew where the information was stored, fixing it was simple. Simply editing the file to read

libexecdir = /usr/local/apache/modules

instead of

libexecdir = /opt/apache/modules

allowed PHP to install the newly built PHP-Apache module into the writable /usr/local/apache/modules instead of the read-only /opt/apache/modules.

Advertisements


5 Responses to “PH(im)P my Zone”

  1. you do know that wee yeh is the global admin right??

  2. oh yah… welcome to the world of solaris, where slackware feels easier…

  3. 3 Ruiwen

    Yeah I know he’s the admin.. and then? Heh it’s so much more fun to work these problems out on your own don’t you think?

    And yes. Slackware is tons easier, thanks to the loads of libraries that come preinstalled.

    Well.. actually both are pretty much the same.. so long as root is really ‘root’ and none of your filesystems are mounted read-only, you can pretty much compile your way through to your dream system (eh, Gentoo user?),

  4. 4 Joar

    a bit late commenting this one ! But I’ve come back to this post several times during the last couple days because I stumbled into the error as you mention in top of this post.
    “Undefined first referenced
    symbol in file
    mysql_set_character_set ext/mysql/php_mysql.o
    ld: fatal: Symbol referencing errors. No output written to sapi/cli/php
    collect2: ld returned 1 exit status
    gmake: *** [sapi/cli/php] Error 1″

    I’m building on Solaris 10, i386, and I’m in a Zone. I’ve had the same problem with both php-5.2.11 as wel as with 5.3.1 and 5.3.2 .
    On my box readline didn’t do the trick. It turned out to be /usr/sfw held libs for mysql4 but I was trying to build up against mysql5 under /usr/local/mysql .
    Using LD_FLAGS=”-L/usr/local/mysql:/usr/local/mysql/lib/mysql/:/usr/local:/usr/local/lib -R/usr/local/mysql:/usr/local/mysql/lib/mysql:/usr/local:/usr/local/lib” ./configure
    still put /usr/sfw before /usr/local/mysql in files such as Makefile and scripts/php-config . I had to manually grep out everything regarding /usr/sfw from all files after configure and make sure /usr/local/mysql was put in front of /usr/sfw and it finally built !

    Anyway, thanks for your thorough post, and I’m adding my experience as a comment for any future frustrated nerds having similar problems :p

  5. Hello friends, how is all, and what you wish for to
    say on the topic of this piece of writing, in my view its truly awesome
    designed for me.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: