Sounds a little bit crazy, but you would probably need this more often than you think. If you develop some JNI applications this probability increases quite a bit.
Nowadays there is a big hype with the Continuous Integration and behind that usually sits a pretty solid build system. So most likely you will have to find a way to create your native libraries automatically and not from the development environment. Not to mention that you would probably want to generate your binaries on multiple environments to ensure compatibility for your JNI application. After all, it is write once, run anywhere.
And isn’t just nice to do everything from one place? One IDE, one build system, etc.
OK, I convinced you. But how do you do it? Ant is simply great when it comes about building Java applications, but what about compiling C code into native libraries? Now is the part where cpptasks jumps to give you a hand. So let’s see how your ANT file will look like for compiling your native library:
<property environment="env"/> <condition property="iswin"> <os family="windows"/> </condition> <taskdef resource="cpptasks.tasks"/> ... <mkdir dir="${native.out}"/> <cc outtype="shared" subsystem="console" outfile="${native.out}/${native.name}" objdir="${native.out}" name="msvc"> <fileset dir="${native.src}" includes="*.c"/> <libset dir="${native.src}" libs="OtherLib"/> <sysincludepath location="${jdk.path}/include/"/> <sysincludepath location="${jdk.path}/include/win32" if="iswin"/> </cc></pre
where
iswinis an Ant property set only if we are running on windowsnative.outis the directory where the libraries and object files are generatednative.srcis the directory containing the C source filesnative.nameis the name of the generated libraryjdk.pathis the JDK installation directory
.
As you can see the C compiler used is Visual C (name attribute of the cc task). And most probably you will need the WinAPI include file, so add the below inside your cc task:
<compiler name="msvc"> <sysincludepath location="${env.WindowsSdkDir}/include"/> </compiler></pre
And now comes the messy part. The environment variable WindowsSdkDir must be defined. Without this the compiler won’t even start and you will get an error like this:
Could not launch cl: java.io.IOException: Cannot run program "cl" (in directory "native\out"): CreateProcess error=2, The system cannot find the file specified
.
But fortunately there is a workaround and it is pretty simple, even tough not beautiful. In the Windows SDK distribution there is a .bat file that defines all the necessary environment variables: vsvars32.bat. And its location is defined in an environment variable: VS90COMNTOOLS for Visual Studio 2008 and VS80COMNTOOLS for Visual Studio 8.
So all you have to do is run (in the same CMD session) “%VS90COMNTOOLS%\vsvars32.bat” before running your Ant build (or launching your IDE). And no, there is no (clean) way to set an environment variable from Ant or Java.