1

We are shifting from jdk 1.8 to jdk13. In our build.xml we have

<target name="generate-native-headers" depends="compile,resolve" description="Java to Native">
   <javah class="com.zimbra.znative.IO" outputfile="${build.dir}/IO.h" classpathref="build.class.path"/>
</target>

But java10+ is not supporting javah anymore so I found we can achieve this with javac "nativeheaderdir" here - https://ant.apache.org/manual/Tasks/javac.html#nativeheaderdir

So I tried to convert above javah task to javac as below

<target name="generate-native-headers" depends="compile,resolve" description="Java to Native">
    <javac srcdir="src/java/com/zimbra/znative" nativeHeaderDir="${build.dir}" classpathref="build.class.path" includes="src/java/com/zimbra/znative/IO.java"  />
</target>

Now the missing javah error gone, but I don't see IO.h file generated in my build directory. Can anyone help me, how to do this? Your help is really appreciated, thank you.

Note: directory src/java/com/zimbra/znative have around 5-6 .java files. I mentioned an example for 1 file only.

Nilesh
  • 1,047
  • 1
  • 12
  • 20

3 Answers3

1

I can't see an obvious way to persuade the javac task to do this. nativeHeaderDir= generates the headers, but won't concatenate as you have found.

A post-javac workaround might look like this - combine the per-class headers into a single file using the Ant <concat> task:

<concat destfile="IO.h">
  <header>/* DO NOT EDIT THIS FILE - it is machine generated */
#include &lt;jni.h&gt;
</header>
  <concat destfile="IO.h">
    <fileset dir="${build.dir}" includes="*.h" />
    <filterchain>
      <linecontainsregexp negate="true">
        <regexp pattern="(#include .jni.h.)|(DO NOT EDIT THIS FILE - it is machine generated)" />
      </linecontainsregexp>
    </filterchain>
  </concat>
</concat>

The basic idea is simple: find all the header files generated by javac, concatenate them into one header with the name required. Optionally, along the way, strip out the repeated #include and comment lines. The result should look the same as a JDK 8 javah-produced header.

martin clayton
  • 76,436
  • 32
  • 213
  • 198
0

With the below changes, I am able to create header files. But the generated file name is "com_zimbra_znative_IO.h". It should be "IO.h"

<target name="generate-native-headers" depends="compile,resolve" description="Java to Native">
        <javac srcdir="src/java/com/zimbra/znative" destdir="${build.dir}"  nativeHeaderDir="${build.dir}" classpathref="build.class.path"
               includes="IO.java"                                                                                                      
               excludes="Process.java,ProcessorUsage.java,ResourceUsage.java,Util.java,ProxyInfo.java" />
</target>
halfer
  • 19,824
  • 17
  • 99
  • 186
Nilesh
  • 1,047
  • 1
  • 12
  • 20
  • I have edited this answer so that it is mainly an answer. Supplementary questions do not belong in answers - please ask another question for that. Thank you. – halfer Jan 23 '20 at 00:06
0

Generating header files using javac task from ant should be along with your generated class file. So if the corresponding class file already available and no change in the source file (other words your compiled class modification time is higher than the java source file) then the javac ant task won't do any action on that class file including native header file generation.

You have to perform few check,

  1. Is your srcdir attribute pointing to the right directory which starts your packages. (ex. your class name is com.zimbra.znative.MyClass and the file path is src/java/com/zimbra/znative/MyClass.java then your srcdir should be point to src/java.
  2. Provide destdir where your compiled class files will be generated, otherwise it will generate inside your srcdir.
  3. Normally includes not required if you want to generate all header files which all the class having native method in your srcdir
<target name="generate-native-headers" depends="compile,resolve" description="Java to Native">
    <javac srcdir="src/java" nativeHeaderDir="${build.dir}" destdir="${build.classes}"
      classpathref="build.class.path" includes="src/java/com/zimbra/znative/IO.java"  />
</target>

Before running the ant make sure the IO.class file not exist or the source .java file has recent changes than the existing class file. then see it will generate the class file and header files. Header files should be inside ${build.dir}

J J
  • 70
  • 6