Skip to main content

How to do Conditional Compilation with Java

Posted by schaefa on January 20, 2005 at 4:50 PM PST

These instructions are a way to do conditional compilation with Java like the C/C++ #ifdef. In Java there is no preprocessor and so we need to work around this missing feature. This work around is using Ant's copy and filter feature to create the source with the different code in it. In this example I wanted to accomplish the following:

  • The Java classes must be valid Java code so that any editor/IDE can read it as regular Java code
  • The conditional compilation must also work outside Java methods so a constant boolean if statement does not work
  • The selection of the version to compile to must be settable when the build of the project is started
  • The compilation must work properly without cleaning the project first

1. Add into your Java classes a start tag (like //[ifdef]) and an end tag (like //[enddef]) around the code in question. To include code for version 1:

//[ifdef]
import java.sql.ParameterMetaData;
//[enddef]

or
//[ifdef]
    public byte[] getBytes(String parameterName)
            throws SQLException {
        ...
    }
//[enddef]

The // at the beginning of the tag ensures that this is still valid Java source code.

To exclude code:
/* //[endef]
    public byte[] getBytes(String parameterName) {
        ...
    }
//[ifdef] */

2. To swap the used code for version 2 the start and end tag just have to be set to /* respectively */. In this case the included code is excluded and the excluded code in included.

3. Add a copy-n-filter task in your Ant build script. There the source coded will be copied away and the filter tags are replace with the actual value. For version 1 the start / end tag will vanish and for version 2 they will be substituted with /* and */. Attention: the source code is copied into two different root directory one for version 1 and the other for version 2. Because Ant tries to avoid copies if the file does not have changed this can lead to having the wrong version of code in your target directory. This is an Ant script snippet:

        <copy todir="${src.dir}/${version}">
            <fileset dir="${src.dir}/java">
                <include name="**/*.java"/>
            </fileset>
            <filterset begintoken="//[" endtoken="]">
                <filter token="ifdef" value="${ifdef.token}"/>
                <filter token="enddef" value="${enddef.token}"/>
            </filterset>
        </copy>

4. Set the start / end tag token. Note that the start / end tag token are set at the end to their default value only when not already set.

        <condition property="ifdef.token" value="/*">
            <equals arg1="${compile.to.version.1}" arg2="false"/>
        </condition>
        <condition property="enddef.token" value="*/">
            <equals arg1="${compile.to.version.1}" arg2="false"/>
        </condition>
        <!-- If not set already make sure that they are defined but empty -->
        <property name="ifdef.token" value=""/>
        <property name="enddef.token" value=""/>

If the Ant script is started without compile.to.version.1 set to false it will compile the code to version 1. If the parameter is set to false it will compile to version 2. This can be accomplished this way:
ant -Dcompile.to.version.1=false build

5. Make sure that you compile from the right directory:

        <javac ...
        >
            <src path="${src.dir}/${version}"/>
        </javac>

I hope this will help you in the future – Andy

Related Topics >>

Comments

Just FYI, you can use the C/C++ Preprocessor with anything, ...

Just FYI, you can use the C/C++ Preprocessor with anything, including Java. Just use the command line option to your C/C++ compiler that indicates only the preprocessor step should be run. Its been a while since I used it, but I believe the command line option is -P.

How to do Conditional

No conditional compilation is really a pain in the neck for all developers. There have been several different approaches to this problem, one that I found recently is a freeware called wwyt, which is a pre-processor for conditional compilation. First, you can embed in your .java files its own directives (like #if, #else, hidden inside comment blocks, of course.) Then, right before compilation, you use this tool to convert the source files. wwyt will remove or expose Java statements based on those directives. After compilation, you can run it again to restore the files back to their original state. Details can be found here: http://www.adarian.com/wwyt. It's an external tool, running under Windows command line, though.