Building OpenCV for Java on Windows x64 with Cmake - java

I am building OpenCV 420 for Java on Windows using cmake including the comtributed (extra) modules. I am successful in doing the cmake processes to generate the VS 2017 project. The VS project, set for x86 target, compiles and generates opencv-420.jar and opencv_420.dll. The opencv_420.dll is 37158kb in size. It contains all of the dependent libraries (dlls) created by the compile process. This jar and dll pair work correctly with the two files giving full access from Java to all opencv functions including the contributed ones. This shows that the varions dependant dlls are being merged into the single library opencv_420.dll.
Next I created a folder for x64 target, copied the x86 folder I used for the above x86 project and set the platform to x64. I run cmake successfully, generate the VS project and it compiles successfully as far as I can tell (there is a lot going I don't fully understand). This generates an x64 opencv-420.jar and an opencv_420.dll as expected. However, the opencv_420.dll is small at 2621kb and when I try to run the application it fails with can't find dependent libraries. I have determined this dll does not contain the the dependent libraries like the x86 dll does.
I have been over the cmake files and the VS project and can't seem to locate the difference between the x86 and x64 projects that causes the dependent dlls to not be merged into the opencv_420.dll.

I answered this one myself. Talk about not seeing the forest for the trees! There was a difference between the x86 and x64 cmake options that I just did not see until some reading I was doing today triggered the aha moment. I needed the Java Fat Jar option enabled in the x64 config as it was in the x86 config. All good now.

Related

Is there a way to build installers for a java application for multiple targets on the same platform?

I would like to build a .msi, .deb, and .pkg from the same source tree and on the same machine.
Distributable runtimes for Java9+ are no longer downloadable, so perfectly sane solutions like launch4j+nsis no longer work.
javapackager has been abandoned by Oracle.
OpenJDK's jpackager can't (and will never) cross compile for different build projects, and it isn't even a real product yet.
Is there a way to build installers for win/linux/macos from the same machine?
Is the promise of "compile once, run everywhere" is truly dead and buried?
I have a legacy java application that is now in limbo, since MacOS java8 doesn't support java.awt.desktop, which requires java9+
I use since Java 9 and the inception of jlink and jpackage a cross platform setup made of different docker images and Virtual Machines, where I can build the runtimes and the installers (MSI, DEB/RPM and DMG/PKG) on the target platforms within' my host system.
For Mac, you can use a KVM image, if you don't have Apple Hardware, where you can issue commands over ssh.
For Windows, a Linux docker container is used, packed with wine, the OpenJDK for Windows, the Visual Studio build tools, WIX and CMake to perform the build of the runtime image and a customised MSI installer (since the javapackage version is too simple)
The answer to your question is not short. But I'll try to be brief and point to all relevant information.
The short answer is: you can do this.
The longer answer is: you still have to build a runtime for each target environment from within that target environment, but you only have to do this once. You can then save that runtime and reuse it to automatically build installers with your latest Java jars/code in a single environment. For example, use jlink to build the runtime image and jpackage to build the app image for Windows, Linux, and macOS (on those respective systems) then copy those app images to macOS and build an nsis installer (or installer builder of your choice) for each platform from within macOS.
When you update your code and recompile, you can just copy the new jars into the pre-built app image. You'll have to copy in all your dependencies, too, but that would be necessary for any installer. There is a config file in the runtime built by jpackage that has options, classpath, etc., which you can change without a need to rebuild the runtime.
Create a runable program, something as simple as
package com.example;
public class Greeter {
public static void main(String[] args) {
System.out.println("Hi, I'm the greeter. Welcome.");
}
}
compile the program and place in a jar (call it greeter.jar for this example and place in the build directory, called target for this example)
run jilnk to build a runtime. The following command uses jlink from JDK11 and puts the result in a directory called runtime. This example includes all modules on the module path, but you can use jdeps to get just the modules you need. I suggest including all modules if you do not want to ever have to rebuid this runtime when your project evolves and depends on more of the Java runtime. Not to mention transitive dependencies on the JRE.
> set JLINK=C:\Program Files\Java\jdk-11.0.6\bin\jlink.exe
> "%JLINK%" --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules ALL-MODULE-PATH --output runtime
run jpackage to build an app image suitable for packaging in an installer. This uses jpackage from JDK14 early access (the only version of the JDK that has jpackage at the time of this writing). The command line option —win-console is only for Windows and is only necessary if the program does something with stdin/stdout (the console). Our example writes to the console, so we need this. This argument will likely sometimes open a console window when running your application, so remove it if you have a pure windows based (gui) application.
> set JPKG=C:\Program Files\Java\jdk-14-ea\bin\jpackage.exe
> "%JPKG%" --type app-image -i target —win-console -n Greeter --main-class com.example.Greeter --main-jar greeter.jar --runtime-image runtime
run the application with .\Greeter\Greeter.exe
The resulting app image (in the app-image directory) can be used to build an installer with your favorite install builder (I use NSIS). You can do this on any platform. Furthermore, when you update you program you only have to copy your new jars into the app image. There is no need to rebuild the app image or the runtime. This copy of the jars can take place on any platform, and there is no need for Windows to be run in order to build a new installer for a new version of your application.
If your application has jar dependencies (say from Maven central), you’ll need to copy those jars to the Greeter/app directory and update app.classpath in the Greeter/app/Greeter.cfg file. Again, all this can be done on any platform, no need to start up the target platform (Windows in my case).
Also, jpackage is an officially supported tool but only available in EA JDK 14 (it's Feb 2020 as I write). JDK 14 may be downloaded and jpackage can be used with other versions of JDK (like JDK 11 LTS).
See https://blogs.oracle.com/jtc/a-brief-example-using-the-early-access-jpackage-utility
The JEP for jpackage has been marked "Closed/Delivered" suggesting the tool is mature and just waiting for JDK 14 to be released: https://openjdk.java.net/jeps/343
There is an example project on GitHub that has a lot of useful command line examples on how to run jlink and jpackage: https://github.com/jtconnors/SocketClientFX
Though this project uses outdated command options. You can run jpackage --help to get the new options.
Useful Links:
JDK 14 (early access until March 17th, 2020): http://jdk.java.net/14/
Explains non-modular usage of jlink: https://medium.com/azulsystems/using-jlink-to-build-java-runtimes-for-non-modular-applications-9568c5e70ef4
jlink manual: https://docs.oracle.com/javase/9/tools/jlink.htm#JSWOR-GUID-CECAC52B-CFEE-46CB-8166-F17A8E9280E9
jpackage - run with the -help option to get good reference information
Creating a Windows MyApp.exe and MyApp-setup.exe on linux:
I don't need jpackage at all, only jlink, launch4j, and nsis:
Use jlink once natively to create the runtime and tar off the
results for use on other machines.
launch4j can be instructed to use that runtime, and nsis can be
told to copy the whole runtime on install.
Creating a MacOS MyApp.app on linux:
Use jlink to create a tarfile that can be reused to recreate
Contents/runtime/Contents/Home (like for windows above)
Copy in the jpackage generated
Contents/runtime/Contents/Info.plist and
Contents/runtime/Contents/MacOS/libjli.dylib
Copy in the jpackage generated Contents/MacOS/MyApp stub and
Contents/MacOS/libapplauncher.dynand hope they never have to
change.
Create Contents/Info.plist and Contents/app/MyApp.cfg file from
templates using the jpackage generated ones as a reference
Fill in Contents/app, Contents/Resources with my jar files and other resources
Creating a pkg on linux:
https://gist.github.com/msabramo/2a8e44eb6dcc3b89437d33649b0b1841
Creating a dmg on linux:
https://askubuntu.com/questions/1117461/how-do-i-create-a-dmg-file-on-linux-ubuntu-for-macos
Alternately, migrate from nsis to install4j
https://www.ej-technologies.com/products/install4j/overview.html
In theory once I get it all working on linux, I can port the effort to both Darwin and cygwin (WSL just doesn't work right for me atm, will get that working last)
Proof of concept is here (linux, MacOS, cygwin):
https://github.com/nyetwurk/ecuxplot
It is kind of ridiculous this multiplatform crosscompile tooling doesn't exist anywhere, considering the rise of CI/CD, and that the whole point of java is portability and architecture independence.

Create standalone executable from Java code for Windows, OSX and Linux all at once

i'm coding a project in Java and building it with gradle.
I need to keep it simple and compile it into standalone binaries for Windows, Mac and Linux.
Is there anything which can build all of this binaries or must i use a separate lib (like Launch4j for Windows executables) for every single binary?
I'd like to call a single "build-all-binarys"-like task in gradle and get a .exe, .app and .bin file out of it.
It would be nice to have the possibility to bundle a JRE into the binary as well.
Use the javapackager, added since Java 8 in the JDK.
It nicely creates a self contained executable - that's it bundles the JVM with every copy - of all standard operating systems with one call.
The javapackager is located in JAVA_HOME/bin/ directory.

JOGL library - universality

I want to use JOGL ibrary and I want to use it on linux and windows...
Will project compiled on linux run on windows?
Do I have to change included libraries if I want to compile it for windows?
Regards,
Peter.
I have worked under GNU Linux (currently Mageia Linux 4) with JOGL since 2006 and I can confirm that my first person shooter works as expected on any operating system supporting the Java Runtime Environment including GNU Linux, Mac OS X, OpenIndiana, Microsoft Windows, ... I compile and build it under GNU Linux. I even build my own self-contained native application bundles under GNU Linux with JNDT and several end users confirmed that they work very well. In other words, I don't need to be under Mac or Windows even to create "native" Java applications.
Vodlez is right even though I wouldn't use the term "link". JOGL 2 provides some JARs containing the native libraries, I advise you to put them all (including those NOT for your own operating system) into your project or to use a build tool (Ant, Maven, Gradle, ...) that does it for you so that other developers can run your project but anyway, when you compile, you don't need those JARs. You can set the Java library path too and then you have to take care of pointing out to the directory containing the appropriate native libraries.

Selecting the correct Java, JRE and JDK versions when building an executable JAR for distribution?

I am putting together my first Java package for distribution to users, and am running into some difficulties. I have jar packages that I've built that users can't run; the error messages vary, but are all "version" something or another. I suspect I'm selecting the wrong build paths, and I'm not quite sure where to start troubleshooting because I don't clearly understand the differences between the Java executable (javaw.exe), the JDK and the JRE; I have some questions that I'd like answered which will help in that understanding. I'm used to the way that C# executables compile in VS; wrapping my head around how executable jar files come together is still a little mysterious to me.
Although I've done a few google searches, most of what I'm finding is how to build a jar file, but not how to manipulate/use/select the Java, JRE and JDK versions appropriately to ensure compatibility. I do understand that the JRE includes the virtual machine that allows Java bytecode to run anywhere, and that the JDK includes development tools...but as to figuring out which version I AM running, vs which version is used when building jar files and which version SHOULD be used...I am completely lost.
I'm using Eclipse Indigo under 64-bit Win7. My build path includes the following:
JRE System Library: C:\Program Files\java\jre7\*
External paths: C:\<MyDocuments>\java\lib\commons-io-2.4*
I also have, installed on my machine, the following paths which are NOT included in the build:
C:\Program Files (x86)\java\jre7\
C:\Program Files (x86)\java\jre1.5.0_22\
C:\Program Files (x86)\java\jdk1.7.0_21\
The users that will be running this executable file are only supported (by corporate IT) up to JRE5. I suspect that my building this pointing it jre7 is one of the things that's messing with me.
My first stupid question is whether there's a difference between "Java" and the "JRE" when it comes to version numbers. For instance, when I read about JavaSE7 or JavaEE7, are they talking about the JRE version for the standard or enterprise editions? Are the development kits and runtime environments just components to JavaSE/EE? Or are they separate and distinct products?
Then, my understanding is that I should build this jar using the lowest-common-denominator JRE expected from my users. In this particular case, because the corporate standard is JRE5, I should build this pointing to JRE5 instead of JRE7. Is that a correct assumption?
Does it matter if I build using the 64bit or 32bit version? Some older machines may still be 32bit running JRE5, so I need to make sure I'm backwards compatible.
The Program Files (x86) naming conventions confuse me. JRE7 installed as \jre7. However, JRE5 installed as \jre1.5.0_22, and I also have jdk1.7.0_21, which, based on the JRE name, I assume to be the Java7 Development Kit. Do I need to install the Java5 Development Kit to properly build this program? And am I properly interpreting the versions from the filenames? that 1.5 represents Java5 and 1.7 represents Java7?
Then, my last question I know there's an Eclipse option to copy the external libraries to the project. I assume that if I do this, this will be included with the jar so the users do NOT need to have the Apache Commons jars on their local machines in order for this to run properly. Does the manifest include any confirmations that these files were included? I've been unable to find any references...so I'm trying to verify if I'm even pulling the Commons libraries over and where to look to get that confirmation.
This is just speculation, but I think you may have to re-write the program with the java5 jdk, because some of the APIs/libraries used in java7's jdk may not be recognized by the java5 jre. (Just like it wouldn't be possible to play PS4 games on a PS2... without any serious modding)
If you write the program in Eclipse, you can just select what library you want to use as you create the Java project. At the "Create a Java Project" screen, you can select the "Use an execution environment JRE:" or "Use a project specific JRE" or "Use default JRE" option. (I have jdk6 and jdk7 installed on my computer so I'm able to select those two options; which is why you may have install the jdk5 in order to create a java 5 project.)
You are properly interpreting the filenames. jre1.5.0_22 is java 5 update 22.
There is a way to specify which JRE is used to run the jar file.
cmd prompt >
"C:\Program Files (x86)\java\jre1.5.0_22\bin\javaw.exe" -jar "filepath_filename.jar"
Drop the "w" from the javaw.exe, and you'll be able to see any console and/or stack trace output.

Why the JAR file compiled by Java SE, able to execute in Android

In Android OS, I am able to run several Java JAR files compiled under desktop environment. For instance, jtransforms
May I know why is it so? I thought the JVM from Oracle and Dalvik VM from Google uses two different byte code formats? Why the JAR file compiled by Java SE able to execute in Android?
I assume you are simply including the jar file in your android project? Then it works, as during the build process it is converted (the same is done for your own class files!) to dex format. This is done with the dex (dx) tool. Using ADT in eclipse it is automatically done for you. It's available for manual use in the android sdk of course too:
Under android-sdk-windows\platform-tools\dx.bat if on windows.
According to wikipedia, dx is used to convert compiled .class files into the .dex format.
1. Java SE - Java (Swing + AWT) = Android
2.In 2005, when Java was undergoing changes, Android creator didnt wanted to base Android
totally on Java. So they included JVM as the 1st compilation unit, thats the reason
JRuby , Jython, etc can be used to write Android apps. And 2nd Compilation unit as Dalvik
Compiler.
3. So its quite natural that a jar file compiled under desktop environment works fine on Android.

Categories