|
7.2. Executing External ProgramsThe exec task executes a system command or external program. The attributes for this task appear in Table 7-2.
How you execute general code like this varies by operating system, so you can specify the operating system with the os attribute; operating system names are strings like "Linux", "Windows 2000", and so on. When you specify a target operating system, the command or program is only executed when the OS matches one of the operating systems you specify.
You can nest arg elements in the exec task to pass command-line arguments. And you can set the values of environment variables using nested env elements. The attributes of this element appear in Table 7-3.
7.2.1. Handling Return CodesBy default the return code of an exec is ignored. However, if you set failonerror to TRue, then any OS-specific return code that indicates failure means the build will fail. If you start an external program and the program fails to execute, the build halts unless failifexecutionfails is set to false. You can set the resultproperty to the name of a property that will be assigned the return code for testing. Any of these attributes can test if the results of your build functions as they should. Example 7-2 shows how to execute a C++ compiler, cpp.exe, passing it a command line to execute and watching for errors by setting failonerror to TRue, which means the build will quit if there is an error. Example 7-2. Running a JVM (ch07/exec/build.xml)<?xml version="1.0" ?> <project default="main"> <property name="src" location="source" /> <property name="output" location="bin" /> <target name="main" depends="init, compile"> <echo> Building and running.... </echo> </target> <target name="init"> <mkdir dir="${output}" /> </target> <target name="compile"> <exec dir="." executable="/bin/cpp.exe" failonerror="true"> <arg line="-c ${src}/*.cpp ${output}"/> </exec> </target> </project> You can use this task to run any general program. Here's an example that will launch the Internet Explorer in Windows, assuming a default installation of that browser, and open the exec task's documentation page: <?xml version="1.0" ?> <project default="main"> <property name="browser" location= "C:/Program Files/Internet Explorer/iexplore.exe"/> <property name="file" location="${ant.home}/docs/manual/coretasks/exec.html"/> <target name="main"> <exec executable="${browser}" spawn="true"> <arg value="${file}"/> </exec> </target> </project> This example starts emacs on X Window's display 1: <?xml version="1.0" ?> <project default="main"> <target name="main"> <exec executable="/usr/bin/emacs"> <env key="DISPLAY" value=":1.0"/> </exec> </target> </project> 7.2.2. Targeting Operating SystemsThe exec task depends on a specific operating system. If you want your build file to work on multiple platforms, use the os attribute to specify which exec task is intended to run on which platform. In Example 7-3, two platforms are targeted. The build file executes the ls command on Linux, sending the output to ls.txt, and works on Windows via the dir command, sending output to dir.txt. Example 7-3. Targeting operationg systems (ch07/targeting/build.xml)<?xml version="1.0" ?> <project default="main"> <target name="main"> <exec dir="." executable="ls" os="Linux" output="ls.txt" /> <exec dir="." executable="cmd.exe" os="Windows 2000" output="dir.txt"> <arg line="/c dir"/> </exec> </target> </project> Here's what you might see in Linux: -bash-2.05b$ ant Buildfile: build.xml main: BUILD SUCCESSFUL Total time: 0 seconds -bash-2.05b$ cat ls.txt build.xml ls.txt Here's what you might see in Windows: C:\ant\ch07\exec>ant Buildfile: build.xml main: BUILD SUCCESSFUL Total time: 0 seconds C:\ant\ch07\exec>type dir.txt Volume in drive C has no label. Volume Serial Number is 1512-1722 Directory of C:\ant\ch07\exec 06/25/2004 01:06p <DIR> . 06/25/2004 01:06p <DIR> .. 06/25/2004 02:02p 311 build.xml 06/25/2004 02:02p 104 dir.txt 2 File(s) 455 bytes 2 Dir(s) 29,627,777,024 bytes free 7.2.3. Handling TimeoutsYou can limit the amount of time you want to wait for an external program to execute by setting the timeout attribute to a millisecond value. If the timeout is reached and the program hasn't returned, it's killed and the java tasks's return value will be 1. In that case, the build will halt if failonerror is true. Here's an example: <?xml version="1.0" ?> <project default="main"> <target name="main"> <exec dir="." executable="databaseConnect" timeout="100" failonerror="true" /> </target> </project> 7.2.4. Executing Shell CommandsHow about shell and batch scripts? In Unix, executing shell scripts is no problem. Assign the executable attribute the name of the script. In Windows, it's a different story. To execute a batch (.bat) file, execute the command-line processor, cmd.exe, and pass the name of the batch file using an arg nested element and the /c switch: <exec dir="." executable="cmd" os="Windows 2000"> <arg line="/c backup.bat"/> </exec> If you're running a Unix-like shell in Windows, execute the command shell, sh, and use the -c switch, which sends the output to a file: <exec executable="/bin/sh"> <arg value="-c" /> <arg value="run.sh > results" /> </exec> 7.2.5. Checking for External Programs Before Executing ThemWhen you start launching external programs, ensure the desired programs are available before launching them. Example 7-4 shows how you can do that with the available task, where the existence of cc is verified before compiling C code. If cc is found, the build file sets a property named cc.ok, which is checked by the compile target before the compilation is attempted. Example 7-4. Checking for external programs (ch07/checkfirst/build.xml)<?xml version="1.0" ?> <project default="main"> <property name="src" location="source" /> <target name="main" depends="check, compile"> <echo> Compiling.... </echo> </target> <target name="check"> <condition property="cc.ok"> <or> <available file="cc" filepath="/usr" /> <available file="cc" filepath="/usr/bin" /> <available file="cc" filepath="/usr/local/bin" /> </or> </condition> </target> <target name="compile" depends="check" if="cc.ok"> <exec dir="." executable="cc"> <arg line="${src}/Project.cc"/> </exec> </target> </project> |
|