Translate ant script that creates a jar file into sbt - ant

I have an ant file called jarPLCExample.xml that takes some class files and produces a jar file. What would the <jar> tag section of this file look like in sbt?
<project name="jar_myplc" default="jar_myplc" basedir=".">
<property file="../resources/v2.properties"/>
<property name="dist.dir" value="C://where_jar_files_go/lib"/>
<property name="dist.file" value="${dist.dir}/PLC.jar"/>
<target name="jar_myplc">
<tstamp>
<format property="TODAY" pattern="dd/MM/yyyy hh:mm aa" locale="au"/>
</tstamp>
<delete file="${dist.file}" quiet="true"/>
<jar destfile="${dist.file}">
<fileset dir="${v2.out.root}" includes="com/companyname/server/applic/**/*.class"/>
<fileset dir="${v2.out.root}" includes="com/companyname/common/utils/SeaDef*.class"/>
</jar>
<copy file="${dist.file}" todir="C:/deploy"/>
</target>
sbt-assembly no good for this as it seems you can exclude and include jars, but not source file packages and source file names as needs to be done here.
Obviously important to 'go with the flow': I expect sbt will want to compile from source, so no need to explicitly use .class files as the ant task above does.
I already have a build.sbt in the base directory, and it would be sensible to call this file jarPLCExample.sbt, but I don't know how to get sbt to load one particular file. So instead I will have two projects in the one file and manually set the current project by changing their order. (As they both have the same key the second one seems to overwrite the first one - the projects command will always show only one project).

This answer has two shortcomings. It only includes the applic directory rather than all directories (recursively) below applic. Also it will pick up all SeaDef*.class, no matter which directories they are in.
def filter3(file: File, greatGrandParent:String, grandParent:String, parent:String, excludes:List[String]):Boolean = {
file.getParentFile.getName == parent &&
file.getParentFile.getParentFile.getName == grandParent &&
file.getParentFile.getParentFile.getParentFile.getName == greatGrandParent &&
!excludes.exists( _ == file.getName)
}
/*
* <fileset dir="${v2.out.root}" includes="com/companyname/server/applic/**/*.class"/>
* <fileset dir="${v2.out.root}" includes="com/companyname/common/utils/SeaDef*.class"/>
*/
lazy val jarPLCExample = project.in(file(".")).
settings(commonSettings: _*).
settings(
includeFilter in (Compile, unmanagedSources) :=
new SimpleFileFilter(file => filter3(file, "companyname", "server", "applic", List())) ||
new SimpleFileFilter(file => file.getName.startsWith("SeaDef"))
)

Related

How can I pass a default value via command line when running ant?

<target name="clone-repo" description="Pull code from SCM repository" depends="resolve">
<taskdef resource="org/eclipse/jgit/ant/ant-tasks.properties" classpathref="build.path"/>
<delete dir="${basedir}/omoc_build"/>
<git-clone uri="https://user:******#github.com/sirect/omoc.git" dest="${basedir}/omoc_build" branch="${branch}" />
<zip destfile="${basedir}/devtoolkit/devtoolkit_docker/config.zip" basedir="${basedir}/omoc_build/config" />
I want to run ant command where by default it should clone from main branch
Few things!
To answer your question, you can set the branch property in a properties file, which would be overwritten if you specify on commandline. Include the property file above your target:
<property file="defaults.properties" description="default configuration."/>
in defaults.properties you'll set branch to main and you could overide it with -Dbranch=non-main-branch
That allows you to set a default.
Now for the advice you didn't ask for:
Don't want ant cloning your source. You should have your build system checkout the source and then ant should build the source. You're creating a chicken and egg problem here... build.xml is in source control, and it's checking out source? That's fishy.

How to exclude empty directories from zipfileset

I have an ant target for creating zip like this -
<zip destfile="${dist}/myzip.zip">
<zipfileset prefix="product/install" includes="docs/resources/**,docs/*.*" excludes="docs/build.bat,docs/*.xml,docs/resources/*.html"/>
</zip>
Now, how do I ensure that empty directories don't get included in this zipfileset.
Eg: docs/resources directory only has html files, all of which I have excluded above. How do I make sure docs/resources folder doesn't get included.
Should I be checking for this manually everytime? or is there an option like includeEmptyDirs="false"?
I think there isn't an option for this in zip task, see documentation.
But what you can do is to make a copy with excludes/includes, and define to exclude the empty directories and then call the zip task on the copied folder:
<copy todir="tmp2" includeEmptyDirs="false">
<fileset dir="tmp1" excludes="**/*.txt"/>
</copy>
<zip>...
Documentation of copy

How to create temporary directory in ant?

