How to launch executable embedded within Eclipse plug-in? - linux

I am building an Eclipse plug-in that have to parse the result of an executable (Linux) to display informations to the user. The executable should be embedded in the plug-in, not installed apart.
I first made a small prototype, in which I've embedded a fake executable, then before launching the executable, I extract it into a temporary file, build my command line and then launch it. That worked ok for me.
I've just received the real executable, and then realised it was not a standalone executable, but a bunch of libraries, config files and such. It comes also with a script to execute in order to set env variables.
The only option I am seeing now is to extract the whole bunch to a temp directory, set the environment variables according to the script, and then call my executable.
Is my solution valid ? Do you think of a better way to do it ?

Don't package the plugin as a jar, instead just use a directory so you don't have to do any unpacking.
You specify this using
Eclipse-BundleShape: dir
in the plugin MANIFEST.MF.
Note: if you package your plugins in a feature then this setting is overridden by the unpack="true" attribute of the plugin element in the feature.xml file.

Related

C++ executable fails to link to shared library after scp

So I am working on a project that is intended to run on a remote server. I develop the program on a local pc, compile it, then upload it to the remote server. Both the local pc and the remote server are run on CentOS 7.7.
The program is developed using the CLion IDE, configured with CMake. The program depends a few shared libraries, which are supposed to link to the executable according to what I wrote in CMake. At my local PC, I can compile and run the program perfectly. However, after I scp the whole directory of the project to the remote server, the executable fails to run. It cannot find any of the ".so" files, according to what ldd says.
This is my CMakeList.txt, with every path being relative path, instead of absolute path.
cmake_minimum_required(VERSION 3.15)
project(YS_Test)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_PATH_ src)
file(GLOB SOURCE_FILES_ ${SOURCE_PATH_}/*.*)
set(PROJECT_LIBS_ libTapQuoteAPI.so libTapTradeAPI.so libTapDataCollectAPI.so)
include_directories(api/include)
link_directories(api/lib/linux)
add_executable(YS_Test ${SOURCE_FILES_})
target_link_libraries(YS_Test ${PROJECT_LIBS_})
Please do not tell me to set LD_LIBRARY_PATH to fix my issue. The program worked fine on my local pc without LD_LIBRARY_PATH, so I expect it to run on the remote server without LD_LIBRARY_PATH. I would like to know what is really going on here, instead of a work around. Thanks!
If I understand your problem correctly, you want to ship your compiled YS_Test program along with some dependencies and have it run on a remote server. By default an executable will only look in the directories configured in /etc/ld.so, which will not include the deploy path.
Note: Typically you do not deploy your entire build directory but only the compiled artifacts and dependencies. For this answer I will assume you deploy the binary and its dependencies to the same directory.
You have two options:
Require users of your program to set LD_LIBRARY_PATH, either by themselves or by a wrapper script. This variable will instruct the dynamic linker to look in the specified directories as well. Even if you do not like this solution, it is by far the most common approach.
Add -Wl,-rpath='$ORIGIN' to your linker options. This will add a DT_RUNPATH attribute to the executable's dynamic section. As you are using CMake you can also set this using BUILD_RPATH and/or INSTALL_RPATH target properties.
The ld.so manpage describes this attribute as follows:
If a shared object dependency does not contain a slash, then it is
searched for in the following order:
...
Using the directories specified in the DT_RUNPATH dynamic section
attribute of the binary if present.
The $ORIGIN part expands to the directory containing the program or shared
object.
If you really insist on shipping your build directory (eg during development), you can take a look at the CMake BUILD_RPATH_USE_ORIGIN property (and its usual global counterpart CMAKE_BUILD_RPATH_USE_ORIGIN), this will embed relative paths into binaries instead of absolute paths.
As you don't want a workaround (#Botje has given you two already), I will try an explanation instead. In your development machine, if you use this command:
ldd YS_Test
You will see all the shared libraries used by your program, with their corresponding paths. The libTapQuoteAPI.so libTapTradeAPI.so libTapDataCollectAPI.so are found at your 'api/lib/linux' directory, but resolved with full absolute paths. If you do the same at your server, some shared objects can't be resolved because they aren't at the same location.
If you use one of these commands (not sure which are available in Centos):
chrpath --list YS_Test
or
patchelf --print-rpath YS_Test
You will see the RPATH or RUNPATH tags embedded in your program. This is the path used by the Linux linker to locate dependencies that are outside the standard ld locations. You may find extended explanations on Internet about this, like this one or the Wikipedia article.
Breaking my promise, I give you a third workaround: use patchelf or chrpath at your server after scp to change the embedded RPATH tag, pointing it relative to $ORIGIN (which represents the program location).

A file program debugged under GDB doesn't see its files

I'm trying to gdb a program under Linux. It's a compiler of a language that uses some include files (this language include files, not C/C++ includes) that get properly loaded when running the app normally. When run under gdb, the app complains that it couldn't find these include files. I've checked gdb's internal pwd, and it is exactly the same as when run stand-alone. What could be the problem? How can I fix it?
Note that this compiler doesn't use any environment variables, it gets its includes from current directory, it seems.
you can set the source directories path in gdb..
go through the source path in gdb document.
https://sourceware.org/gdb/download/onlinedocs/gdb/Source-Path.html#Source-Path

How do I deploy Qt libraries with an application?

This should be really simple, but I'm having trouble. I want to include some shared Qt libraries with my application in the installation folder so the user doesn't have to download Qt separately. On Windows, this seemed to work fine, but Ubuntu complains about not being to find the Qt libraries when they are in the same folder as the application.
How do I add the installation directory to shared library search path?
I was able to add the installation directory to shared library search path by adding the following lines to the .pro file, which set the rpath of the binary to $ORIGIN (the install folder). I needed to add the location of QT libs on my current machine (/usr/lib/qt5.5 and /usr/lib/qt5.5/lib) so that the project would build in QtCreator.
unix:!macx {
# suppress the default RPATH if you wish
QMAKE_LFLAGS_RPATH=
# add your own with quoting gyrations to make sure $ORIGIN gets to the command line unexpanded
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\':/usr/lib/qt5.5:/usr/lib/qt5.5/lib"
}
(The unix:!macx line makes it apply to linux only)
Windows, Linux and OSX behave quite differently. Windows is easiest: dump all the dll's in the application dir. OSX is next and Linux is most difficult.
Linux has certain search paths for searching shared objects. These search paths are mainly system libraries and possibly some user libraries. As you do not want to mess around with system files of your user one would prefer to have the shared objects in the application dir. This is possible but you have to tell Linux to read that directory. You can do this with setting the environment variable LD_LIBRARY_PATH. You can do this with a script. See my answer.

Running .jar File on Linux

I have a .jar file that reads two files from within its current folder and produces as output a .txt file and a separate folder with multiple other .txt files. This works perfectly in Windows using this code to create the directory:
static String dir = System.getProperty("user.dir");
I used the instructions here: https://askubuntu.com/questions/192914/how-run-a-jar-file-with-a-double-click to set up my .jar file to run on a simple double-click, but as of right now, it does nothing when double-clicked. My guess is that the above line of code does not translate well to Linux. Anybody know how to resolve this?
First, try running it on the command-line, with
java -jar <file.jar>
The user.dir property is cross-platform (see here) so it should not be the problem. However, are you using correct file separators? Remember it's '/' on UNIX and '\' on Windows.
Try java -jar Jarname.jar and pass other files as arguments after this command
The code line you gave works fine on linux.
My best guess is that you're then trying to use this directory path by adding a windows-specific path separator (like path + "\subdir") which isn't appropriate for linux (you should build a new File object instead).
Either that, or your jar file isn't being executed at all. Have you tried doing something very simple in your jar file to see if anything is being run? Have you tried running your jar with java -jar myapp.jar to see if any exceptions are thrown or error messages displayed?
You will need to manually tweak your build process to get the jar file marked as executable. In your build xml file, there is a target, "-post-jar", that is called after the jar is built. You'll need to make that target and use Ant's chmod task to modify your jar. Once you do that it will occur every time you make a jar file in that project.
It will run fine as long as you have a JRE installed.
Read this article to know more.

Overriding System Binaries With Home Directory Binaries

I'm trying to compile a piece of software in my home directory (OpenMPI). One of the build dependencies (autoconf) installed on my system is not the newer version asked for by the OpenMPI autogen script. I compiled and installed the newer version of autoconf in my home directory.
Is there anyway for the binary installed in my home directory to "override" the version installed on the system for my session?
I tried setting an alias which works via command line but not for the script used to generate the configure script.
Add the path to the binary you want to override to your $PATH environment variable.
Like PATH=/path/to/binary:$PATH ./compile
Your added path will then be looked up first when trying to find the compile command. It will only be valid for that execution and will not remain after command has returned. You can use export PATH=/path/to/binary/:$PATH and it will be saved for that session.
EDIT: As Eric.J states, you can use which compile which will output the path to the command, just to make sure it's the right one.
You can change the PATH environment variable so that your home directory appears before the system directory, e.g.
PATH=$HOME/bin:$PATH
You can then use the which command to ensure the correct binary is being picked up.

Resources