Toolboxcategory cloud |
ViewsPersonal toolsApache Ant IntegrationFrom Seapine Labs(Redirected from Surround SCM and Apache Ant Integration)
[edit] Apache AntAnt is an open-source Java-based build tool. The Ant project is managed by the Apache Software Foundation. [edit] Installing the Ant plug-in
[edit] Supported CommandsSample commands are included in the examples.xml file. The AntHelp.html document provides additional information about the available Surround SCM commands. You can also download the main.html page for more information. [edit] A Simple ExampleThe following is a simple example using Apache Ant 1.6.5 and Surround SCM 5.0.4. The basic workflow of the example is as follows:
[edit] About the Build FileThe build file used in this example was not started from scratch. In the Ant help files, there is a tutorial on how to create a simple batch file to build a Hello Word program. This was the starting point for the build file. It is recommended that this tutorial be read first. This is not a tutorial on how to build the Ant build file, rather, it is an example on how to add Surround SCM tasks to the build file. It is important to note, that also a slightly more sophisticated program is used in this example. [edit] About the Program being BuiltThe program built by the build file is a java program that consists of three classes: 1. MessageRunner - main class. 2. HelloMessage - Has one method (execute) which displays a "Hello there!" message. 3. FinishedMessage - Has one method (execute) which displays a "I am finished!" message. The main class creates an instance of each of the two other classes and invokes its execute method. Following is the code for each class: MessageRunner.java
public class MessageRunner{
/** Creates a new instance of MessageRunner */
public MessageRunner() {
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here and comments
HelloMessage aHelloMessage = new HelloMessage();
aHelloMessage.execute();
FinishMessage aFinishMessage = new FinishMessage();
aFinishMessage.execute();
}
}
HelloMessage.java
public class HelloMessage
{
public void execute()
{
System.out.println("Hello there!");
}
}
FinishMessage.java
public class FinishMessage
{
public void execute()
{
System.out.println("I am finished!");
}
}
Following the tutorial in Ant's documentation, the .java files are saved in a directory called "src" and the .class files will be created in a sibling directory called "classes". The Jar file will created in the parent directory. The same structure is followed in Surround SCM. For this article, a mainline branch called "Ant Example" is created and the "MessageRunner" folder is added. The working directory for the "Ant Example/MessageRunner" repository is set to "D:\MessageRunner\". [edit] Writing the build fileTo recap, the three Surround SCM actions that will be used are: - Get. - Check In. - Branch. The build.xml file, which is the file that Ant uses to build the program, must reside on the parent directory of the "src" and "classes" directory. In this example, the build.xml file resides in the "D:\MessageRunner\" directory. These tasks have to be defined at the top of the file: <taskdef name="sscmget" classname="com.seapine.surroundscm.ant.SSCMGet"/> <taskdef name="sscmcheckin" classname="com.seapine.surroundscm.ant.SSCMCheckin"/> <taskdef name="sscmbranch" classname="com.seapine.surroundscm.ant.SSCMBranch"/> Next, in the target that compiles (target name "compile") the program, we add a task to first get the latest version from Surround SCM.
<sscmget
serverconnect="localhost:4900"
serverlogin="administrator:"
file="/"
branch="Ant Example"
repository="Ant Example/MessageRunner/src"
destdir="D:\MessageRunner\src"
recursive="true"
quiet="false"
writable="false"
overwrite="replace"
force="true"
/>
The next step is to indicate in the task that jars the program which is the main class. To do this, simply add the following to the "jar" target:
<manifest>
<attribute name="Main-Class" value="MessageRunner"/>
</manifest>
This adds it to the manifest file. Since the jar target is the last in the build file, we will also add the check in and branch operations to this target. First, we check in the jar file:
<sscmcheckin
serverconnect="localhost:4900"
serverlogin="administrator"
file="${ant.project.name}.jar"
branch="Ant Example"
repository="Ant Example/MessageRunner"
comment="Check In from Ant"
makewritable="true"
deletelocal="false"
quiet="true"
force="true"
/>
Next, we check in the .class files:
<sscmcheckin
serverconnect="localhost:4900"
serverlogin="administrator"
file="/"
branch="Ant Example"
repository="Ant Example/MessageRunner/classes"
comment="Check In from Ant"
makewritable="true"
deletelocal="false"
quiet="true"
force="true"
/>
Lastly, we want to create a snapshot branch to capture this build for future reference. In order to obtain a unique name for the snapshot branch, we will use the ${DSTAMP} and ${TSTAMP} properties supplied by Ant. They return the current date and time, respectively. To make sure that these properties have been set, we add "<tstamp/>" to the target before the branch operation:
<tstamp/>
<sscmbranch
serverconnect="localhost:4900"
serverlogin="administrator:"
branch="${DSTAMP} - ${TSTAMP} - ${ant.project.name}"
repository="Ant Example/MessageRunner"
parent="Ant Example"
type="snapshot"
comment="Ant Build on ${DSTAMP} at ${TSTAMP}"
/>
The Finsihed File Here is what the final build.xml file looks like:
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="MessageRunner" basedir="." default="jar">
<taskdef name="sscmget" classname="com.seapine.surroundscm.ant.SSCMGet"/>
<taskdef name="sscmcheckin" classname="com.seapine.surroundscm.ant.SSCMCheckin"/>
<taskdef name="sscmbranch" classname="com.seapine.surroundscm.ant.SSCMBranch"/>
<property name="src.dir" value="src"/>
<property name="classes.dir" value="classes"/>
<target name="clean" description="Delete all generated files">
<delete dir="${classes.dir}" failonerror="false"/>
<delete file="${ant.project.name}.jar"/>
</target>
<target name="compile" description="Compiles the Task">
<mkdir dir="${classes.dir}"/>
<sscmget
serverconnect="localhost:4900"
serverlogin="administrator:"
file="/"
branch="Ant Example"
repository="Ant Example/MessageRunner/src"
destdir="D:\MessageRunner\src"
recursive="true"
quiet="false"
writable="false"
overwrite="replace"
force="true"
/>
<javac srcdir="${src.dir}" destdir="${classes.dir}"/>
</target>
<target name="jar" description="JARs the Task" depends="compile">
<jar destfile="${ant.project.name}.jar" basedir="${classes.dir}">
<manifest>
<attribute name="Main-Class" value="MessageRunner"/>
</manifest>
</jar>
<sscmcheckin
serverconnect="localhost:4900"
serverlogin="administrator"
file="${ant.project.name}.jar"
branch="Ant Example"
repository="Ant Example/MessageRunner"
comment="Check In from Ant"
makewritable="true"
deletelocal="false"
quiet="true"
force="true"
/>
<sscmcheckin
serverconnect="localhost:4900"
serverlogin="administrator"
file="/"
branch="Ant Example"
repository="Ant Example/MessageRunner/classes"
comment="Check In from Ant"
makewritable="true"
deletelocal="false"
quiet="true"
force="true"
/>
<tstamp/>
<sscmbranch
serverconnect="localhost:4900"
serverlogin="administrator:"
branch="${DSTAMP} - ${TSTAMP} - ${ant.project.name}"
repository="Ant Example/MessageRunner"
parent="Ant Example"
type="snapshot"
comment="Ant Build on ${DSTAMP} at ${TSTAMP}"
/>
</target>
</project>
[edit] Setting it into MotionNow to run the build, we open a command line terminal window ("Start">"Run", type "cmd" and click "OK"). Since my environment is on a different drive, I switch to the drive by typing "D:" and then hitting my {ENTER} key. Now I am at the "D:\>" prompt. I then change directory to where my build.xml file is located by typing "cd MessageRunner" and then hitting my {ENTER} key. Once my prompt is at the appropriate directory, I call Ant by simply typing "ant" and then hitting my {ENTER} key. Here is the output from the terminal window:
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and Settings\user>d:
D:\>cd messagerunner
D:\MessageRunner>ant
Buildfile: build.xml
compile:
[sscmget] get from Ant Example/MessageRunner/src:
[sscmget] D:\MessageRunner\src\FinishMessage.java
[sscmget] D:\MessageRunner\src\HelloMessage.java
[sscmget] D:\MessageRunner\src\MessageRunner.java
[javac] Compiling 3 source files to D:\MessageRunner\classes
jar:
[jar] Building jar: D:\MessageRunner\MessageRunner.jar
BUILD SUCCESSFUL
Total time: 1 second
D:\MessageRunner>
Now that the jar file has been compiled, we can run the program by using the "java -jar <name of jar file>" command. Here is the output from the terminal window: D:\MessageRunner>java -jar MessageRunner.jar Hello there! I am finished! So the program works, and this it is in a distributable form. Also, if we now go into Surround SCM, we can see that the snapshot branch was also created: [edit] Automating The BuildYou could automate the Ant build based on file actions by using triggers in Surround SCM. The best approach for this is to use changelists. Remember that triggers are mostly file based, therefore we do not want to create a build as many times as there are files that are checked in. A simple trigger can be setup so when you commit a changelist, Surround can run a simple batch file that calls Ant. So the idea is that everytime you commit a changelist, you get a new build. When you call Ant, you have at least two choices in indicating which build.xml file to use. If you simply run the Ant command by itself, Ant will use the build.xml file that exists in the directory where you run the command from. If a file does not exist, it fails. The other option is to pass the "-buildfile" argument. This is handy for triggers, since the trigger won't run from the directory where you have your build.xml file. Sure, you could add commands to switch drives and change directories, but why go through all that trouble? In the example used in this artilce, the trigger would look something like this: Trigger applies to files in branch [Ant Example] and in repository [Ant Example/MessageRunner/src] -- after an event when a changelist is committed -- Run script located at "d:\batch\anttrigger.bat" The contents of the batch file is just one line: ant -buildfile D:\MessageRunner\build.xml That's it! You could further extend this with the workflow. For example, you could also create a trigger so when you check in a file in this repository, it sets the state to "Build Created". If instead of DOS you used a programming language, you could probably also test whether the build was successful or not. And then based on that result, change the state to "Build Failed" or "Build Successful". [edit] Known IssuesThere were some errors encountered while setting this up. Some where Ant errors and some were Surround SCM errors. Please refer to the Ant documentation for any Ant errors. Exceptions Thrown After Get The main issue was with the get that Surround SCM does. In order to fix it, the get was set to "force file retrieval from server", which is done by adding "force=true" to the get task. It is unknown at this time why this must be set. We suspect that if the "force" is not set, Surround SCM throws a message to Ant that it does not expect, causing the exception. This is currently being reviewed. Files Were Not Checked In The very first time that the build was done, the .class and .jar file did not exist, and therefore did not exist in Surround SCM. This caused the check in to fail, since there was no corresponding files in Surround SCM. The solution is to add these files to Surround SCM after the first build. Any subsequent check-in should work. Files Have to be Writable Since you are checking in the .class and .jar files, at some point you may check them in from the Surround SCM GUI and forget to check the box to "make files writable". If you do this, simply do a get and check the box to "make files writable". If you are using DOS,you can also run the following command from the top directory from your terminal window: attrib -r *.* /s The build will fail if the .class or .jar files are read-only. Snapshot Branch is not Created You may get an error message that a branch by that name already exists. This can happen if you run the build twice, one right after the other. The ${TSTAMP} property we use to name the snapshot branch only gives us the hour and minutes, not seconds. So if you run the same build within the same minute, the second build will try to create a second snapshot branch with the same name as the one created by the first build. |
|