I'd like to create a temporary directory in ant (version 1.6.5) and assign it to a property.
The command "mktemp -d" would be ideal for this, but I cannot find similar functionality from inside ant
I can't find any official function in the docs apart from the tempfile task which apparently only creates files, not directories.
I'm considering using exec to call tempfile and get the result, however this will make my build.xml dependent on UNIX/linux, which I'd like to avoid.
Background: I'm trying to speed up an existing build process which builds inside networked filesystem. The build already copies all the source to a temporary directory, however this is on the same filesystem. I've tested changing this to /tmp/foo and it gives a worthwhile speed increase: 3mins vs 4mins.
You could combine the tempfile task with the java.io.tmpdir system property to get a file path to use to create a temporary dir:
<project default="test">
<target name="test">
<echo>${java.io.tmpdir}</echo>
<tempfile property="temp.file" destDir="${java.io.tmpdir}" prefix="build"/>
<echo>${temp.file}</echo>
</target>
</project>
Note that the tempfile task does not create the file (unless you ask it to). It just sets a property which you can use to create a file or dir.
This task sets a property to the name of a temporary file. Unlike
java.io.File.createTempFile, this task does not actually create the
temporary file, but it does guarantee that the file did not exist when
the task was executed.
Output in my environment:
test:
[echo] C:\Users\sudocode\AppData\Local\Temp\
[echo] C:\Users\sudocode\AppData\Local\Temp\build1749402932
The answer above only hints at how to create a temporary directory. The point is that merely returns a string. A more complete answer is
<target name="temptest" description="test making tempdir">
<tempfile property="mytempdir" destdir="${java.io.tmpdir}"/>
<tempfile property="mytempfile" destdir="${mytempdir}"/>
<tstamp>
<format property="now" pattern="MMMM dd yyyy"/>
</tstamp>
<copy tofile="${mytempfile}">
<string value="today=${now}"/>
</copy>
<property file="${mytempfile}"/>
<echo message="It it now ${today}"/>
</target>

Passing a variable into ant

If I pass a variable to ant by doing
ant -Dsomething=blah
How can I refer to it in my build.xml? I tried #something# and ${something} but neither seem to work.
Ultimately what I am trying to do is set some properties (versions) at compile time.
update: the problem of course turned out to be somewhere else - accepting the most complete looking answer with examples
Don't you hate it when you over think these things:
<project name="test">
<echo message="The value of foo is ${foo}"/>
</project>
Now, I'll run my program. Notice that I never defined a value for property foo in my build.xml. Instead, I'll get it from the command line:
$ ant -Dfoo=BAR_BAR_FOO
test:
[echo] The value of foo is BAR_BAR_FOO
BUILD SUCCESSFUL
time: 0 seconds
See. Nothing special at all. You treat properties set on the command line just like normal properties.
Here's where the fun comes in. Notice that I've defined the property foo in my build.xml this time around:
<project name="test">
<property name="foo" value="barfu"/>
<echo message="The value of foo is ${foo}"/>
</project>
Now watch the fun:
$ ant
test:
[echo] The value of foo is barfu
BUILD SUCCESSFUL
time: 0 seconds
Now, we'll set the property foo on the command line:
$ ant -Dfoo=BAR_BAR_FOO
test:
[echo] The value of foo is BAR_BAR_FOO
BUILD SUCCESSFUL
time: 0 seconds
See the command line overrides the value I set in the build.xml file itself. This way, you can have defaults that can be overwritten by the command line parameters.
It sounds like you want to do something like the following:
<mkdir dir="build/src"/>
<copy todir="build/src" overwrite="true">
<fileset dir="src" includes="**/*.java"/>
<filterset>
<filter token="VERSION" value="${version}"/>
</filterset>
</copy>
...which will cause your source to get copied, replacing #VERSION#:
public class a { public static final String VERSION = "#VERSION#"; }
...and then include build/src in your javac src.
That said, I don't recommend this approach since the source copy step is expensive, and it will undoubtedly cause confusion. In the past, I've stored a version.properties file in my package with version=x.y. In my Java code, I used Class.getResourceAsStream("version.properties") and java.util.Properties. In my build.xml, I used <property file="my/pkg/version.properties"/> so that I could create an output-${version}.jar.
${argsOne} works for me and is easily referenced if the invoking command is
ant -DargsOne=cmd_line_argument
Ant documentation also says so. This should work, try running with ant -debug and paste the output.

Delete all files and folders via Ant FTP task

How to delete all files and folders inside specified remote folder in Ant?
I've tried the following:
<ftp server="${ftp.host}" userid="${ftp.user}"
password="${ftp.pass}" remotedir="${ftp.remotedir}" action="del">
<fileset>
<include name="**/*"/>
</fileset>
</ftp>
it deletes all files, but not folders.
(if I write here <include name="*.txt"> instead it works as expected - deletes all txt files, but what if I want to delete all files and folders?)
You should use another command: rmdir.
This command does not remove folder specified in the remotedir parameter.
The sample based on information from ant.apache.org:
<ftp action="rmdir"
server="${ftp.host}"
userid="${ftp.user}"
password="${ftp.pass}"
remotedir="${ftp.parentdir_for_remotedir}" >
<fileset>
<include name="${ftp.remotedir}/**"/>
</fileset>
</ftp>
The quote from site:
The directory specified in the remotedir parameter is never selected
for remove, so if you need to remove it, specify its parent in
remotedir parameter and include it in the pattern, like
"somedir/**".
Also worth noting is that rmdir will fail if there are anything but empty folders in the fileset specified.
From the same site:
As an example suppose you want to delete everything contained into
/somedir, so invoke first the task with action="delete", then
with action="rmdir" ...

Resources