Actions

Building Joomla Extensions with Apache Ant

From Joomla! Documentation

Revision as of 05:17, 24 June 2010 by Rvsjoen (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Contents

Environment

The build scripts depend on three environment variables, these values can either be set in the environment, or you can edit common.xml and set them manually

SOURCEDIR

This is the absolute path to the Joomla installation you are testing the extension on

BUILDDIR

This is the path to a temporary directory used to build packages, can be a relative or an absolute path

RELEASEDIR

This is the folder in which to put the packaged extensions when script is invoked with the 'package' target

Build Targets

NOTE: The PREFIX property in the build targets has different meaning depending on the extension type, for plugins it is used to determine the plugin group, and for other types it is used to determine whether the extension is for the site or for the administrator. To make a build target with an admin extension set PREFIX to "administrator"

buildcomponent

The target to build a component takes the component name and prefix, prefix is either empty or "administrator" if we are building a component for the backend
<antcall target="buildcomponent">
  <param name="NAME" value="com_helloworld"/>
  <param name="PREFIX" value=""/>
</antcall>

buildmodule

The target to build a module takes the module name and prefix, prefix is either empty or "administrator" if we are building a module for the backend
<antcall target="buildmodule">
  <param name="NAME" value="module_helloworld"/>
  <param name="PREFIX" value=""/>
</antcall>

buildtemplate

The target to build a template takes the template name and prefix, prefix is either empty or "administrator" if we are building a template for the backend
<antcall target="buildtemplate">
  <param name="NAME" value="helloworld"/>
  <param name="PREFIX" value=""/>
</antcall>

buildplugin

The target to build a plugin takes the template name and prefix, prefix is the plugin group to which the plugin belongs
<antcall target="buildplugin">
  <param name="NAME" value="plg_helloworld"/>
  <param name="PREFIX" value="system"/>
</antcall>

Extension structure

Component

Module

Plugin

Template

Scripts

build.xml

This file is per project or per extension, whatever the user sees fit, it includes the common.xml file and specifies which extensions to build. You can have one build file per extension or you can use one build file to build many extensions. I prefer having one build file for each extension named by the extension, so the build file for a helloworld component would be build_com_helloworld.xml or simply com_helloworld.xml. This is shown in the downloadable test packages.

<?xml version="1.0" encoding="UTF-8"?>
<project name="helloworld" default="all" basedir=".">
       <import file="common.xml"/>
       <target name="all" depends="build,sync,package"/>
       <target name="package">
               <antcall target="_package">
                       <param name="NAME" value="com_helloworld"/>
               </antcall>
       </target>
       <target name="build">
               <antcall target="buildcomponent">
                       <param name="NAME" value="com_helloworld"/>
                       <param name="PREFIX" value=""/>
               </antcall>
       </target>
       <target name="sync">
               <antcall target="_sync">
                       <param name="NAME" value="com_helloworld"/>
               </antcall>
       </target>
</project>


common.xml

This is where the magic happens, this file contains build targets to build any module, plugin, template or component. You should normally not have to modify this file unless you need to manually set the environment variables or change the overall structure of an extension.

<?xml version="1.0" encoding="UTF-8"?>
<project>
       <property environment="env"/>
       <property name="source" value="${env.SOURCEDIR}"/>
       <property name="release" value="${env.RELEASEDIR}"/>
       <property name="builddir" value="${env.BUILDDIR}"/>
       <property name="verbose" value="false"/>

       <tstamp>
               <format property="NOW" pattern="yyyyMMdd"/>
       </tstamp>

       <loadfile property="dist.revision" srcFile="./.svn/entries" failonerror="false">
               <filterchain>
                       <headfilter lines="1" skip="3"/>
                       <deletecharacters chars="\n"/>
               </filterchain>
       </loadfile>

       <property name="version" value="${NOW}"/>
       <condition property="version" value="${NOW}_r${dist.revision}">
               <isset property="dist.revision"/>
       </condition>

       <target name="_clean">
               <delete dir="${builddir}/${NAME}" verbose="${verbose}"/>
       </target>

       <target name="_sync">
               <sync todir="${NAME}" includeemptydirs="true">
                       <fileset dir="${builddir}/${NAME}"/>
                       <preserveintarget>
                               <include name="**/.svn/**"/>
                       </preserveintarget>
               </sync>
       </target>

       <target name="_package">
               <zip destfile="${release}/${NAME}_${version}.zip" basedir="${NAME}" excludes=".svn"/>
       </target>

       <target name="buildplugin" depends="_clean">
               <copy todir="${builddir}/${NAME}" overwrite="true" verbose="${verbose}" failonerror="false">
                       <fileset dir="${source}/plugins/${PREFIX}">
                               <include name="*${NAME}*"/>
                       </fileset>
               </copy>
       </target>
       <target name="buildmodule" depends="_clean">
               <copy todir="${builddir}/${NAME}" overwrite="true" verbose="${verbose}" failonerror="false">
                       <fileset dir="${source}/${PREFIX}/modules/${NAME}"/>
               </copy>
               <copy todir="${builddir}/${NAME}/media" overwrite="true" verbose="${verbose}"  failonerror="false">
                       <fileset dir="${source}/media/${NAME}"/>
               </copy>
               <copy todir="${builddir}/${NAME}/language" overwrite="true" verbose="${verbose}"  failonerror="false" flatten="true">
                       <fileset dir="${source}/${PREFIX}/language">
                               <include name="*/*${NAME}.ini" />
                       </fileset>
               </copy>
       </target>
       <target name="buildtemplate" depends="_clean">
               <copy todir="${builddir}/${NAME}" overwrite="true" verbose="${verbose}" failonerror="false">
                       <fileset dir="${source}/${PREFIX}/templates/${NAME}"/>
               </copy>
       </target>
       <target name="buildcomponent" depends="_clean">
               <mkdir dir="${builddir}/${NAME}/site"/>
               <mkdir dir="${builddir}/${NAME}/admin"/>
               <mkdir dir="${builddir}/${NAME}/admin/sql"/>
               <mkdir dir="${builddir}/${NAME}/media"/>
               <mkdir dir="${builddir}/${NAME}/language"/>
               <mkdir dir="${builddir}/${NAME}/language/admin"/>
               <mkdir dir="${builddir}/${NAME}/language/site"/>
               <copy todir="${builddir}/${NAME}/media" overwrite="true" verbose="${verbose}" failonerror="false">
                       <fileset dir="${source}/media/${NAME}"/>
               </copy>
               <copy todir="${builddir}/${NAME}/admin" overwrite="true" verbose="${verbose}">
                       <fileset dir="${source}/administrator/components/${NAME}"/>
               </copy>
               <copy todir="${builddir}/${NAME}/language/admin" overwrite="true" verbose="${verbose}" flatten="true">
                       <fileset dir="${source}/administrator/language">
                               <exclude name="overrides/*"/>
                               <exclude name="pdf_fonts/*"/>
                               <include name="**/*${NAME}*.ini"/>
                       </fileset>
               </copy>
               <copy todir="${builddir}/${NAME}/site" overwrite="true" verbose="${verbose}">
                       <fileset dir="${source}/components/${NAME}"/>
               </copy>
               <copy todir="${builddir}/${NAME}/language/site" overwrite="true" verbose="${verbose}" flatten="true">
                       <fileset dir="${source}/language">
                               <exclude name="overrides/*"/>
                               <exclude name="pdf_fonts/*"/>
                               <include name="**/*${NAME}*.ini" />
                       </fileset>
               </copy>
               <move file="${builddir}/${NAME}/admin/${NAME}.xml" todir="${builddir}/${NAME}" verbose="${verbose}"/>
               <move file="${builddir}/${NAME}/admin/uninstall.${NAME}.php" todir="${builddir}/${NAME}" verbose="${verbose}" failonerror="false"/>
               <move file="${builddir}/${NAME}/admin/install.${NAME}.php" todir="${builddir}/${NAME}" verbose="${verbose}" failonerror="false"/>
               <move todir="${builddir}/${NAME}/admin/sql" verbose="${verbose}">
                       <fileset dir="${builddir}/${NAME}/admin">
                               <include name="*.sql"/>
                       </fileset>
               </move>
       </target>
</project>