Multiple configuration files for the ProGuard Ant task - ant

I am using the ProGuard ant task, and everything is great, except that my ProGuard configuration file is huge. Also, different tasks use different ProGuard configuration files, and there is a lot of copy-pasting that I would like to refactor into separate .pro files.
<taskdef resource="proguard/ant/task.properties" classpath="C:/Program Files/proguard4.7/lib/proguard.jar"/>
<target name="obfuscated_jar" depends="raw_jar">
<proguard configuration="core.pro lib1.pro lib2.pro">
<outjar path="prog_obfuscated.jar"/>
</proguard>
</target>
The above doesn't work, because it treats the multiple .pro files as one big filename. I'm a known idiot w.r.t. ant, am I missing something obvious? Thanks!

You can create a single main .pro file that contains -include options pointing to your actual .pro files.

This answer isn't great, but it works...
<taskdef resource="proguard/ant/task.properties" classpath="C:/Program Files/proguard4.7/lib/proguard.jar"/>
<target name="obfuscated_jar" depends="raw_jar">
<concat destfile="proguard_temp.pro">
<filelist dir="." files="core.pro,lib1.pro,lib2.pro"/>
</concat>
<proguard configuration="proguard_temp.pro">
<outjar path="prog_obfuscated.jar"/>
</proguard>
<delete file="proguard_temp.pro"/>
</target>

Looks like only one file allowed in configuration attribute.
Edited
And attributes allowed only on <proguard> element. I have another possible solution. Try to concatenate your config-files into one with Ant concat-task and pass this temporary file to <proguard configuration=""> attribute.
Also, it's possible to modify ProGuardTask-class to accept several files as arguments and concatenate them later. And same result could be achieved with Ant macrodef .

Related

How do you extract from a binary file created with Ant <concat>?

I have a binary file that was created with the Ant <concat> task:
<target name="bun.create">
<concat destfile="final.bun" binary="yes">
<filelist dir="scripts/" files="script.sh"/>
<filelist dir="working/" files="files.tgz"/>
</concat>
<chmod file="final.bun" perm="+x"/>
</target>
I have the final.bun file and am wondering how I can extract the script.sh and files.tgz from it, without executing it? I know the unzip command doesn't work.
I don't think there's any way to do this - at least not easily. I'm sure there are some old Unis heads who can use the dd utility to do this, but that is still a hack. What you have done is create a file format that doesn't really exist. It's like concating together a Word document with an Excel document.
In fact, I'm not even sure if the <concat> task wouldn't shred the binary file into an incomprehensible mess as it was trying to concatenate it.
If you must put both files together, use the <zip/>, or <tar/> task to combine both files together. Yes, I know that files.tgz is already a compressed archive, but this would be the best way to put those two files together.

Ant exclude file based on it's content

Is there any way to exclude files from an ant fileset based on the file content?
We do have test servers where code files are mixed up with files that have been generated by a CMS.
Usually, the files are placed in different folders, but there is a risk that real code files are in the middle of generated code.
The only way to differentiate generated files is to open the files and look at it's content. If the file contains a keyword, it should be excluded.
Does anyone know a way to perform this with Ant?
From the answer provided by Preet Sangha, Ishould use a filterchain. However, I'm missing a step here.
Let's say I load a text file of exclusions to be performed:
<loadfile property="exclusions" srcFile="exclusions.txt" />
But I don't know how to integrate it into my current copy task:
<copy todir="${test.dir}">
<fileset dir="${src.dir}">
</fileset>
</copy>
I tried to add the following exclude to the fileset but it does not do anything:
<exclude name="${exclusions}"/>
I'm sure I'm missing a simple step...
Have a look at the not and contains selectors.
The not selector contains an example of pretty much exactly what you're trying to do.
<copy todir="${test.dir}">
<fileset dir="${src.dir}">
<not>
<contains text="your-keyword-here"/>
</not>
</fileset>
</copy>
There's also the containsregexp selector which might be useful if your criteria for exclusion is more complicated.
There's a load more selectors you can use to refine your selection if needed.
I don't know ant but reading the docs....
Can you build a files list using a filterchain, and put this into the excludefiles of a fileset?
or
perhaps create a fileset with a filterchain that uses a filterreader and linecontainsregexp

Ant: Create directory containing file if it doesn't already exist?

