How to debug Qt dll issues with cross compiled builds? - c++

After cross-compiling Qt 5 applications (host: Fedora 19/64 bit, target: Windows 32 bit) I execute following steps for deploying the executable:
$ DEST=/windows/testdir
$ cp /usr/i686-w64-mingw32/sys-root/mingw/bin/*.dll $DEST
$ mkdir $DEST/platforms
$ cp /usr/i686-w64-mingw32/sys-root/mingw/lib/qt5/plugins/platforms/qwindows.dll\
$DEST/platforms
$ cp release/main.exe $DEST # the cross-compiled Qt5 binary
I test it on Windows like this:
say /windows is mounted on f:
start command prompt window
f:
cd testdir
main
And there I get:
Failed to load platform plugin "windows". Available platforms are:
Microsoft Visual C++ Runtime Library
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
I don't really believe the first message because:
a) the above steps worked in the past (executed on the same Fedora 19 system)
b) the platforms directory is there as documented in the qt docs.
What changed is that now the application includes some PNGs/JPGs in dialogs (read via Qt's resource file system, as QIcons).
Thus, I've also copied some plugins:
$ cp -r /usr/i686-w64-mingw32/sys-root/mingw/lib/qt5/plugins $DEST
Which didn't help to resolve the above issue.
Conclusion
Is there a way to debug dynamic runtime linker issues like these?
Can I instruct it such that I somehow get output on which dll's the app/linker tries to load and where is does its lookups? (and why they fail ...)
For example something like this would be great:
ldd: main.exe -> load of foo.dll in work-dir failed (no such file)
ldd: main.exe -> load of bar.dll in work-dir/platforms failed (wrong file format)
ldd: main.exe -> load of baz.dll in work-dir successful
...
Compile steps
I used following steps for cross-compiling on Fedora 19:
$ mingw32-qmake-qt5 main.pro -o win32.mf
$ mingw32-make -f win32.mf
$ # -> binary is created in release/main.exe
Wine
I've looked at wine for testing purposes. It is helpful because it displays an error message when it can't find a DLL, e.g.:
$ wine $DEST/main.exe
err:module:import_dll Library libEGL.dll (which is needed by L"Z:\\usr\\i686-w64-mingw32\\sys-root\\mingw\\lib\\qt5\\plugins\\platforms\\qwindows.dll") not found
err:module:import_dll Library libjpeg-62.dll (which is needed by L"Z:\\usr\\i686-w64-mingw32\\sys-root\\mingw\\lib\\qt5\\plugins\\imageformats\\qjpeg.dll") not found
Interestingly, it directly finds the platforms library and needed plugin under Z:\\usr\\i686-w64-mingw32\\sys-root\\mingw\\lib\\qt5\\.
But when all needed DLLs from /usr/i686-w64-mingw32/sys-root/mingw/bin/*.dll are copied to $DEST, wine runs the same main.exe just fine - where on native windows (7) I get the above error boxes.

You can use tools like Dependency Walker for checking dependencies of a single DLL, Wine for quickly checking startup on the compile-host and Process Monitor to see which directories/files are accessed during runtime of the process.
It also makes sense to debug-output the library path from the Qt application, e.g.
int main(int argc, char **argv)
{
qDebug() << "Library paths: " << QApplication::libraryPaths();
QApplication app(argc, argv);
...
With that I get following output on native windows:
Library paths: ()
(To enable qDebug() statements - even with release binaries - you have to add CONFIG += console to your qmake project file.)
Looking at the Process Monitor output it seems that the binary does not try to open any plugins (platforms or other) in its current working directory (CWD) nor in its base directory.
When I extend the library path the binary finds all needed plugins in its CWD:
int main(int argc, char **argv)
{
QApplication::addLibraryPath(QDir::currentPath());
QApplication app(argc, argv);
...
I don't know if this qualifies as a work-around - perhaps one is supposed to do something like this. But the Qt documentation seems to suggest opposite:
To deploy the application, we must make sure that we copy the relevant Qt DLL (corresponding to the Qt modules used in the application) and the windows platform plugin as well as the executable to the same directory in the release subdirectory.
The complete deploy procedure is now:
$ cp /usr/i686-w64-mingw32/sys-root/mingw/bin/*.dll $DEST
# copying platforms, imageformats etc. plugin directories:
$ cp /usr/i686-w64-mingw32/sys-root/mingw/lib/qt5/plugins/* $DEST -r
$ cp release/main.exe $DEST
(Depending on what packages are installed on your compile-host you probably don't need to copy all DLLs - with wine it is easy to start a fixpoint iteration for all needed non-plugin dlls.)
Missing non-platform plugins don't necessarily abort the programs startup - e.g. without a jpeg plugin some icons are just not displayed.

Related

Method names changes in libstandalonelibwebviewchromium.so after build

I am using libstandalonelibwebviewchromium.so in my android application and when I am calling a native method it throws "java.lang.UnsatisfiedLinkError: No implementation" . I have looked into this issue and found out that name of the function is different in the library. I have used "nm -gD libstandalonelibwebviewchromium.so" command to list all the methods. For example :
method "org_chromium_base_library_1loader_LibraryLoader_registerNonMainDexJni" changed to "Java_J_N_MIOj213u".
How to configure chromium at the build time to preserve original library method name??
Please help....
Thank You,
Avishek Nath
//////////////////////////////////
EDIT
/////////////////////////////////
For the Android Chromium source checkout I have followed this link :
https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md
I have checked out Chromium source code for Android from github.
Then I ran these commands in ubuntu system
$ gclient sync
$ gn gen --args='target_os="android" target_cpu="arm" is_debug=false' out/Default
$ ninja -C out/Default webview_instrumentation_apk
After these command execution "libstandalonelibwebviewchromium.so" generated in the out/Default folder.
I have taken the libstandalonelibwebviewchromium.so in my project and kept it in the jniLibs folder.
I also ran this "nm -gD libstandalonelibwebviewchromium.so" command which gave a list of symbols but all of them are like "Java_J_N_MIOj213u".

Gradle Cpp-Application not detecting gcc in windows

I am starting to get into c++ more and I have began learning gradle to use as the build too for it. I am using gradle's cpp-application plugin for compiling the code. However when I try to build it gradlew tells me that it can't detect gcc, my only installed compiler.
I have for the most part followed the guide on gradle's website (https://guides.gradle.org/building-cpp-executables/). That is where I came up with most of the code so far.
I have gcc from ming-w32 installed in my path correctly (I can run it from the command prompt and through make without any issues)
I am also using a gradlew install that was made with gradle 5.2.1
I am, for the most part, using the exact setup in the gradle guide.
apply plugin : 'cpp-application'
application {
baseName = "test"
}
^ /$Project/build.gradle
This is the command line output when i run gradlew assemble
* What went wrong:
Execution failed for task ':compileDebugCpp'.
> No tool chain is available to build C++ for host operating system 'Windows 10' architecture 'x86-64':
- Tool chain 'visualCpp' (Visual Studio):
- Could not locate a Visual Studio installation, using the command line tool, Windows registry or system path.
- Tool chain 'gcc' (GNU GCC):
- Could not determine GCC metadata: failed to execute gcc.exe -m64 -dM -E -v -.
- Tool chain 'clang' (Clang):
- Could not find C++ compiler 'clang++' in system path.
When I run the command that they say failed to execute in the same command prompt (gcc.exe -m64 -dM -E -v -.)
I do get output from gcc without any errors that I can see
If you are curious on what it outputs you can find it here
I would expect that the issue isn't with my cpp code because it isn't ever recognizing the compiler but it is fairly short so I might as well.
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Hello World!!" << std::endl;
return 0;
}
^ /$Project/src/main/cpp/main.cpp
By default, Gradle tries to locate a tool chain that matches your system's architecture (x86_64), but you only have a 32-bit MinGW
A workaround is to explicitly configure a 32-bit target in your Gradle script:
application {
targetMachines = [ machines.windows.x86 ]
}

How to install GMP Mp on windows? (C++)

I've followed every single guide I could possibly find but to be completely honest I have no idea what some installation 'steps' even mean.
I tried installing Cygwin (and MYSY) and running the commands that the guides told me to, but the terminal either doesn't do anything or it gives me the error: 'no such file or directory'. (I changed the folder directory to where my files where)
Also I'm not entirely sure I installed everything correctly because I should've checked some add-ons during the installation right? I did as in the guide but still I maybe missed something...
Could someone please explain to me step by step how to install it saying explicitly all that has to be done, (I'm running windows 7) considering It's the first time I do such thing and I have no idea what ./configure , make and all the other commands even mean...
The following is a simple step by step using only cygwin tools.
To compile C++ we need the g++ compiler; to locate the correct package to be installed the cygwin tool is cygcheck (that is installed by default), with the -p switch it interrogates the database at https://cygwin.com/packages/:
$ cygcheck -p bin/g++
Found 3 matches for bin/g++
gcc-g++-7.3.0-1 - gcc-g++: GNU Compiler Collection (C++)
gcc-g++-7.3.0-2 - gcc-g++: GNU Compiler Collection (C++)
gcc-g++-7.3.0-3 - gcc-g++: GNU Compiler Collection (C++)
so we need the gcc-g++ package.
To install it, we run the cygwin setup, select the Full view, search the gcc-g to filter the thousands of packages and click on skip at the gcc-g++ row
after complety the installation, to verify we have it correctly installed:
$ cygcheck -c gcc-g++
Cygwin Package Information
Package Version Status
gcc-g++ 7.3.0-3 OK
Installing gcc-g++ will pull also the installation of the C compiler package gcc-core.
To compile a gmp program we need the proper header and shared library; that are usually included in a "*-devel" package:
$ cygcheck -p include/gmpxx.h
Found 9 matches for include/gmpxx.h
libgmp-devel-6.1.0-3p1 - libgmp-devel: Library for arbitrary precision arithmetic (development) (installed binaries and support files)
libgmp-devel-6.1.1-1 - libgmp-devel: Library for arbitrary precision arithmetic (development) (installed binaries and support files)
libgmp-devel-6.1.2-1 - libgmp-devel: Library for arbitrary precision arithmetic (development)
mingw64-i686-gmp-6.0.0a-2 - mingw64-i686-gmp: Multiple Precision arithmetic library for Win32 toolchain (installed binaries and support files)
...
All the packages with mingw64 are for cross compiling and we can ignore, so it is libgmp-devel. Verifying that is properly installed
$ cygcheck -c libgmp-devel
Cygwin Package Information
Package Version Status
libgmp-devel 6.1.2-1 OK
And the package content is the header files and the import libraries
$ cygcheck -l libgmp-devel
/usr/include/gmp.h
/usr/include/gmpxx.h
/usr/lib/libgmp.dll.a
/usr/lib/libgmpxx.dll.a
Now we can program one example, I am taking it from
https://gmplib.org/manual/C_002b_002b-Interface-General.html
and written in a file called mpz_add.cpp
You can use whatever editor you want. The important is that the file follows
the Unix line termination standard LF and not the Windows CR+LF (see note below if not)
$ file mpz_add.cpp
mpz_add.cpp: C++ source, ASCII text
$ cat mpz_add.cpp
#include <gmpxx.h>
#include <iostream>
using namespace std;
int main (void)
{
mpz_class a, b, c;
a = 1234;
b = "-5678";
c = a+b;
cout << "sum is " << c << "\n";
cout << "absolute value is " << abs(c) << "\n";
return 0;
}
To compile our example and test it:
$ g++ mpz_add.cpp -lgmpxx -lgmp -o mpz_add
$ ./mpz_add
sum is -4444
absolute value is 4444
We can also verify which library are linked in the program mpz_add, I added some extra comment:
$ cygcheck ./mpz_add
D:\cyg_pub\tmp\gmp\mpz_add.exe
D:\cygwin64\bin\cygwin1.dll <= cygwin library
C:\WINDOWS\system32\KERNEL32.dll <= windows system library
C:\WINDOWS\system32\ntdll.dll ...
C:\WINDOWS\system32\KERNELBASE.dll ...
D:\cygwin64\bin\cyggmp-10.dll <= GMP C library
D:\cygwin64\bin\cyggmpxx-4.dll <= GMP C++ library
D:\cygwin64\bin\cyggcc_s-seh-1.dll <= C library
D:\cygwin64\bin\cygstdc++-6.dll <= C++ library
If the file has the wrong line termination, the best tool is d2u (Dos to Unix)
$ cygcheck -p bin/d2u
Found 6 matches for bin/d2u
...
dos2unix-7.4.0-1 - dos2unix: Line Break Conversion
$ file mpz_add.cpp
mpz_add.cpp: C++ source, ASCII text, with CRLF line terminators
$ d2u mpz_add.cpp
dos2unix: converting file mpz_add.cpp to Unix format...
$ file mpz_add.cpp
mpz_add.cpp: C++ source, ASCII text
As you added also the tag makefile and autotools, the first is in the package make:
$ cygcheck -p bin/make.exe
Found 6 matches for bin/make.exe
..
make-4.2.1-2 - make: The GNU version of the 'make' utility
The second is more complex and you need the packages autoconf automake and libtool,

How to use LibVLC with Qt 5

I'm trying to use LibVLC in a Qt 5 program to open a VLC instance and play a video.
The following code comes from https://wiki.videolan.org/LibVLC_Tutorial/
I'm using Linux.
.pro :
TEMPLATE = app
TARGET = projectLoic
INCLUDEPATH += . vlc
QT += widgets
# Input
HEADERS +=
SOURCES += main.cpp
LIBS +=-lvlc
main :
#include <vlc/vlc.h>
#include <QApplication>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
libvlc_instance_t * inst;
libvlc_media_player_t *mp;
libvlc_media_t *m;
// Load the VLC engine
inst = libvlc_new(0, NULL);
// Create a new item
m = libvlc_media_new_path (inst, "/home/........mp3");
// Create a media player playing environement
mp = libvlc_media_player_new_from_media (m);
// play the media_player
libvlc_media_player_play (mp);
return app.exec();
}
The compilation is fine. But the program immediatly crashes when I build it (with Qt Creator). Any idea?
Many thanks
Many things could cause this crash. The best is to get VLC source code to trace back the issue. Passing the option '--verbose=2' when initializing libVLC can help as well.
In my case the cause of the crash was due to this bug in the ubuntu package of vlc:
https://bugs.launchpad.net/ubuntu/+source/vlc/+bug/1328466
When calling libvlc_new() vlc modules and their dependent libraries are loaded into memory. The qt module of LibVLC was searching for Qt4 shared objects instead of Qt5 (manually installed).
The solution was to rebuild the module cache which was outdated an pointing to Qt4 binaries. You can reset it on the command line:
sudo /usr/lib/vlc/vlc-cache-gen -f /usr/lib/vlc/plugins/
Or pass to vlc the option:
--reset-plugins-cache
I have never used this library, but Are you using exactly this code?
m = libvlc_media_new_path (inst, "/home/........mp3");
This path may be the problem.
What distribution of Linux are you using?
I ran into this same problem with Qt5 and LibVLC, and the primary cause (Ubuntu 12.04 LTS and 14.04 LTS), was that LibVLC was loading the qt4 interface plugin, which conflicted with Qt5. If you check your call stack, you'll most likely see that at a Qt4 library was being loaded, causing the crash.
If this is the problem, there are only 3 options (tested with LibVLC 2.2 and Qt5 on Ubuntu 12.04 and 14.04 LTS 64 bit).
The first (worst) is to delete the qt4 user interface plugin. You can test this is the problem by moving and running and then setting it back. Deleting will break your regular VLC player most likely.
Second option is to create a copy of the plugins directory and set that in your runtime path using VLC_PLUGIN_PATH, environment variable. but I've had trouble getting that to work without changing the original plugin path folder also (which will break your VLC player unless you modify your shortcuts, etc. to also set VLC_PLUGIN_PATH.
The third option, and what I ended up doing, was to custom build my own static LibVLC binary with a few edits to the source code so that it will not load the qt4 interface plugin installed with VLC. You can follow these steps to do this.
1) Download VLC Source Code for your platforms distribution.
http://download.videolan.org/pub/videolan/vlc/
Make sure you download the version matching your distribution. For
example, match the VLC version to what is installed with Ubuntu.
2) Extract source code to folder
3) Install dependencies for the OS distribution
sudo apt-get build-dep vlc
4) Modify src/modules/bank.c
Edit the module_InitDynamic function
Add the following code at the top of the function:
// HACK TO DISABLE QT4 PLUGIN
if(strstr(path, "qt4") != NULL)
return NULL;
// END HACK
3) From terminal
./bootstrap
./configure --disable-qt --disable-skins2 --enable-xcb --prefix=/home/$USER/vlc-custom_build_output_folder_name
./make
./make install
4) Copy/Save the resulting files in the install folder.
Then just link against this library instead.

gdbinit "no such file or directory" Eclipse c

I'm using Xming to connect to a Linux (enterprise edition) server on which I'm trying to debug a C++ project in Eclipse Galileo. The following errors occurred:
Reading symbols from ../workspace/myfile ..(no debugging symbols found) ... done.
.gdbinit : No such file or directory
Setting environment variable "LS_COLORS " to null value
(.gdbinit is on the server (in root), my account has rights)
If i try to run gmake on the same file from the terminal I get the following error :
gmake ** No rule to make target /workspace/myfile' . Stop.
//I have exported the path (including the library path), and gmake exists.
My project has 3 subprojects (proj1 , proj2 and proj 3). In order to debug proj3 I have to build projs 1 and 2 . I created make targets for projects 1 and 2, and I obtained .so files for which i made softlinks to corresponding files in my_project/libs folder.
My Eclipse debug configuration is as follows (tab order):
Main
  Project: My Project
  Build Configuration: UseActive
  C++ Application: path to my project/myproject
  Environment: path to libs on server (my user rights)
Debugger
  Debugger: gdb/mi
  (Checked) Stop startup at main
  GDB debugger: gdb
  GDB command line .gdbinit
  GDB command set: standard
  Protocol mi
Project Properties:
  Builders CDT Builder
  Scanner Configuration Builder
  C/C++ Build
  Build command gmake -k
Behaviour
  build incremental build : all ( sometimes i get the error no rule for make all)
  Clean: clean
  Discovery options:
    (Checked) Automatic discovery path
    (checked) Report path detection problems
    Discovery profile GCC per project
    (checked ) Enable build output
    Compile invocation comand gcc
    Toolchain
    No toolchain
    Correct builder GNU make builder
This Eclipse debug configuration works on another account (on the same server using the same Eclipse). The gdbinit and gmake files are on the server and work, I'm not supposed to update the versions (this was one solution I found online).
Has anyone seen this error before? Does anyone have a clue what I'm doing wrong?