Working around long Classpath issue in Windows
Running ant task on windows
If you are building the code in linux or mac, you will not have to worry about the long classpath error. But you are using windows, then it is likely that you will run into following errors while running an Ant build
java.io.IOException: Cannot run program "C:\Program Files\Java\jdk1.8.0_73\bin\javac.exe" (in directory "c:\<workspace folder>\pentaho-platform-ee\bi-platform-ee"): CreateProcess error=206, The filename or extension is too long
Possible solutions
Searching for the solutions on the web, I found a few workaroundsÂ
- Reduce the classpath
- Use directories instead of jar files. For example, if the directory foo contains a.jar and b.jar, then the foo/* can be specified in the classpath. The only limitation is you cannot specify the order in which the jar files will be added in the classpath.
- Use the classpath attribute inside of manifest file to point to other jars.
Classpath attribute of manifest file
In this approach, you can create an empty jar file and specify all the jars in the classpath attribute of the manifest. For example, following section list the content of manifest file inside of jar.
Manifest-Version: 1.0 Class-Path: activation-1.1.jar annogen-0.1.0.jar antlr-complete-3.5.2.jar
Ant version 1.7, includes a new task 'manifestclasspath', which converts the classpath into space separated list of items. This can be used to set the class-path attribute of the manifest.Â
<manifestclasspath property="jar.classpath" jarfile="MyJar.jar"> <classpath refid="classpath" /> </manifestclasspath>
Example Usage
Here is an example of using the above approach to resolve the long classpath issue while building pentaho-platform-extensions
- Copy the following target into subfloor.xml,. This creates Manifest-path.jar using the classpath refid - 'classpath'. The classpath refid in subfloor.xml, includes all the jars that are present in lib and dev-lib folder. So essentially, class-path attribute of manifest of Manifest-path.jar will have all the jars that are present in lib and dev-lib folder. The path element of the target then adds the newly created Manifest-path.jar in the manifest.classpath.
<target name="manifest.jar"> <manifestclasspath property="jar.classpath" jarfile="${bin.dir}/Manifest-path.jar"> <classpath refid="classpath"/> </manifestclasspath> <jar destfile="${bin.dir}/Manifest-path.jar"> <manifest> <attribute name="Built-By" value="${user.name}" /> <attribute name="Class-Path" value="${jar.classpath}"/> </manifest> </jar> <path id="manifest.classpath"> <pathelement path="${bin.dir}/Manifest-path.jar"/> </path> </target>
- Â In the compile.compile target, change the path refid from classpath to manifest.classpath. Add the new target 'manifest.jar' as dependency to make sure it gets executed first.
<target name="compile.compile" depends="init, manifest.jar"> <javac destdir="${classes.dir}" debug="${javac.debug}" deprecation="${javac.deprecation}" fork="true" memorymaximumsize="${javac.maxmemory}" source="${javac.source}" target="${javac.target}" encoding="UTF-8"> <classpath> <!-- path refid="classpath"/ --> <path refid="manifest.classpath"/> </classpath> <src path="${src.dir}"/> <compilerarg value="${javac.xlint}"/> </javac> </target>