0

I would like to do conditional compilation in a program of mine. I know that if you declare a public static final boolean the compiler will ignore the branch that is not traversed. Is it possible to have an ant target change a variable before building the program?

For example if I have:

final public static boolean windows = false;

I would like two ant targets: Windows and Mac. I would like the command ant windows to change the boolean to true, while ant mac leaves the variable as is.

Thanks.

Thilo
  • 257,207
  • 101
  • 511
  • 656
kgrad
  • 4,672
  • 7
  • 36
  • 57
  • 1
    Is this really necessary? Why not just load the boolean once at startup from a configuration file? Think about how much you gain (the evaluation of a non-static non-final boolean variable at runtime has no real cost), versus the impact this has on your build process. – Thilo Feb 26 '10 at 01:09
  • @Thilo - The point is to not have the code in the jar at all. Property file doesn't really achieve this, good idea nonetheless. – kgrad Feb 26 '10 at 01:13
  • If it's large swaths of code, the delocalization caused by the dead code in the middle can be pretty significant in terms of performance. – Anon. Feb 26 '10 at 01:13
  • 2
    Consider the OO solution. Create an interface with a separate implementation class for each platform. Then only instantiate the class of the appropriate platform. Java won't load the classes for the other platforms if they are never instantiated, and thus they won't take up memory or ruin localization. You could even distribute the classes for each platform in separate jar files so that you can choose which pieces to distribute to which users. – ChrisH Feb 26 '10 at 01:32
  • 1
    there are valid cases for what you want to do. It's called "source code instrumentation" and there are tools allowing to do that (not Ant AFAIK but surely an Ant Task could be made to perform source code instrumentation). However the use case you gave is not one of them :) – SyntaxT3rr0r Feb 26 '10 at 02:49

5 Answers5

11

You can get Ant to modify a properties file, and then you can read this file in your application pretty easily:
new Properties(new FileInputStream("filename" / new File(filename))),

and read properties using:
Boolean isWindows = new Boolean(properties.getProperty("windows"))

or:
String os = properties.getProperty("os").

You can use the Ant PropertyFile task for doing this: http://ant.apache.org/manual/Tasks/propertyfile.html.

Edit: here's an alternative using another task if you absolutely must edit the source code file using Ant:

<replaceregexp file="blah.java" match="public static final boolean WINDOWS = \"(.*)\"" replace="public static final boolean WINDOWS = \"" + ${properties.windows} + "\"" />
-- replace the code as your own as required. See http://ant.apache.org/manual/Tasks/replaceregexp.html for details.

Chris Dennett
  • 22,412
  • 8
  • 58
  • 84
  • +1. This should be property, not compiled in. The performance benefit of having the compiler strip out the un-used code is negligible. – Thilo Feb 26 '10 at 01:11
  • 1
    I noticed you need to use " for ". Using \" does not work. – Zitrax Feb 07 '11 at 11:19
2

You should read the other answers carefully and see if there is a better solution for you. However, Ant does have a task to replace text in files. For example:

<replace file="${src}/MyFile.java" token="boolean windows=true" value="boolean windows=false"/>

Greg Charles
  • 1,880
  • 4
  • 20
  • 39
1

Skip ant and property files etc, Java already does this!

Use something like System.getProperty("os.name");

jqa
  • 1,340
  • 6
  • 17
1

The properties and the replace tasks should get you what you need. I concur that finding a different approach is a good idea.

However if for some reason the built in tasks will not get you what you need, it is pretty easy to write a custom task for ant. See http://ant.apache.org/manual/develop.html

Development 4.0
  • 2,705
  • 1
  • 22
  • 17
0

You can also provide command-lind value as an argument while calling Java-main program from Ant.

For eg. ant -f build.xml "YouranttaskName" -Doperatingsys="windows"

Inside build.xml

<target name="YouranttaskName">
<java classname="javaclassname" fork="true" >
<arg value="${operatingsys}" />
</java>
</target> 

Inside java -main method this argument-value will be available in same order .i.e. args[0] contains "Windows".

You can write your logic by considering that what is your default OS value, as user may not provide commandline argument and then set 'boolean flag' parameter accordingly.

lucentmind
  • 192
  • 2
  • 11