I have written an application in C++ without using system specific libraries. I know that if I want to obtain executable binaries for instance for Windows, I need to build my code on this platform. But I am looking for a way to check if my executable is compatible with all windows versions or with all linux distributions. Is there any automatic way to check it? Or I am obliged to check it on my own?
Short answer: it depends on the version of the libc/libstdc++ you are building with.
If you create an executable, unless you link it statically, it will actually be linked against several system libraries. Those libraries version will determine which system your application will be compatible with.
So unfortunately, there is no way to tell, except testing on several systems directly…
And to do so, some systems exist, ex:
https://distrotest.net/
Related
I'm struggling to deploy my Qt/C++ application, probably because I have not found a good introduction about this online. In brief my question is how do I setup an installation framework which requires only minimal, or preferably no, compilation before shipping to users.
I want to deploy the GUI to users on different platforms, who may or may not have admin rights on their machines. I have found different options:
Statically compile Qt -> statically compile an executable -> distribute the executable. With this setup I have encountered a Windows security warning, which requires admin privileges (I have not yet tried on Linux / macOS). And frankly this approach seems sub-optimal, as my compiler has no idea about how to compile optimally for my users.
Create an installer. But there I start to be confused... Do I need to provide a statically compiled executable of my GUI, or just of the installer, or neither? Or can I avoid pre-compiling on my side all together by using an installer from Qt with built-in compiler/libraries?
With this setup I have encountered a Windows security warning
You didn't sign the binaries. This issue has nothing to do with Qt. You'd face it even when distributing a trivial "Hello World".
Ensure that you sign all of the following:
The executables.
All DLLs that you redistribute and are not signed (verify each one).
The installer.
my compiler has no idea about how to compile optimally for my users.
Since C++ doesn't use just-in-time compilation, this statement is a truism. When you dynamically link your compiler will also have "no idea" how to compile "optimally for your users" if you imply that you need CPU-specific variants of your code. This has to be addressed by having multiple executables, each compiled for a particular CPU, and selecting them on installation. I don't think you meant that, though. But then I have no idea what you mean by "compile optimally for my users".
Do I need to provide a statically compiled executable of my GUI
It's up to you. If you don't provide a statically compiled executable, you will need to provide all of the dependencies: the C++ runtime of your compiler, and all the libraries and plugins needed by Qt.
The procedure for producing a statically linked executable on Windows, Linux and OS X is identical. You start with a statically configured copy of Qt (configure -static -static-runtime), then build it, and then use that to build your application. The end product will be statically linked against C++ runtime and Qt libraries.
Do I need to provide a statically compiled executable of [...] the installer
Only if you compile the installer program yourself using a C++ compiler. Most installer generator packages take care of creating an installer that has no additional dependencies, i.e. you can run it on a bare Windows system.
can I avoid pre-compiling on my side all together by using an installer from Qt
Qt provides no pre-built installers for re-use.
You can use e.g. NSIS to deploy the compiler runtime, Qt libraries and plugins, and your application and any data files it needs.
Or you can statically compile your application so that it has no dependencies and is a single .exe file, and have it as a portable application. It could also self-install, i.e. you could bundle the installer within the application, and on startup the application could detect whether it's already installed, and if not it'd relaunch itself in administrative mode and perform the installation.
Obviously you need to build your application on each platform you want to distribute it to. Easiest way is to link all the QT libraries dynamically to your application. After that all you need to do is provide your application (as in exe file on windows, or executable on linux etc) and the QT libraries you used (DLLs on windows, SO file I think on linux etc)
For example (on windows) if your app is called MyApp and uses QTGui, QTWidgets and QTNetwork, then you have the following files to distribute:
MyApp.exe
QTCore.dll and few other DLLs needed called icu*.dll something, can't remember)
QTGui.dll
QTWidgets.dll
QTNetwork.dll
and you can zip them all in one zip, create an installer etc.
EDIT Few notes after the follow up in the comment.
The standard library (what you called default library that has vector class) is part of the c/c++ runtime (on windows) or installed on linux systems etc, so no, you don't have to worry about this. I can't say for all compilers but for some you can specify a flag/parameter to link this runtime statically (rarely there is a need to do this).
On windows there is a tool called dependency walker, which gives you the list of all DLLs needed for the application to run. On linux systems I don't know, never needed one really. But for your own application, you do know which libraries you need, since you wrote it :)
When I develop across different OS's I find that a program built on one Linux system can not be run on another system, due to the different libc version.
How can I build in all the shared libraries just like golang did in c/c++?
Including libc and libcxx
If you want to run on multiple Linux systems, all you really need is to build using the oldest glibc from any of them. The easiest way is to simply download a virtual machine image from an old system like CentOS 5 and build there. You don't need to worry about static linking, just building against an old version will mean you are mostly compatible with newer versions.
This is a possible duplicate to this question but the answer is not solving my problem...
I want to use third party software delivered by c++ headers, libraries (.lib) and dlls for a project. Because it will run on a BeagleBone, I am writing this project for Linux. Is there any proper way to link dlls for Linux applications?
Highly unlikely to ever work:
Windows uses a different file-format for executable files (and DLL's are essentially executable files - same for shared libraries in Linux). This means that relocation information and symbol linkage is different.
Even if you manage to load and relocate the DLL, you most likely will need many other DLL's (such as the compiler runtime and system runtime [kernel32.dll for example]) to actually run the application. And of course, those dependent files need to have a correct interface to work on Linux (see #3)
There's nothing stopping a Windows DLL from making system calls directly in the shared library - these won't work in Linux.
Your best choices are:
Request Linux versions from the supplier of those libraries. Depending on what the functionality is, it may or may not be an easy task for the supplier to produce alternatives for different architectures.
Run the application inside the WINE (WINdows Emulator) package.
Run a Windows virtual machine, and run the application inside that.
Write your own replacement libraries, or find others already available out there.
Is static linking in Linux portable? I mean, can I use the -static option in gcc and link with every dependencies statically to have a clean output from ldd, and expect that the resulting executable will run portably in another computer with Linux installed? Of course given that the CPU architecture and the kernel version is compatible.
The short answer: Pretty much.
This will make a binary which will run on a kernel which is the same or compatible with the one for which the software was designed.
It may not take into account directory structure and if the binary expects to be able to load any external dependencies dynamically, that might not work.
Assuming there's nothing too fancy going on though, it will work fine.
This is approximately what Go's compiler does to enable shipment of binaries roughly anywhere. This also is a method for making a build forward compatible if you expect to be making OS upgrades that will be disruptive.
Additionally, these static binaries could be run in a FreeBSD kernel with Linux compatibility. As long as the kernel and user space is compatible, the binary should work.
As always, test.
Yes. The static link means it won't depend on any other library.
Maybe. You won't need to worry about dynamic library dependencies. Your statically linked libraries might use system calls or other kernel interfaces that older kernels don't have, so you'll only be forward compatible (the linux kernel has a pretty strong backwards compat policy). The only thing you might need to worry about are external files that your statically linked libraries might depend on (like localization databases and such).
I am looking to create a C++ library that can be used by both Linux and Windows clients. The OS specific functionality will be hooked up by the client by implementing the interfaces provided by the library.
Is this possible to achieve? Do I need to recompile the C++ project again in linux.
P.S: I am using CodeBlocks IDE
The short answer is no, you still need to compile your library for each targetted platform -- however, assuming your code is written such that it is cross-platform, you can set up your build to target both Windows and Linux environments with little fuss. I do this now using CMake to generate both Visual Studio projects for Windows environments and Makefiles for Linux environments.
I'm pretty confident that Linux will not accept a .dll :) And yes, you will need to recompile. Unless you run windows as a virtual machine under linux which sort of preempts the question.
It certainly cannot be the same binary file: shared objects ELF format on Linux, DLL "PE" format on Windows. And dynamic loading has different semantics on both systems. See Levine's linker and loader book for details.
You could, if done carefully, have the same source code giving the two different files (the DLL on Windows, the dynamic shared object on Linux).
But you probably would need some conditional compilation tricks like #ifdef WINDOWS etc...
You might use libraries providing you a common abstraction for such things. For instance, both GTK/Glib and Qt have some mechanism giving a common abstraction of dynamically linked (or dynamically loaded - ie dlopen-ed) libraries.
You probably want to read the Program Library Howto (at least for Linux).