Phing buildfiles are written in XML, and so you will need to know at least some basic things about XML to understand the following chapter. There is a lot of information available on the web:
A valid Phing buildfile has the following basic structure:
The Foobar project installs some PHP files from a source location to a target location, creates an archive of this files and provides an optional clean-up of the build tree:
<?xml version="1.0"?> <project name="FooBar" default="dist" basedir="."> <target name="prepare"> <echo msg="Preparing build..." /> <mkdir dir="./build" /> </target> <target name="build" depends="prepare"> <echo>Building...</echo> <copy file="./src/File.php" to="./build/File.php"/> <copy file="./src/File2.php" to="./build/File2.php"/> </target> <target name="dist" depends="build"> <echo message="Creating archive..." /> <tar outfile="furbee.tar.gz" basedir="./build"/> </target> <target name="clean"> <echo msg="Cleaning up..."/> <delete file="./build"/> </target> </project>
The first element after the document prolog is the root element named <project> on line 3. This element is a container for all other elements and can/must have the following attributes:
Attribute | Meaning | Required |
---|---|---|
name | The name of the project | No |
basedir | The base directory of the project. If none is specified, the current directory is used. | No |
default | The default target that is to be executed if no target(s) are specified when calling this build file. | Yes |
description | The description of the project. | Yes |
A target can depend on other targets. You might have a target for installing the files in the build tree, for example, and a target for creating a distributable tar.gz archive. You can only build a distributable when you have installed the files first, so the distribute target depends on the install target. Phing resolves these dependencies.
It should be noted, however, that Phing's depends attribute only specifies the order in which targets should be executed - it does not affect whether the target that specifies the dependency(s) gets executed if the dependent target(s) did not (need to) run.
Phing tries to execute the targets in the depends attribute in the order they appear (from left to right). Keep in mind that it is possible that a target can get executed earlier when an earlier target depends on it, in this case the dependant is only executed once:
<target name="D" depends="C,B,A" />
Suppose we want to execute target D . From its depends attribute, you might think that first target C , then B and then A is executed. Wrong! C depends on B , and B depends on A , so first A is executed, then B , then C , and finally D .
A target gets executed only once, even when more than one target depends on it (see the previous example).
The optional description attribute can be used to provide a one-line description of this target, which is printed by the -projecthelp command-line option.
You can specify one or more of the following attributes within the target element.
Attribute | Meaning | Required |
---|---|---|
name | The name of the target | Yes |
depends | A comma-seperated list of targets this target depends on. | No |
if | The name of the Property that hast to be set in order for this target to be executed | No |
unless | The name of the Property that must not be set in order for this target to be executed. |
A task is a piece of PHP code that can be executed. This code implements a particular action to perform (i.e. install a file). Therefore it must be defined in the buildfile so that it is actually invoked by Phing.
These references will be resolved before the task is executed.
Tasks have a common structure:
<name attribute1="value1" attribute2="value2" ... />
where name is the name of the task, attributeN is the attribute name, and valueN is the value for this attribute.
There is a set of core tasks (see Appendix B) along with a number of optional tasks. It is also very easy to write your own tasks (see Extending Phing).
Tasks can be assigned an id attribute:
<taskname id="taskID" ... />
By doing this you can refer to specific tasks later on in the code of other tasks.
Properties are essentially variables that can be used in the buildfile. These might be set in the buildfile by calling the PropertyTask, or might be set outside Phing on the command line (properties set on the command always line override the ones in the buildfile). A property has a name and a value only. Properties may be used in the value of task attributes. This is done by placing the property name between " ${ " and " } " in the attribute value. For example, if there is a BC_BUILD_DIR property with the value 'build', then this could be used in an attribute like this: ${BC_BUILD_DIR}/en . This is resolved to build/en.
It should be noted that if you use a property that is not defined via the property task, the system environment table is searched for this name. For example, if you would use the property ${BCHOME} and you did not define this prior in the buildfile or at the command line, Phing uses the environment variable BCHOME if it exists.
Phing provides access to system properties as if they had been defined using a <property> task. For example, ${os.name} expands to the name of the operating system. See Appendix A for a complete list
<?xml version="1.0" ?> <project name="testsite" basedir="." default="main"> <property environment="env"/> <property file="${env.BCHOME}/build.properties"/> <property name="package" value="${phing.project.name}" override="true" /> <property name="builddir" value="${env.BCHOME}/build/testsite" override="true" /> <property name="srcdir" value="${project.basedir}" override="true" /> <!-- Fileset for all files --> <fileset dir="." id="allfiles"> <include name="**"> </fileset> <!-- Main Target --> <target name="main" description="main target"> <copy todir="${builddir}"> <fileset refid="allfiles" /> </copy> </target> <!-- Rebuild --> <target name="rebuild" description="rebuilds this package"> <delete dir="${builddir}" /> <phingcall target="main"/> </target> </project>
This build file first defines some properties with the <property> task call to PropertyTask. Then, it defines a fileset and two targets. Let us have a quick rundown of this build file.
The first five tags within the project tag define properties. They appear in the three ways this tag can occur:
The next noticeable thing in the build file is the <fileset> tag. It defines a fileset, i.e. a set of multiple files. You can include and exclude Files with include and exclude tags within the fileset tag. For more information concerning Filesets (i.e. Patterns) see Appendix C. The fileset is given an id attribute, so it can be referenced later on.
The first task only contains a call to CopyTask via <copy>. The interesting thing is within the copy tag. Here, a fileset task is not written out with nested include or exclude elements, but via the refid, the earlier create Fileset is referenced. This way, you can use a once defined fileset multiple times in your build files.
The only noticeable thing in the second target is the call to PhingTask with the <phingcall> tag (see Appendix B for more information. The task executes a specified target within the same build file. So, the second target removes the build directory and calls main anew so the project is rebuilt.