Saturday, 5 January 2013

XHProf on OS-X with PHP 5.4.4


Almost got nervous breakdown - I hate when system dependencies take forever to configure. I literally spent half a year several times fixing system dependencies. If there is Satan - I'm quite sure he is giving bad people library and plugin dependencies. Jesus.


So I wanted a blogpost about code discovery. And then I got so excited I wanted to use XHProf and then my said 'oh hell no'. Here you are the story.

XHProf is hosted by PECL. But

sudo pecl install xhprof

doesn't do anything because it's a beta version. All right let's use the proper channel

sudo pecl install channel://pecl.php.net/xhprof-0.9.2

Nah, it fails too. All righty then, let's go dirty and compile it. Google is very kind to offer you many tutorials - which all failed to me. One of the best is from Lullabot. But - this too - provided me the same error. I downloaded the PHP source with the same version (5.4.10 is the closest available to 5.4.4 - it's ok), got XHProf version 0.9.2, run

phpize
make

And it gave me this:

/bin/sh /private/tmp/pear/temp/pear-build-rootGjn44l/xhprof-0.9.2/libtool --mode=compile cc  -I. -I/private/tmp/pear/temp/xhprof/extension -DPHP_ATOM_INC -I/private/tmp/pear/temp/pear-build-rootGjn44l/xhprof-0.9.2/include -I/private/tmp/pear/temp/pear-build-rootGjn44l/xhprof-0.9.2/main -I/private/tmp/pear/temp/xhprof/extension -I/Applications/MAMP/bin/php/php5.4.4/include/php -I/Applications/MAMP/bin/php/php5.4.4/include/php/main -I/Applications/MAMP/bin/php/php5.4.4/include/php/TSRM -I/Applications/MAMP/bin/php/php5.4.4/include/php/Zend -I/Applications/MAMP/bin/php/php5.4.4/include/php/ext -I/Applications/MAMP/bin/php/php5.4.4/include/php/ext/date/lib  -DHAVE_CONFIG_H  -g -O2   -c /private/tmp/pear/temp/xhprof/extension/xhprof.c -o xhprof.lo
mkdir .libs
 cc -I. -I/private/tmp/pear/temp/xhprof/extension -DPHP_ATOM_INC -I/private/tmp/pear/temp/pear-build-rootGjn44l/xhprof-0.9.2/include -I/private/tmp/pear/temp/pear-build-rootGjn44l/xhprof-0.9.2/main -I/private/tmp/pear/temp/xhprof/extension -I/Applications/MAMP/bin/php/php5.4.4/include/php -I/Applications/MAMP/bin/php/php5.4.4/include/php/main -I/Applications/MAMP/bin/php/php5.4.4/include/php/TSRM -I/Applications/MAMP/bin/php/php5.4.4/include/php/Zend -I/Applications/MAMP/bin/php/php5.4.4/include/php/ext -I/Applications/MAMP/bin/php/php5.4.4/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /private/tmp/pear/temp/xhprof/extension/xhprof.c  -fno-common -DPIC -o .libs/xhprof.o
/private/tmp/pear/temp/xhprof/extension/xhprof.c:635:5: warning: implicit declaration of function 'restore_cpu_affinity' is invalid in C99 [-Wimplicit-function-declaration]
    restore_cpu_affinity(&hp_globals.prev_mask);
    ^
/private/tmp/pear/temp/xhprof/extension/xhprof.c:639:3: warning: implicit declaration of function 'bind_to_cpu' is invalid in C99 [-Wimplicit-function-declaration]
  bind_to_cpu((int) (rand() % hp_globals.cpu_num));
  ^
/private/tmp/pear/temp/xhprof/extension/xhprof.c:898:10: warning: assigning to 'char *' from 'const char *' discards qualifiers [-Wincompatible-pointer-types]
    func = curr_func->common.function_name;
         ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/private/tmp/pear/temp/xhprof/extension/xhprof.c:909:13: warning: assigning to 'char *' from 'const char *' discards qualifiers [-Wincompatible-pointer-types]
        cls = curr_func->common.scope->name;
            ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/private/tmp/pear/temp/xhprof/extension/xhprof.c:911:13: warning: assigning to 'char *' from 'const char *' discards qualifiers [-Wincompatible-pointer-types]
        cls = Z_OBJCE(*data->object)->name;
            ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/private/tmp/pear/temp/xhprof/extension/xhprof.c:930:35: error: no member named 'u' in 'union _znode_op'
      curr_op = data->opline->op2.u.constant.value.lval;
                ~~~~~~~~~~~~~~~~~ ^
