Creating a Native OSX Executable for Java from Windows - java

I have a program written in java that I'd like to provide native-style wrappers for. My target platforms are OSX, Windows, and Linux.
I have Windows and Linux working "good enough" right now. It'd be nice to provide a windows installer, a linux rpm, and a linux .deb, but for now I'm relatively satisfied with the package I provide to the user on those two platforms. I think it is relatively intuitive, feels native, and is easy to use.
For Windows
I use launch4j to create a native executable.
I package the native executable, jars, stripped JRE, and resource files in .zip
The user downloads the zip, extracts the folder inside, and double clicks the executable.
While this method doesn't have an installer, I feel it's "native-enough".
For Linux
I have a simple C++ program serving as a native 32-bit executable, which launches java targeting my jar file.
I package the native executable, jars, stripped JRE, and resource files in .tar.gz
The user downloads the .tar.gz, extracts the folder inside, and double clicks the executable (or calls it from the console).
While I think it would be nice to distribute via .rpms and .debs, and to provide native icon support for at least KDE and gnome, I'm also happy with this result for the time being.
Here is the native executable code, for anyone who is interested.
/*Compile this on a linux machine to create a local nix executable
g++ -m32 -o executable-name this-file-name.cpp
-m32 forces 32 bit mode, which should help compatibility
*/
#include <stdio.h>
#include <cstdlib>
int main() {
int result = system( "java -jar TARGET_JAR.jar 2> /dev/null > /dev/null " );
if ( result != 0 ) {
printf ( "PROGRAM_NAME requires Java, but Java isn't in your path. Please make sure Java is installed and 'java' is visible in your path. Once you've done that, please run this executable to run PROGRAM_NAME!\n" );
}
}
I intend to modify this for the upcoming release to also use an embedded jre, but that is a trivial change.
For OSX
I don't have a working system yet. Here is what I'd like:
User downloads a .dmg file, which contains an .app.
I'd like for the .app to:
Have an embedded JRE
Be double clickable
Build can be automated with ANT.
My previous attempts at creating this app failed miserably. I tried:
Appbundler: I could not get the examples to work. I believe the source of the problem was working in a windows environment, but perhaps I was just doing things wrong.
Rolling my own .app: This failed, as you can see in the thread.
javapackager (included with java 8): I similarly could not get this to work. As it's a new tool, there is a sparsity of examples in the wild, and the tool seems immature and focused on webstart; the windows installer I got when trying to create the native windows package was primitive and I could not get it to include other non-jar resources.
webstart: I don't want .jnlps. I can't have icons or embedded jres.
I feel like there should be an easy way to roll my own .app. As far as I can tell, apps are just directories with special structures and a Info.plist.
However, I'm open to any suggestions that work. In the end, as long as I get a package that feels native on OSX and can be automated with ANT, I'll be very happy.
Thank you!

You will need a Mac computer with Xcode installed in order to do this.

Related

Decide GNU or MUSL build of linux in Java

