From my previous question, I know that JavaFX is not supported in RedHat 5.8 meaning, even when I have Java 8 (jdk1.8.0_05) installed on my Linux, a JAR file created in win7 can't be executed via java -jar helloworld.jar. Does that mean there is NO way to run JavaFX jars on this machine?
The problem with running JavaFX applications on RHEL5 is the version of glib that comes with that OS is not new enough. The trick, then, is to provide a newer version of that library and all of the other libraries that depend on it to the JRE. The next hurdle is that RHEL5 shared library loader won't load those libraries. You have to use a compatible loader. But the JVM has the path to the loader hard-coded in the executable! So you need a separate JVM with a custom loader path patched in. Roughly, the steps to get this working are...
Unpack the following packages from RHEL6:
glib2
libffi
glibc
glibc-common
zlib
gtk2
pango
cairo
pixman
Put all of the shared libraries from those packages in a directory on your RHEL5 system. Let's call it /YOUR-ALIEN-RHEL6-LIBS-PATH.
Unpack another copy of a JRE to, say, /YOUR-ALIEN-JVM-PATH.
Use patchelf to point the JVM executable to the new loader.
./usr/bin/patchelf --set-interpreter /YOUR-ALIEN-RHEL6-LIBS-PATH/lib/amd64/ld-linux-x86-64.so.2 /YOUR-ALIEN-JVM-PATH/jre1.8.0_25/bin/java
Run the application after setting LD_LIBRARY_PATH=/YOUR-ALIEN-RHEL6-LIBS-PATH/lib/amd64:/YOUR-ALIEN-RHEL6-LIBS-PATH/lib/amd64/jli
Although it is not pretty, I have successfully run JavaFX applications on RHEL5 using this method. Having said that, I highly recommend just upgrading your OS if it is even remotely feasible.
Note this builds upon the existing answer from James with more concrete detail
Obtain RPMs from a RedHat 6.x, e.g. http://vault.centos.org/6.2/os/i386/Packages. Copy into directory rpms/
cairo-1.8.8-3.1.el6.i686.rpm
glib2-2.22.5-6.el6.i686.rpm
glibc-2.12-1.47.el6.i686.rpm
glibc-common-2.12-1.47.el6.i686.rpm
gtk2-2.18.9-6.el6.centos.i686.rpm
libffi-3.0.5-3.2.el6.i686.rpm
libXcomposite-0.4.1-2.el6.i686.rpm <== not mentioned in other answer
pango-1.28.1-3.el6_0.centos.5.i686.rpm
pixman-0.18.4-1.el6_0.1.i686.rpm
zlib-1.2.3-27.el6.i686.rpm
libXdamage-1.1.2-1.el6.i686.rpm <== not mentioned in other answer
Extract all the contents from the RPMs into separate directory. Use rpm2cpio and xzcat. xzcat can be installed from these RPMs if necessary [xz, xz-libs, xz-lzma-compat]
mkdir redhat-6u2-libs
cd redhat-6u2-libs/
ls -1 rpms/* | xargs -i{} bash -c "rpm2cpio {} | xzcat | cpio -idmv"
Obtain copy of patchelf. I built from source as couldn't find a Redhat 5 RPM. Only requires dependent RPMs [gcc, gcc-c++, glibc-devel, kernel-headers, libstdc++-devel]
wget https://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.bz2
tar xjf patchelf-0.9.tar.bz2
cd patchelf-0.9
./configure --prefix /tmp/patchelf
make install
Use patchelf to set location of redhat 6u2 loader (aka interpreter)
/tmp/patchelf/bin/patchelf --set-interpreter ~/redhat-6u2-libs/lib/ld-linux.so.2 jdk1.8.0_40/bin/java
Set LD_LIBRARY_PATH, this needs to have both /usr/lib and /lib, otherwise you get a segfault.
export LD_LIBRARY_PATH=/home/user/redhat-6u2-libs/usr/lib:/home/user/redhat-6u2-libs/lib
(Note that any other applications run after LD_LIBRARY_PATH is set other than java which has had its interpreter location corrected will segfault.)
Now run java app...
./jdk1.8.0_40/bin/java -cp etc...
Happy days
Related
VSCode, Java 11 JavaFX 18.0.2
I am trying to package my code up for distribution as a desktop app. In my case I want a fully self-contained app because of my target user's profile.
I have been through Jenkov add the Oracle docs here and here which suggest I need ant-javafx.jar. That jar file seems to have been dropped from the standard Java SDK some time around Java 7 and put into the regular JavaFX install lib folder.
It's not there in the build I have.
JavaFX seems to have gone to openjfx.io and nowhere in there can I see support for the ant packaging jar. In fact I see openjfx as a retrograde step as they are increasingly forcing everyone into paid plans (try going round and round the loop of downloading anything that doesn't require an LTS payment).
I have a suspicion that there is some silent assumption that everyone will use something from maven or gradle, and maybe the packaging tools are buried away in one of those build tools. For historical reasons I don't use either and it should be possible to do this packaging without one of them.
So where do I get the JavaFX Ant build tasks from without having to pay someone?
I have found that the following works as an alternative with Java 19 and OpenJFX 19. I use the maven-dependency-plugin to copy all the dependency jars (excluding JavaFX, which I use as modules from a "full" JDK [one that includes JavaFX)] into the target/lib directory.
#!/bin/bash
set -o errexit
set -o noclobber
set -o xtrace
# find dependency modules of required modules
DEP_MODS=$(jdeps -quiet --class-path "target/lib/*" --add-modules java.base,java.logging,java.sql,javafx.controls,javafx.fxml --multi-release base --ignore-missing-deps --print-module-deps target/myapp-4.0-beta.jar)
# create a modular runtime image
jlink --compress=1 --no-header-files --no-man-pages --add-modules "java.logging,java.sql,javafx.controls,javafx.fxml,$DEP_MODS" --output target/myapp-4.0-beta
# Example of running it out of the runtime image
# TEST target/myapp-4.0-beta/bin/java -cp "../../myapp-4.0-beta.jar:../../lib/*" org.myapp.App
# symlink to the artifact jar from the lib directory
$(cd target/lib && ln -s ../myapp-4.0-beta.jar)
# use the lib directory and modular runtime image as input to jpackage
jpackage --input target/lib --runtime-image target/myapp-4.0-beta --main-jar myapp-4.0-beta.jar --main-class org.myapp.App --type app-image --app-version 4.0 --name app --dest target/dist/bundle --mac-entitlements src/dist/mac/entitlements.plist
We have some smaller libraries we use in our bigger project quite often.
Still we compile and run the unit tests of these smaller libraries as independent CI Jobs.
Most of these libs use QMake as buildtool, not using Qt in any way. And we started to move our CI-Jobs into docker containers. Now I realized that I always have to get qt5-default (on Ubuntu 16) for qmake to work. Is this intended? This gives quite a signifacant overhead. Does anybody know a way, to use qmake on Ubuntu 16 wihtout getting the whole Qt instalation on board?
You don't actually need Qt installed for qmake to work. The reason why you need qt5-default is that most linux distributions provide both Qt5 and Qt4, which have the same binaries, for example they both have a version of qmake, which would both get installed to /usr/bin. In order to fix that problem Qt5 installs to /usr/lib/.../qt5 and Qt4 to /usr/lib/.../qt4, and the qt5-default package creates symlinks from there to /usr/bin
For Ubuntu , ... is x86_64-linux-gnu!
You can choose between:
Install only the qt5-qmake package in your docker container and create a symlink /usr/bin/qmake -> /usr/lib/.../qt5.*
Specify the full path to the qmake binary when building your software, inside your {travis, gitlab, jenkins} CI config
Add /usr/lib/.../qt5/bin to your $PATH
* The proper place for a manually created symlink would actually be /usr/local/bin because if you have the symlink in /usr/bin, installing qt5-default package would fail because the symlink qt5-default wants to create would already exist. However, you are in a docker container and can actually control whether qt5-default gets installed, and if you create the symlink in /usr/local/bin you have to make sure to add /usr/local/bin to your $PATH, which is overkill for that scenario.
I have made an application using QtWebKit, Qt4. I have the binary generated in Fedora 16. Now, I want to run that application on another PC (running some other Fedora version), where Qt is not installed. How can I package my Qt application so that it can run on a platform where Qt is not installed? Is there any command line utility as well as QtCreator utility to do so. I have tried "deploy all" command, but it didn't have any affect.
Create an Installer with the Qt Installer Framework and just supply all needed shared libraries (Win/OSX) or compile statically. Under Linux there is always the problem between system-wide libraries or bundled libraries. The documentation https://qt-project.org/doc/qt-5.0/qtdoc/deployment.html should give you a good start
Obviously, you need to have access to the qt libraries, which are exactly the same version that you used to compile your application.
There are two options :
link qt libraries statically
create a RPM package (see this how)
Also check Deploying Qt Applications.
Since you're deploying using rpm, to systems where Qt 4 rpms are available, you don't need to do anything besides simply adding a dependency on the qt to your rpm's specfile. The user installing your package using yum localinstall will get the Qt dependencies automatically installed. That's the correct way of doing it - it will keep your package size small.
Of course you need a separate rpm build for every fedora/centos major version out there, but that's almost always a requirement.
If your package needs newer Qt version than the one provided by the platform packages, you can still make a specific version dependency (say qt >= 4.7.0) and have a readme that indicates that newer packages can be obtained from a 3rd party repository (epel etc.)
For deployment under Linux I've used Bitrock Installer Tool.
The main thing before deploying is to check your dependencies. You can do that by using command:
ldd appName | grep libQt
After that you'll see list of dependencies. You'll have to set environment variable LD_LIBRARY_PATH to let linker know where're your libraries. To do that:
export LD_LIBRARY_PATH=.
. means current directory
And after that:
./appName $*
After that you'll be able to use your executable with Bitrock Installer Tool.
I use qt-creator 5.2 and install qwt6.1.0 on the mac os 10.9. I follow the guide,and install the qwt6.1.0 success.
I use these cmd:
cd $QwtDir
qmake -spec macx-g++
make
sudo make install
sudo ln -s /usr/local/qwt-6.1.0/lib/qwt.framework/qwt /usr/lib/qwt
But when I compile the program, It occurs this problem:
dyld: Library not loaded: qwt.framework/Versions/6/qwt
what should I do?
I finally found the Solution: Just copy the qwt.framework to the Libary/Frameworks Folder and everything should work from now. I was looking for like 3 Hours for finding the right solution after reinstalling everything etc. Hope this helps.
From the Mac Developer Library:
Third-party frameworks can go in a number of different file-system locations, depending on certain factors.
Most public frameworks should be installed at the local level in /Library/Frameworks.
If your framework should only be used by a single user, you can install it in the ~/Library/Frameworks subdirectory of the current user; however, this option should be avoided if possible.
If they are to be used across a local area network, they can be installed in /Network/Library/Frameworks; however, this option should be avoided if possible.
For nearly all cases, installing your frameworks in /Library/Frameworks is the best choice. Frameworks in this location are discovered automatically by the compiler at compile time and the dynamic linker at runtime. Applications that link to frameworks in other directories, such as ~/Library/Frameworks or /Network/Library/Frameworks, must specify the exact path to the framework at build time so that the dynamic linker can find it. If the path changes (as it might for a user home directory), the dynamic linker may be unable to find the framework.
I wanted to migrate my Qt 4 app to use Qt 5 instead. These instructions failed, due to some differences with how MXE builds Qt 5, including the fact that it uses modularised Qt tarballs, instead of one large tarball.
Here are the full instructions:
Get it:
git clone https://github.com/mxe/mxe.git
Install build dependencies
Build Qt 5 for Windows:
cd mxe && make qtbase
This will first build its dependencies and the cross-build tools;
It should take less than an hour on a fast machine with decent internet access.
Due to the new modular nature of Qt 5, various major Qt components are now in different tarballs. The one selected above, qtbase, should give you enough functionality to run ordinary GUI apps, which is all I needed for my own (smallish) app.
If you want to build all of Qt 5 instead, you'll need to run make qt5 (instead of make qtbase). Note that it will take a lot longer to complete, so be sure that you need the extra functionality.
Get to the directory of your app, and run the Qt Makefile generator tool:
<mxe root>/usr/bin/i686-w64-mingw32.static-qmake-qt5
Build your project:
make
You should find the binary in the ./release directory:
wine release/foo.exe
Some notes:
This was tested on my 64-bit Debian 8, and on Windows of course.
The output is a 32-bit static executable, which will work well on 64-bit Windows.
If you want a 64-bit executable, build Qt with:
make MXE_TARGETS=x86_64-w64-mingw32.static qtbase
The default MXE_TARGETS value is i686-w64-mingw32.static.
The git checkout command is not correct. You now have to get their stable branch or it will fail building.
git clone https://github.com/mxe/mxe.git
should be...
git clone -b stable https://github.com/mxe/mxe.git
That alone fixed all my issues with qtbase building but leaving no qt folder when done. Then qt5 target would fail with obscure errors. Deleted folder, checked out stable and it worked flawlessly.
For those who directly want a GCC10 64bit compiled Qt5 (for filesystem lib for example),
Here are the full instructions:
Get it:
git clone https://github.com/mxe/mxe.git
Install build dependencies
Build Qt 5 for Windows with gcc10 64bits plugin activated :
cd mxe && make MXE_TARGETS=x86_64-w64-mingw32.shared MXE_PLUGIN_DIRS=plugins/gcc10 qt5
After 2-3 hours of build you can build your app (in your .pro directory) :
<mxe root>/usr/x86_64-w64-mingw32.shared/qt5/bin/qmake
Export path of compiler & build your project:
export PATH=<mxe root>/usr/bin:$PATH
make
You should find the binary in the ./release directory & start it with wine (or wine64) :
wine foo.exe
I don't really know why, but I needed to add the MXE compiler directory to the wine path because it's couldn't find the DLLs :
WINEPATH="<mxe root>/usr/x86_64-w64-mingw32.shared/bin/" wine64 foo.exe
If you try to do this, for me work fine!
su
mv mxe /opt/mxe
cd /opt/mxe && make