/private/tmp/pear/temp/xhprof/extension/xhprof.c:963:41: warning: passing 'const char *' to parameter of type 'char *' discards qualifiers [-Wincompatible-pointer-types]
        filename = hp_get_base_filename((curr_func->op_array).filename);
                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/private/tmp/pear/temp/xhprof/extension/xhprof.c:856:41: note: passing argument to parameter 'filename' here
static char *hp_get_base_filename(char *filename) {
                                        ^
/private/tmp/pear/temp/xhprof/extension/xhprof.c:1206:7: warning: implicit declaration of function 'thread_policy_set' is invalid in C99 [-Wimplicit-function-declaration]
  if (SET_AFFINITY(0, sizeof(cpu_set_t), &new_mask) < 0) {
      ^
/private/tmp/pear/temp/xhprof/extension/xhprof.c:60:9: note: expanded from macro 'SET_AFFINITY'
        thread_policy_set(mach_thread_self(), THREAD_AFFINITY_POLICY, mask, \
        ^
/private/tmp/pear/temp/xhprof/extension/xhprof.c:1650:44: error: no member named 'u' in 'union _znode_op'
                       EX_T(opline->result.u.var).var.ptr,
                       ~~~~~~~~~~~~~~~~~~~~^~~~~~
/private/tmp/pear/temp/xhprof/extension/xhprof.c:1624:60: note: expanded from macro 'EX_T'
#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
                                                           ^
/private/tmp/pear/temp/xhprof/extension/xhprof.c:1683:35: warning: passing 'const char *' to parameter of type 'char *' discards qualifiers [-Wincompatible-pointer-types]
  filename = hp_get_base_filename(file_handle->filename);
                                  ^~~~~~~~~~~~~~~~~~~~~
/private/tmp/pear/temp/xhprof/extension/xhprof.c:856:41: note: passing argument to parameter 'filename' here
static char *hp_get_base_filename(char *filename) {
                                        ^
8 warnings and 2 errors generated.
make: *** [xhprof.lo] Error 1
ERROR: `make' failed

Don't panic. (I did, btw.) So what do you do? Blame GCC? Blame the environment? Blame Apple? I was looking for the error messages - here and there I've found some ideas but nothing particular. They said it's not gonna work with PHP 5.4.4. I was thinking in alternatives, such as Brew or an already compiled version. But you know well you're hurt already.

So I was wondering how could I set GCC to co-op with XHProf. I was looking for compile arguments and edited the Makefile - and how funny it worked :D Well, I set a stage preprocessor that went through 'make' just fine - but of course it was a preprocessor. Anyways - no help there neither.

Then I realized I always miss something. The error message. If you look at the problem you can actually see the problem:

/private/tmp/pear/temp/xhprof/extension/xhprof.c:930:35: error: no member named 'u' in 'union _znode_op'
      curr_op = data->opline->op2.u.constant.value.lval;

Then a more targeted search and found it: http://lists.freebsd.org/pipermail/freebsd-ports-bugs/2012-May/234478.html the patch! Actually you need to change only two things. From this:

curr_op = data->opline->extended_value;

to this:

curr_op = data->opline->op2.u.constant.value.lval;

And from this:

temp_variable *retvar = &EX_T(opline->result.var);
 ((zend_internal_function *) EX(function_state).function)->handler(
 opline->extended_value,
 retvar->var.ptr,
 (EX(function_state).function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ?
 &retvar->var.ptr:NULL,
 EX(object), ret TSRMLS_CC);

to this:

((zend_internal_function *) EX(function_state).function)->handler(
 opline->extended_value,
 EX_T(opline->result.u.var).var.ptr,
 EX(function_state).function->common.return_reference ?
 &EX_T(opline->result.u.var).var.ptr:NULL,
 EX(object), ret TSRMLS_CC);

Then you have to force remake:

make -B

And fuck yeah:



Parents are always right, you never get anything for free. Except dependencies.

---

I'm wondering, what was the longest time you hassled setting up a dependency?

Peter

2 comments:

  1. If you found this via esoteric Google searches like me, there's an easier way to do this. xhprof was patched to work fine with php5.4, but that code has not made it into PECL yet.

    Instead of patching xhprof.c, try this:

    git checkout https://github.com/facebook/xhprof
    cd xhprof/extension
    phpize
    ./configure
    make
    make install

    Works :)

    ReplyDelete
  2. Hi there, thank you very much. I'll keep it mind. I was hoping they manage to have a new release with a fix - but if it's already there in the FB repo it's the same good. Thank you very much for pointing that out :)

    ReplyDelete