Date: 2004-02-28T21:39:16 Editor: 218.214.49.176 <> Wiki: Ant Wiki Page: NewAntFeaturesInDetail/Import URL: http://wiki.apache.org/ant/NewAntFeaturesInDetail/Import
no comment Change Log: ------------------------------------------------------------------------------ @@ -1,91 +1,91 @@ -[http://ant.apache.org/manual-1.6beta/CoreTasks/import.html the task's manual page] +[http://ant.apache.org/manual/CoreTasks/import.html the task's manual page] <import> lets you import build file snippets much like entity includes did before Ant 1.6, but it also adds some new features on top of this. ---- -<strong><import> vs entity includes</strong> +'''<import> vs entity includes''' - * Files suitable for <import> must be legal Ant build files, i.e. they have to be well-formed XML documents and use <project> as their root element. This means that - unlike the snippets you use in entity includes - the included file can easily be edited and (partly) validated with XML aware tools. + * Files suitable for <import> must be legal Ant build files, i.e. they have to be well-formed XML documents and use <project> as their root element. This means that - unlike the snippets you use in entity includes - the included file can easily be edited and (partly) validated with XML aware tools. - * You can use Ant properties in the file name for the piece to include in <import>. With entity includes you've been limited to static file names and hard-coded (relative) paths. + * You can use Ant properties in the file name for the piece to include in <import>. With entity includes you've been limited to static file names and hard-coded (relative) paths. - * You don't have to worry about the way your XML parser resolves relative file names. + * You don't have to worry about the way your XML parser resolves relative file names. - * Entity includes require a DOCTYPE declaration and thus have their roots in DTD systems. If you have an XML-Schema or Relax-NG gramar for Ant build files, the two are hard to combine. + * Entity includes require a DOCTYPE declaration and thus have their roots in DTD systems. If you have an XML-Schema or Relax-NG gramar for Ant build files, the two are hard to combine. - * You must not use <import> inside a <target> (or <sequential>), while there is no such limitation for entity includes. + * You must not use <import> inside a <target> (or <sequential>), while there is no such limitation for entity includes. ---- -<strong>How does an imported file load a resource relative to itself?</strong> +'''How does an imported file load a resource relative to itself?''' By using the magic <code>ant.file.</code><em>projectname</em> property. -Assume build.xml loads config/common.xml, the latter making use of a collocated properties file config/common.xml. The way <code><import></code> is currently implemented (I argumented against it, but that's beside the point), common.xml cannot simply do a <code><property file="common.properties"/></code> as if it was stand-alone, because the project's 'basedir' will correspond to the top-most importing build file. Ant does on the other hand store the absolute pathname of imported build files in a magic property of the form ant.file.<em>projectname</em>, where <em>projectname</em> is an imported project's name (as defined by the 'name' attribute of the top-level <code><project></code> element, and <em>NOT</em> the imported file name!). You can thus <code><dirname></code> that absolute filename, and use the resulting directory to locate the resource relatively to the imported build file. Here's a full example on Windows: +Assume build.xml loads config/common.xml, the latter making use of a collocated properties file config/common.properties. The way <code><import></code> is currently implemented (I argumented against it, but that's beside the point), common.xml cannot simply do a <code><property file="common.properties"/></code> as if it was stand-alone, because the project's 'basedir' will correspond to the top-most importing build file. Ant does on the other hand store the absolute pathname of imported build files in a magic property of the form ant.file.<em>projectname</em>, where <em>projectname</em> is an imported project's name (as defined by the 'name' attribute of the top-level <code><project></code> element, and <em>NOT</em> the imported file name!). You can thus <code><dirname></code> that absolute filename, and use the resulting directory to locate the resource relatively to the imported build file. Here's a full example on Windows: -{{{ -C:\oss\org_apache\antx\import16> type build.xml -<project name="main" default="build"> -{{{ <import file="config/common.xml" /> }}} - -{{{ <target name="build" depends="common.build"> }}} -{{{ <echo>main-build called.</echo> }}} -{{{ <echo>version = ${version}</echo> }}} -{{{ </target> }}} -</project> - -C:\oss\org_apache\antx\import16> type config\common.xml -<project name="common" default="build"> }}}<strong>{{{ -{{{ <dirname property="mybasedir" file="${ant.file.common}" /> }}} -{{{ <property file="${mybasedir}/common.properties" /> }}} - }}}</strong>{{{ -{{{ <target name="build" depends="compile, test"> }}} -{{{ <echo>common-build called.</echo> }}} -{{{ <echo>version = ${version}</echo> }}} -{{{ </target> }}} - -{{{ <target name="compile"> }}} -{{{ <echo>common-compile called.</echo> }}} -{{{ <echo>version = ${version}</echo> }}} -{{{ </target> }}} - -{{{ <target name="test"> }}} -{{{ <echo>common-test called.</echo> }}} -{{{ <echo>version = ${version}</echo> }}} -{{{ </target> }}} -</project> +{{{ +C:\oss\org_apache\antx\import16> type build.xml +<project name="main" default="build"> + <import file="config/common.xml" /> + + <target name="build" depends="common.build"> + <echo>main-build called.</echo> + <echo>version = ${version}</echo> + </target> +</project> + +C:\oss\org_apache\antx\import16> type config\common.xml +<project name="common" default="build">}}}'''{{{ + <dirname property="mybasedir" file="${ant.file.common}" /> + <property file="${mybasedir}/common.properties" /> +}}}'''{{{ + <target name="build" depends="compile, test"> + <echo>common-build called.</echo> + <echo>version = ${version}</echo> + </target> + + <target name="compile"> + <echo>common-compile called.</echo> + <echo>version = ${version}</echo> + </target> + + <target name="test"> + <echo>common-test called.</echo> + <echo>version = ${version}</echo> + </target> +</project> -C:\oss\org_apache\antx\import16> type config\common.properties +C:\oss\org_apache\antx\import16> type config\common.properties version = 1.0 -C:\oss\org_apache\antx\import16> ant +C:\oss\org_apache\antx\import16> ant Buildfile: build.xml compile: -{{{ ["echo"] common-compile called. }}} -{{{ ["echo"] version = 1.0 }}} + [echo] common-compile called. + [echo] version = 1.0 test: -{{{ ["echo"] common-test called. }}} -{{{ ["echo"] version = 1.0 }}} + [echo] common-test called. + [echo] version = 1.0 common.build: -{{{ ["echo"] common-build called. }}} -{{{ ["echo"] version = 1.0 }}} + [echo] common-build called. + [echo] version = 1.0 build: -{{{ ["echo"] main-build called. }}} -{{{ ["echo"] version = 1.0 }}} + [echo] main-build called. + [echo] version = 1.0 BUILD SUCCESSFUL Total time: 0 seconds - }}} +}}} Since an imported build file <em>projectname</em> is used both in itself (to be able to locate resources relative to itself as demonstrated above) but also potentially in all the files that will import it (to refer to its overriden targets), changing the <em>projectname</em> of an imported build file will almost always break its <em>client</em>s, i.e. those build files that import it. This is a mistake IMHO, and breaks encapsulation (again, I argued against this, but no avail.) One should therefore select those project names carefully, lest one wants to expose itself to quite of bit of refactoring. ---- -<strong>Overriding targets in the imported build file</strong> +'''Overriding targets in the imported build file''' If a target is present in both your main build file and the one that you import, the one from your main file takes precedence. @@ -93,77 +93,77 @@ For example, let's take the simple build file from Ant's manual. Suppose it is called "example.xml". -{{{ +{{{ <project name="MyProject" default="dist" basedir="."> -{{{ <description> }}} -{{{ simple example build file }}} -{{{ </description> }}} -{{{ <!-- set global properties for this build --> }}} -{{{ <property name="src" location="src"/> }}} -{{{ <property name="build" location="build"/> }}} -{{{ <property name="dist" location="dist"/> }}} - -{{{ <target name="init"> }}} -{{{ <!-- Create the time stamp --> }}} -{{{ <tstamp/> }}} -{{{ <!-- Create the build directory structure used by compile --> }}} -{{{ <mkdir dir="${build}"/> }}} -{{{ </target> }}} - -{{{ <target name="compile" depends="init" }}} -{{{ description="compile the source " > }}} -{{{ <!-- Compile the java code from ${src} into ${build} --> }}} -{{{ <javac srcdir="${src}" destdir="${build}"/> }}} -{{{ </target> }}} - -{{{ <target name="dist" depends="compile" }}} -{{{ description="generate the distribution" > }}} -{{{ <!-- Create the distribution directory --> }}} -{{{ <mkdir dir="${dist}/lib"/> }}} - -{{{ <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file --> }}} -{{{ <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/> }}} -{{{ </target> }}} - -{{{ <target name="clean" }}} -{{{ description="clean up" > }}} -{{{ <!-- Delete the ${build} and ${dist} directory trees --> }}} -{{{ <delete dir="${build}"/> }}} -{{{ <delete dir="${dist}"/> }}} -{{{ </target> }}} + <description> + simple example build file + </description> + <!-- set global properties for this build --> + <property name="src" location="src"/> + <property name="build" location="build"/> + <property name="dist" location="dist"/> + + <target name="init"> + <!-- Create the time stamp --> + <tstamp/> + <!-- Create the build directory structure used by compile --> + <mkdir dir="${build}"/> + </target> + + <target name="compile" depends="init" + description="compile the source " > + <!-- Compile the java code from ${src} into ${build} --> + <javac srcdir="${src}" destdir="${build}"/> + </target> + + <target name="dist" depends="compile" + description="generate the distribution" > + <!-- Create the distribution directory --> + <mkdir dir="${dist}/lib"/> + + <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file --> + <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/> + </target> + + <target name="clean" + description="clean up" > + <!-- Delete the ${build} and ${dist} directory trees --> + <delete dir="${build}"/> + <delete dir="${dist}"/> + </target> </project> - }}} +}}} Now, let's assume you also need to "rmic" some classes - a convenient way to do that would be right after the javac task in the compile target. You could do -{{{ +{{{ <project basedir="." default="dist"> -{{{ <import file="example.xml"/> }}} + <import file="example.xml"/> -{{{ <target name="compile" depends="init" }}} -{{{ description="compile the source and rmic some classes" > }}} -{{{ <!-- Compile the java code from ${src} into ${build} --> }}} -{{{ <javac srcdir="${src}" destdir="${build}"/> }}} -{{{ <rmic base="${build}" verify="true"/> }}} -{{{ </target> }}} + <target name="compile" depends="init" + description="compile the source and rmic some classes" > + <!-- Compile the java code from ${src} into ${build} --> + <javac srcdir="${src}" destdir="${build}"/> + <rmic base="${build}" verify="true"/> + </target> </project> - }}} +}}} and your rmic task has been injected. You can even do -{{{ +{{{ <project basedir="." default="dist"> -{{{ <import file="example.xml"/> }}} + <import file="example.xml"/> -{{{ <target name="compile" depends="MyProject.compile" }}} -{{{ description="rmic some classes" > }}} -{{{ <rmic base="${build}" verify="true"/> }}} -{{{ </target> }}} + <target name="compile" depends="MyProject.compile" + description="rmic some classes" > + <rmic base="${build}" verify="true"/> + </target> </project> - }}} +}}} and use your own compile target just to post-process the original compile target. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]