Basically, I get a path like "C:\test\subfolder1\subfolder2\subfolder3\myfile.txt", but it's possible that subfolders 1-3 don't exist already, which means I'd get an exception if I try to write to the file.
Is there a way to create the directory structure the target file is in, either by using some task that creates the structure when it outputs to the file and then deleting the file, or by parsing the directory part of the path and using the mkdir task first?
Ant will create the full tree of directories for you when you use the <mkdir> task. So you just need to use the <dirname> task to get the directory name from the file name.
<dirname property="directoryProperty" file="${filePathProperty}"/>
<mkdir dir="${directoryProperty}" />
The first line extracts the directory portion of your file path and stores it in the directoryProperty property. The second line creates the directory (and any parent directories that don't exist).
This task works well
<mkdir dir="${file}/../"/>
Sometimes we could have an alternate choice, using touch task
<touch file="${file}" mkdirs="true" verbose="true"/>
This task should do the job but would have a side effect to create the file with zero size
Just make failonerror=false to avoid the error to stop the whole logic.
<delete includeemptydirs="true" failonerror="false">
<fileset dir="${builder-base.dir}" includes="**/*"/>
</delete>
Using the
<mkdir dir="${dir}"/ >
inside your <target> tag should work, but I am not sure what else you want to do along with mkdir?
I'm not 100% sure it'll work but you might be able to do something like the following to make the parent directory you're after:
<mkdir dir="${file}/../"/>
If that doesn't work straight off then it might be worth defining a property using the location syntax before creating a directory with the new property:
<property name="dir" location="${file}/../" />
<mkdir dir="${dir}" />
Well-behaved Ant tasks are generally expected to create any necessary directory structures unless there is a good reason not to.
Are you writing a task? If so you should add the directory creation logic to your task. If you are getting the task from a third party you should point this fact out to them and have them fix their task. Failing that Dan's solution should work.

ANT: How to call target for all build.xml in subdirectories?

How do you call a specific target in all build.xml located in all subdirectories using wildcards (ie not hard coding the subdirectory names)? The below answer is hardcoded. Is there a way to do it without hardcode?
Similar to this question: Pass ant target to multiple build.xml files in subdirectories
Use the Ant subant task like this:
<subant target="sometarget">
<fileset dir="." includes="*/build.xml" />
</subant>
If you include an "inheritall" attribute (same as how it's used in but defaults the opposite), you can share all your current project's properties and everything too. This also makes it very easy to overwrite tasks defined in your main build.xml file if you need to.
Read more about it here.
I'll setup different properties within my build.properties file. I use these to dynamically build paths in my targets.
Define the location of your build.properties file:
<!-- all properties are in build.properties -->
<property file="build.properties" />
Use those properties in your targets:
Properties in the build properties are similar to setting up an .ini file:
project.rootdir=c:/Deploy
project.tempbuilddir = c:/Deploy/Temp/Inetpub
project.builddir=c:/Deploy/Inetpub
# Build prefix will be added to that tags urls (.../tags/${project.buildprefix}Build_${today.date})
project.buildprefix=ACA_
I guess you could use a dynamic file as your properties file, if necessary, as long as you define the proper path to the file. You could point it to a server-side file to dynamically write your properties file (ColdFusion, PHP, JSP, whatever).
I've used ant-contrib's foreach task to do something like this.
http://ant-contrib.sourceforge.net/tasks/tasks/foreach.html
Sounds like a perfect candidate for the <subant> task.

ant iterate over files

I want to iterate over a list of jars (undefined number) and add them all to the jar file.
To add them I plan to use something like this:
<jar id="files" jarfile="all.jar">
<zipfileset src="first.jar" includes="**/*.java **/*.class"/>
<zipfileset src="second.jar" includes="**/*.java **/*.class"/>
</jar>
but how do I iterate over them? I don't have ant-contrib
Thanks!
Just use zipgroupfileset with the Ant Zip task
<zip destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</zip>
This will flatten all included jar libraries' content.
If you do not have access to ant-contrib For task, you may end up to have to define your custom Task for doing what you need...
If you have ant1.6 and above, you can also try subant (see New Ant 1.6 Features for Big Projects):
If you use <subant>'s genericantfile attribute it kind of works like <antcall> invoking a target in the same build file that contains the task.
Unlike <antcall>, <subant> takes a list or set of directories and will invoke the target once for each directory setting the project's base directory.
This is useful if you want to perform the exact same operation in an arbitrary number of directories.

Resources