Use class system path for ant javac task

I want the javac task to use jars from the system class path, by which I mean the class path that is installed in the shell environment before ant runs. This class path

CLASSPATH=D:\local\lib\java\*;.;C:\lib\java\*;C:\lib\java\db\* 

on my system. I have popular banks that are used by many projects. The main snippet that I use in the assembly file is

 <target name="build"> <mkdir dir="${obj}" /> <javac srcdir="${src}" destdir="${obj}" includes="**/*.java" excludes="**/package-info.java **/deprecated/*.java" includeAntRuntime="no" debug="true" debuglevel="source,lines" > <compilerarg value="-Xlint"/> </javac> </target> 

Thus, ant only passes the output directory as the classpath.

 [javac] '-classpath' [javac] 'D:\dev\tbull-projects\jsonc\obj' 

(jsonc is the project I'm working on, and D:\dev\tbull-projects\jsonc is the working directory.) For a while I looked at the documentation and came up with two attempts. First, the attribute classpath="${java.class.path}" to the javac tag. This would skip the extremely long path to the compiler, specifying each jar from ant of its own lib directory, and finally tools.jar from the JDK. Not the class path I wanted.

Second shot set

  <property name="build.sysclasspath" value="first" /> 

before calling javac, and that led me in the right direction. Now these lines were among the weekend:

 dropping D:\dev\tbull-projects\jsonc\D:\local\lib\java\* from path as it doesn't exist dropping D:\dev\tbull-projects\jsonc\C:\lib\java\* from path as it doesn't exist dropping D:\dev\tbull-projects\jsonc\C:\lib\java\db\* from path as it doesn't exist dropping D:\dev\tbull-projects\jsonc\C:\Program Files\Java\jdk1.6.0_18\jre\lib\sunrsasign.jar from path as it doesn't exist dropping D:\dev\tbull-projects\jsonc\C:\Program Files\Java\jdk1.6.0_18\jre\classes from path as it doesn't exist 

Well, you can imagine that these paths really do not exist. I just don't understand why ant built them that way. He would know how to do path arithmetic in Windows, right?

Perhaps my approach has been corrupted more fundamentally, so I will let you know what I really am after. Therefore, I am developing this project (library) that uses another library. The project will be open source, so I want other developers to be able to create it after they download the dependency library and put it somewhere in their classpath.

From what I saw in other questions about ant + classpath, it seems like this is a normal way to distribute dependency libraries with source code (so the class path can be like. / Libs). But of course I don't want to have jars in my git repository. So how can this be done?

+6
source share
8 answers

Soo ... I think I should answer the question myself. Passing the source class path to the javac task can be achieved with this:

 <!-- load environment into the env property --> <property environment="env" /> <javac srcdir="${src}" destdir="${obj}" includes="**/*.java" excludes="**/package-info.java **/deprecated/*.java" includeAntRuntime="no" includeJavaRuntime="no" debug="true" debuglevel="source,lines" > <!-- add -classpath option manually --> <compilerarg value="-classpath" /> <compilerarg value="${env.CLASSPATH}" /> <compilerarg value="-Xlint"/> </javac> 

This does the trick, at least so far, when the javac task now gets the correct class path. However, this still won't work, javac now spits on these complaints:

 [javac] warning: [path] bad path element "D:\local\lib\java\*": no such file or directory [javac] warning: [path] bad path element "C:\lib\java\*": no such file or directory [javac] warning: [path] bad path element "C:\lib\java\db\*": no such file or directory 

This is a direct lie, these paths really exist. I use them all the time, and if I manually create an equivalent javac call in the shell, it works like a charm. I suspect ant javac does not allow jar files in these directories. I have to learn this.

UPDATE

This is true, as I suspected, the wildcard is not allowed for the individual jar files represented by the javac task. I managed to execute the resolution manually, and now it works as it should. And this decision was actually a struggle in itself. Therefore, I will leave a solution here for those poor souls who struggle with the same stupidity, I hope before they ask people who have nothing more to do than to deceive (yes, Ano, speaking of you).

Turns off, ant is missing the most basic functions that you expect from a build tool. It also turns out that I'm not the first to notice this. While solutions are rare, there is a good article on Using JavaScript to make Apache ant less painful , which really saved my day. Yes, ant can indeed be a script that does not seem to be widely known, although not kept secret . We can safely assume that Javascript is already available without installing additional libraries if you run ant on Java 6.

Su ... before the business. That's what:

 <target name="expand_classpath"> <script language="javascript"><![CDATA[ // the original classpath var ocp = java.lang.System.getenv("CLASSPATH"); // ... split in parts var ocp_parts = ocp.split(project.getProperty("path.separator")); // where our individual jar filenames go, // together with pure directories from ocp_parts var expanded_parts = [ ]; for each (var part in ocp_parts) { if (part.endsWith('*')) { var dir = part.substring(0, part.length() - 1); var f = new java.io.File(dir); // don't know how to construct a java.io.FilenameFilter, // therefore filter the filenames manually for each (var file in f.listFiles()) if (file.getPath().endsWith('.jar')) expanded_parts.push(file.getPath()); } else expanded_parts.push(part); } var expanded = expanded_parts.join(project.getProperty("path.separator")); project.setProperty("classpath.expanded", expanded); ]]></script> <!-- <echo message="classpath.expanded = ${classpath.expanded}" /> --> </target> <target name="build" depends="expand_classpath"> <mkdir dir="${obj}" /> <javac srcdir="${src}" destdir="${obj}" classpath="${classpath.expanded}" includes="**/*.java" excludes="**/package-info.java **/deprecated/*.java" includeAntRuntime="no" includeJavaRuntime="no" debug="true" debuglevel="source,lines" > <compilerarg value="-Xlint"/> <compilerarg value="-Xlint:-fallthrough"/> </javac> </target> 
-1
source

Set includeJavaRuntime = true in the javac task.

 <target name="build"> <mkdir dir="${obj}" /> <javac srcdir="${src}" destdir="${obj}" includes="**/*.java" excludes="**/package-info.java **/deprecated/*.java" includeAntRuntime="no" includeJavaRuntime="true" debug="true" debuglevel="source,lines"> <compilerarg value="-Xlint"/> </javac> </target> 
+3
source

Why don't you install CLASSPATH in Ant? This is great for this. You make a mistake if you do anything else. This will not only work, but your build.xml file will also document the requirements.

+1
source

When javac compiles the code, it tries to find the files in the rt.jar file in the ct.sym symbol file (which is also present in the lib directory). some files are missing from this character file. I have to add a compilation option to ignore the character file and look directly in rt.jar.

so I used this option -XDignore.symbol.file for ant, I put this value in the javac tag. it works great if you use eclipse or any other ideal.

 <compilerarg value="-XDignore.symbol.file"/> 

So, whenever you get a ClassNotFoundException when using classes from rt.jar, and if the class is still there, just try adding this argument to the java compiler

For rt.jar link from ant you can use:

 <fileset dir="${java.home}/lib" includes="rt.jar"/> 

The source data was found here: http://www.javaroots.com/2013/01/javac-error-using-classes-from-rtjar.html

+1
source

If someone is new to the java / ANT world, people offering maven are idiots, what happened to the KISS principle?

OP, instead of using javascript flicker try this

 <project default="build"> <property name="src" value="src" /> <property name="obj" value="obj" /> <property name="parent.dir" value="/jakarta-tomcat/common/lib" /> <path id="project.class.path"> <pathelement location="lib/" /> <fileset dir="${parent.dir}" includes="**/*.jar" /> </path> <target name="build"> <delete dir="${obj}" /> <mkdir dir="${obj}" /> <javac srcdir="${src}" destdir="${obj}" includes="**/*.java" excludes="**/package-info.java **/deprecated/*.java" debug="true" debuglevel="source,lines" classpathref="project.class.path" /> </target> 

0
source

It’s clear that the people behind java , and (or at least) ant , really don’t really want to see $CLASSPATH ending up as a repository for user-installed libraries of the type that 95% of other main languages ​​(C / C + +, perl, python, ruby, etc.). So this is a complex paradigm of swallowing if you are used to general programming in most other major languages.

Unwillingness is still such that it is obvious that ant intentionally forces $CLASSPATH out of the environment, but the simple way is to simply use another variable.

  <property name="classpath" location="${env.JAVALIBPATH}"/> 

This will work without fuss with the <javac> and <java> commands ( classpath="${classpath} ), which is good, because if you try this instead:

  <property name="classpath" location="${env.CLASSPATH}"/> 

There is no includeAntRuntime="false" option for <java> that will allow this to work. You just can't get $CLASSPATH , and someone went long to make sure of it (without, apparently, yikes, adding a heavy javascript hack).

Of course, this means that you need to use a separate env variable, and for your common / production version stick to Java "Sorry, no user libraries!" paradigm. This is not a big problem if you use a variable name, which, if used, will almost certainly be undefined on the target system.

0
source

Alternatively there are Maven Ant Tasks . This will allow you to use the Maven dependency mechanism so that the IMO is cleaner than Ivy. But this is not the best solution.

-1
source

I assume your “popular” JARs are well-known open source projects. This means that they are available in the central Maven repository.

Although I believe that using Maven is the best answer to this question, you can also hack something using the Ant <get> task. For example, to download the JUnit JAR (possibly typos):

 <property name="dependency.dir" value="${basedir}/dependencies"/> <property name="junit.jar" value="junit-4.8.2.jar"/> <property name="junit.url" value="http://search.maven.org/remotecontent?filepath=junit/junit/4.8.2/${junit.jar}"/> <target name="download.dependencies"> <mkdir dir="${dependency.dir}/> <get url="${junit.url}" dest="${dependency.dir}/${junit.jar}"/> </target> 

Of course, if you do this, you will have to carefully configure the build scripts so that you do not load with each run. And you will increase the load on the Maven Central repository.

-2
source

Source: https://habr.com/ru/post/887490/


All Articles