I have a Java desktop application which is supposed to run in both GNU Linux distributions (Debian and Ubuntu) and MUSL Linux distributions (Alpine). My application uses a native library also and native library build is different for both type of Linux distributions.
I will deliver both with my application in different folders. So at runtime Java program needs to pick the right distribution of native library to pick as per Linux (GNU or MUSL).
I don't find any mechanism to know that in the Java program, which Linux distribution JVM is running on.
One way I was thinking to read the OS file from /etc/ folder of Linux. But I don't think it would be a good solution (as some custom build might change this details), can someone suggest some better solution for this problem? Or how this can be done?
Using Java/JNA, you can map the gnu_get_libc_version() function and attempt to execute it after loading libc. If it works, you're on glibc (GNU). If you get an UnsatisfiedLinkError that the function is not found, you're on some other libc.
Map the function:
public interface Libc extends Library {
Libc INSTANCE = Native.load("c", Libc.class);
String gnu_get_libc_version();
}
Call it:
public class GnuOrMusl {
public static void main(String[] args) {
try {
System.out.println("On GNU libc version " + Libc.INSTANCE.gnu_get_libc_version());
} catch (UnsatisfiedLinkError e) {
System.out.println("Not on glibc!");
}
}
}
There may be similar approaches with a unique function to distinguish other libc variants from MUSL, but as far as I'm aware, MUSL attempts to be so standards-compliant that it doesn't really allow identifying itself.
Another option for finding GNU distributions is the uname -o command that you can execute with a ProcessBuilder.
On non-GNU (Alpine) it is just "Linux" while on Ubuntu, Debian and OpenSUSE it is "GNU/Linux".
You may also have success determining GNU vs. MUSL by iterating /lib* directories looking for libc variants. This is similar to the approach taken when compiling the JDK, which executes the ldd command and parses libraries from that output.
For example, iterating the /lib directory in Alpine linux gives this link: libc.musl-x86_64.so.1 -> ld-musl-x86_64.so.1
In Debian /lib32 has libc.so.6 -> libc-2.28.so, and in OpenSUSE /lib64 I see something similar: libc.so.6 -> libc-2.26.so, and Ubuntu /lib/aarch64-linux-gnu has libc-2.27.so.
If you stay within Java, determining which /lib path to search may require some trial-and-error. Parsing the output of a command line such as ldd `which ls` will likely get you a string containing gnu or musl.
As far as determining which Linux Distribution to use, reading from an /etc folder is a good intuition. I manage the Java-based Operating System and Hardware Information (OSHI) project, and went through pretty much all the options to identify which distribution you are running. You can see the results of all that labor in this class.
I'll quote a comment in that file:
There are two competing options for family/version information. Newer
systems are adopting a standard /etc/os-release file:
https://www.freedesktop.org/software/systemd/man/os-release.html
Some systems are still using the lsb standard which parses a variety
of /etc/*-release files and is most easily accessed via the
commandline lsb_release -a, see here:
https://linux.die.net/man/1/lsb_release In this case, the
/etc/lsb-release file (if it exists) has optional overrides to the
information in the /etc/distrib-release files, which show:
"Distributor release x.x (Codename)"
The code's logic goes:
Attempt /etc/system-release
Attempt /etc/os-release
Run lsb_release command
Read /etc/lsb-release
Look for and read any /etc/*-release file.
Those files contain keys like NAME that help you out.
Feel free to copy and use that file or a variant, or just use that project as a dependency.
You can detect which Linux Distribution is running by following this StackOverflow answer
Unfortunately there aren't so many alternatives to detect if you are running on MUSL or GLIBC

How to execute Carrot2 Document Clustering server

I downloaded the Carrot2 Document clustering server build 3.15.0 for Mac. The read me file says:
The DCS requires a Java Runtime Environment (JRE) version 1.7.0 or later. To
run the DCS, execute the 'dcs' script and point your browser at
http://localhost:8080 for further instructions.
Mac OS Sierra doesn't make it easy, but I got 1.8.0_112 installed.
The problem is that I don't know how to execute the 'dcs' script.
There are .cmd, .sh, .war, and .jar files. I wasn't sure which of those to work with. I thought .jar looked promising, so I followed some of this thread and tried this in a terminal window:
java -jar invoker.jar
I cd-ed to the correct directory, but it just says Provide main class, but I'm not sure what or where that is.
Can anybody provide instructions or a link to how to do this?
Use the dcs.sh (on Linux/Mac) and dcs.cmd (on Windows) to start the server. The scripts will set some extra options for the JVM and then start the DCS. In case of any problems, append the -v option to see diagnostic output.

Automated testing of InstallAnywhere wizard

I need to automate installation process of some product, but it has to be exactly installation through passing InstallAnywhere wizard (it's kinda GUI testing of installation process, so silent install won't work).
Any suggestion how to do this?
I guess the main problem is that installation file (*.exe) is just extractor which extract required files to temp folder and then run java application.
You may try pywinauto to test it on Windows. Java part of the installer may require new "UIA" back-end which will be released in March. For early testing you may try the following steps:
Install pyWin32 and comtypes by pip install pypiwin32 and pip install comtypes.
Install UIA branch of pywinauto by python setup.py install.
Try the following code:
import pywinauto
pywinauto.backend.activate('uia')
app = pywinauto.Application().start('your_installer_path.exe')
app.ApproximateMainWindowName.Wait('ready', timeout=15)
app.ApproximateMainWindowName.PrintControlIdentifiers()
PrintControlIdentifiers output is a hint for further steps. There are possible access names for the controls on the window. Only basic functionality like ClickInput() and TypeKeys('something') should work for now.
Available methods for the control can be advised here:
app.MainWindow.OKButton.WrapperObject(). # methods list can be displayed here in IDLE or Visual Studio Python Tools
app.MainWindow.OKButton.WrapperObject().ClickInput() # code for debugging
#app.MainWindow.OKButton.ClickInput() # it works the same way, for production code
Feel free to ask more help if something doesn't work.
Python scripts may require running as Administrator to have an access to the GUI. Or add manifest for python.exe with uiAccess="true".

Running a project with shell commands

I need to open a project which I think it is written in linux or need linux env for building it.
I use Win8 and I'mnot familiar with Linux env anymore.
Iin it's README file, it is written s.th like this:
HOW TO INSTALL
> tar xzvf DepOE-beta.tar.gz
> sh install-DepOE.sh
Two NLP tools are installed:
- DepPattern (dependency-based parser)
- Tree-Tagger (PoS tagger)
Pay attention: do not install the package in a directory whose name contain blank spaces!
HOW TO USE
depOE.sh <tagger> <lang> <file> [parser]
tagger=freeling, treetagger
language=gl, es, en, pt, fr
file=path of the input file
I opened it by Eclipse env which is integrated with Perl. but I couldnt open it.
what should I do??
please help me:(
since the usage file specifically says that you need to run
depOE.sh <tagger> <lang> <file> [parser]
I believe you will need some sort of UNIX shell to make it work. Moreover from the file tree you posted I believe you will also need a running Perl implementation on your machine. Please refer to http://slu.livejournal.com/17395.html for a tutorial on how to install Cygwin and Perl for Windows. Cygwin should give you some basic Linux/Unix/GNU tools for Windows environments and Perl obviously is a Perl interpreter for Windows.
However, I believe in your case the option to run a real Linux operating system in a virtual environment (if you want to keep your Windows installation untouched) is the best way to go. The fastest way (and a free option) would be to download VirtualBox from https://www.virtualbox.org and a Linux VM for instance with Ubuntu preinstalled from here http://virtualboxes.org/images/ubuntu/.

creating 100% standalone executable jar that doesn't require the java command

so apparently if you create an executable jar, in order to run it you still need the java command:
java -jar something.jar
but what if I just want it to run without the java command, so just directly from the command line
something.jar
is there a way to export my java app in eclipse in order to accomplish such
On Unix systems you can append the jar file at the end of an executable script.
On Windows you have to create a batch file.
For instance in Unix:
$cat HelloWorld.java
public class HelloWorld {
public static void main( String ... args ) {
System.out.println("Hola mundo!");
}
}
$cat M.mf
Main-Class: HelloWorld
$cat hello
#!/bin/sh
exec java -jar $0 "$#"
$javac HelloWorld.java
$jar -cmf M.mf hello.jar HelloWorld.class
$cat hello.jar >> hello
$chmod +x hello
$./hello
Hola mundo!
In windows you have to create a batch file like:
::hello.cmd
javaw -jar hello.jar
Which has the same effect.
On Windows and OSX you can double click on the jar to run it, I'm pretty sure you may add a trigger on Linux too.
I hope this help
Excelsior JET - http://www.excelsior-usa.com/jet.html - claims to compile to native code and bring its own runtime support, so it does not require an existing JVM. Commercial product.
I have not tried it myself, but they have spent quite a bit of effort over the years to market JET as a great deployment method for precompiled binaries.
Also note that if you have an executable/runnable jar which works fine with "java -jar someting.jar" and you just want to be able to invoke it in a more convenient way, this is the job of the program accepting your command and launching the java command.
For Linux you can frequently add an alias saying that "something" expands to "java -jar something.jar", and some command interpreters allow for saying that all commands ending with jars should be executed specially. The exact details depend on which shell (command line interpreter) you are using.
What you need is a tool called 'Java Executable Wrapper'.You can use it to Pack all your class files to a Single Executable Package.
The One i recomment is launch4j,you can download it from sourceforge launch4j.sourceforge.net
Launch4J can be used to create standalone Executables (.exe) from a jar file for windows Environment.
The thing is, that Java gets interpreted by the JVM, so you'll at least need to ship it with your app.
To be a little more specific about this, Java gets kind of compiled to byte-code so it can be interpreted faster. But the Byte-Code can't run without the JVM. This is the nice side of Java: You don't need to recompile your Apps to run on other platforms like Linux or OS X, the JVM takes care of that (as it is written in native code and is recompiled for those platforms).
There are some compilers out there which can convert your Java code to something native like C which can then be executed without the JVM. But this isn't the idea behind Java and most of those tools suck at what they do.
If you want your App to run without any interpreter, you'll need to use a compiled language like C or C++
Java program runs on a JVM, for the first question I don't think there's a compiler that can do the job well. For the second question since a jar file is not an executable per se, there must be some sort of settings in the target machine, "executing" a jar file without providing the java command is a matter of convenience for the user. On Windows every file extension has a program associated with it, so .doc documents have (usually) Word as the program associated -that setting is set by the office installer, the java runtime also sets the setting for .jar files when you install it, but behind the scenes, java command will be used by the system. So the short answer to the second question is: depends on the target machine.

Categories

Resources