Chapter 3. Running phc

Table of Contents
Compiling executables
Compiling web applications
Writing and Reading XML
Internal Representations
Graphical Output
Including files

Once you have installed phc (see Installation Instructions), run it by typing

phc --help

You should see

phc 0.2.0

Usage: phc [OPTIONS]... [FILES]...

  -h, --help               Print help and exit
      --full-help          Print help, including hidden options, and exit
  -V, --version            Print version and exit

GENERAL OPTIONS:
  -v, --verbose            Verbose output  (default=off)
  -c, --compile            Compile  (default=off)
      --pretty-print       Pretty print input according to the Zend style 
                             guidelines  (default=off)
      --obfuscate          Obfuscate input  (default=off)
      --run=STRING         Run the specified plugin (may be specified multiple 
                             times)
      --r-option=STRING    Pass option to a plugin (specify multiple flags in 
                             the same order as multiple plugins - 1 option only 
                             per plugin)
  -d, --define=STRING      Define ini entry (only affects -c and --include)

INPUT OPTIONS:
      --read-xml=passname  Assume the input is in XML format. Start processing 
                             after the named pass
      --include            Parse included or required files at compile-time  
                             (default=off)

COMPILATION OPTIONS:
  -C, --c-option=STRING    Pass option to the C compile (e.g., -C-g; can be 
                             specified multiple times)
      --extension=NAME     Generate a PHP extension called NAME instead of a 
                             standalone application
  -O, --optimize=STRING    Optimize  (default=`0')
  -o, --output=FILE        Place executable into file FILE
  -e, --execute            Run executable after compiling (implies -c)  
                             (default=off)

PRETTY PRINTING OPTIONS:
      --next-line-curlies  Output the opening curly on the next line instead of 
                             on the same line  (default=off)
      --no-leading-tab     Don't start every line in between  with a 
                             tab  (default=off)
      --tab=STRING         String to use for tabs while unparsing  
                             (default=`	')
      --no-hash-bang       Do not output any #! lines  (default=off)

Now write a very small PHP script, for example

<? echo "Hello world!"; ?>

and save it to helloworld.php. Then run phc:

phc --pretty-print helloworld.php

This should output a pretty-printed version of your PHP script back to standard output:

<?php
   echo "Hello world!";
?>

You can see a list of options controlling the style of pretty printing, using the --full-help option.

Compiling executables

phc can compile either executables or extensions. To compile an executable, phc creates C code, which it compiles and links to the PHP embed SAPI. Since it links to PHP, you have access to all of PHP's large built-in standard library. In order to compile the "hello world" executable from before, run

phc -c helloworld.php -o helloworld

This creates an executable helloworld, which can then be run

./helloworld

If you prefer to run your executable immediately after it compiles, use the -e. phc will compile your program, then immediately execute it. You can also view the C code generated by phc:

phc --generate-c helloworld.php > helloworld.c

One of the advantages of phc is that it can optimize your program. Using the -O flag, you can instruct phc to analyse your source code, and perform simple optimizations. On simple benchmarks, this can increase the speed of your application by 50%. To optimize:

phc -O2 -c helloworld.php -o helloworld

phc generates C code, which is then compiled by gcc. To see the command passed to gcc by phc, use the -v flag.

If you specify the -O flag, phc will also pass the -O flag to gcc, which will optimize your code further. The argument to the -O flag must therefore be usable by gcc, so it must be any of -O0 (default), -O1, -O2, -O3 or -Os. Consult the gcc manual for more details.

It is also possible to pass command-line arguments to gcc through phc, using the -C flag. For example, to disable inlining of the generated code by gcc, using -fno-inline:

phc -c -O2 helloworld.php -o helloworld -C-fno-inline

Compiling web applications

Warning

In order to compile web applications, it is currently necessary to alter your php.ini file, or have access to the root account. We welcome suggetions of a different method which avoids these requirements, especially if they would work in a shared hosting environment.

Warning

This section is experimental. Please report any problems.

We have created the command-line option --web-app, which will in the future automate the process of compiling a web application. Unfortunately, for now, please follow these steps.

We describe how to create and install an extension using the C code generated by phc. While we give an overview of creating extensions, significantly more detail can be found in the Zend Extension Writing Tutorial and in Extending and Embedding PHP.

To begin, create a new directory for the extension. We'll use ext/ in our example. Generate C code from helloworld.php using phc.

phc --generate-c helloworld.php > ext/helloworld.c

Create a new file, ext/config.m4, by copying the following, and changing instances of "helloworld" appropriately:

PHP_ARG_ENABLE(helloworld, whether to enable Hello World support,
[ --enable-helloworld   Enable Hello World support])

if test "$PHP_HELLOWORLD" = "yes"; then
  AC_DEFINE(HAVE_HELLOWORLD, 1, [Whether you have Hello World])
  PHP_NEW_EXTENSION(helloworld, helloworld.c, $ext_shared)
fi

In the previous section, we described using the PHP embed SAPI. If you installed a copy of PHP with --enable-embed enabled, it is important NOT to use that version for the following commands. Instead, you should the same version as your webserver uses. From the ext/ directory, run:

phpize --with-php-config=/usr/bin/php-config
./configure --enable-helloworld

Build and install the extension (if you dont have root, refer instead to Alternatives):

make
sudo make install

In your web folder, replace the existing helloworld.php file contents with the following:

<?php
	dl ("helloworld.so");
	__MAIN__ ();
?>

If the dl() function is not enabled in your php.ini file, enable it:

enable_dl = On;

Accessing helloworld.php should now work.

Alternatives

Instead of setting enable_dl, you can instead load the extension manually in your php.ini file:

extension=helloworld

You can also avoid installing the extension using sudo make install by adding an alternate extension directory:

extensions_dir="/full/path/to/ext"

Writing and Reading XML

phc can output an XML representation of the PHP script. You can use this representation if you want to process PHP scripts using tools in your desired framework, instead of using phc plugins. After processing the XML representation, phc can convert it back into PHP. To generate an XML version of a PHP script, run

./phc --dump-xml=ast helloworld.php > helloworld.xml

When reading the XML back in, all the usual features of phc are again available; in particular, it is possible to read an XML file, and write PHP syntax. To convert the XML file we just generated back to PHP syntax, run

./phc --read-xml=ast --pretty-print helloworld.xml

The generated XML should use the schema http://www.phpcompiler.org/phc-1.0. However, our XML schema is currently broken.

Internal Representations

After parsing, phc converts a PHP script into an Abstract Syntax Tree (AST) (this is further explained in Chapter 3 in The phc Developer's Manual). This is very useful for processing PHP scripts which you wish to convert back into PHP. However, for some tasks, especially program analysis, a simpler form of the PHP script is more suitable. phc offers two other Internal Representations (IRs). The High-level Internal Representation (HIR) simplifies most expressions by assigning them to temporary variables. However, code represented in the HIR is still valid PHP. The Medium-level Internal Representation (MIR) converts HIR statements to simpler components, for example converting control-flow statements like the for-loop, into gotos. To view PHP in any of these forms, use the --dump option:

phc --dump=ast helloworld.php
phc --dump=hir helloworld.php
phc --dump=mir helloworld.php

Nearly all phc options work as well on the HIR and MIR as on the AST. For example, XML can be read and written:

phc --dump-xml=hir | ./myprog | phc --read-xml=hir

Graphical Output

If you have a DOT viewer installed on your system (for example, graphviz), you can view the AST graphically. First, ask phc to output the AST in DOT format:

./phc --dump-dot=ast helloworld.php > helloworld.dot

You can then view the tree (helloworld.dot) using Graphviz. In most Unix/Linux systems, you should be able to do

dotty helloworld.dot

And you should see the tree; it should look similar to the tree shown in figure Figure 3-1.

Figure 3-1. Abstract syntax tree for “Hello world”

Including files

phc has initial support for compile-time processing of PHP's include built-in. Enabling this feature inserts the included statements in the AST in the place of the include statement. Included functions, classes and interfaces become part of the file's top-level scope. In the event that phc is not able to process the include statement (for example, if the file cannot be found), a warning is issued, and the include statement is left in place. To enable this support, run

./phc --include script_with_includes.php

The include support is intended to mimic PHP's include built-in, as far as can be achieved at compile time. phc supports:

phc does not support: