what is the difference between lib-mingw and lib-vc2019 - c++

I'm new to Windows programming and found that lots of prebuilt libraries for Windows offer libraries like lib-mingw, lib-vc2019, lib-vc2017...
Could anyone help to point out
what is the difference? Which library should I use in what case?
If I want to use Clang on Windows, which one should I use?
Why these different libraries rarely seen on Linux (let's say
Ubuntu), does package managers like apt hide this detail? In other word, why there's no such thing like lib-gcc.a, lib-clang.a on Linux platform?

Mingw (GCC), VC2019 and VC2017 are different compilers. Use the library corresponding to your compiler.
I'm not sure but I think none of them will work with Clang. At least on Linux GCC and Clang are very similar. I mean they are mostly binary compatible, many same compiler flags, many same compiler extensions. Clang tried to make it possible to easily replace GCC in your build pipeline. But all these information is for Linux.
These libraries are not seen on Linux because all these compilers are Windows compilers
You can always build a library with your compiler to use it in your project with your compiler (if you have the sources).
If it's a third party closed source library and you are a paying customer you can ask if they build it for you. It's usually better the add a new compiler to the build pipeline than to lose a customer.

Related

If you use a newer gcc than the one that comes with your distro, are system libraries a concern?

My question specifies the version numbers of my scenario, but I'm interested in a general to the question.
I'd like to use gcc 11 on Alma Linux/Red Hat 8 (identical ABI), which come with gcc 8, in order to use C++20/23 features in my own programs. The programs I compile with it (all userspace applications) would run on the same system.
I'm thinking of compiling gcc11 from source, installing it in /usr/local/gcc11/, and calling it when I need it. I don't want to replace/remove the system gcc, since various tools that support a given distro will be expecting that compiler. I would just call a wrapper script to use gcc11 when I need it.
I expect gcc11 will compile just fine, and so will programs I compile with it. But any non-trivial program tends to link against libc, libm, libdl, libpthread, libgcc_s, libstdc++, and so on. I would be using gcc11 with relatively old versions of these system libraries. These are all system libraries which I've never had to deal with directly.
The situation that worries me is if some new dependency I use was written around libpthread version Z but my system has version X, and despite the ABI being unchanged (which allows my program to link successfully against the system libpthread), the behavior is different due to bugfixes, and I end up with subtle runtime bugs.
Is this a valid worry? Or am I golden as soon as my application compiles/launches successfully?
The only existing discussion on this that I could find ( Is there any issue in upgrading GCC version to other than the ones come with distro? ) is light on info, and the warnings given don't apply to me since I don't intend to touch the system gcc/libs.
It depends which features you're compiling against. This article from cppreference.com has more details on which c++ features for each language version are supported by which c++ runtime. https://en.cppreference.com/w/cpp/compiler_support
Since you're talking about compiling with gcc, you're going to want to look at the libstdc++ runtime library. It looks like not even every feature of c++20 is even supported by version 8 of the runtime library. But it is most things.
To work around this you could
install the runtime version of libstdc++ you want
package and distribute the libstdc++ runtime library along with your code
statically link against libstdc++, which I don't recommend
Keep in mind that there is theoretically an option to compile against libstdc++ statically, but you're not guaranteed to get those symbols at runtime depending on your situation. It also makes a difference if you're compiling an application vs a library. Loading a library my cause your libraries symbols to conflict with what's already been loaded (probably by libstdc++). This post does a good job explaining some things to look out for https://stackoverflow.com/a/14082540/1196033.
(Also, Android is weird https://developer.android.com/ndk/guides/cpp-support)

How does musl's GCC wrapper differ from musl's cross-compiler?

I am trying to compile various programs such as MariaDB with a musl toolchain. That is, I don't want any dependencies on glibc or GNU's linker after compilation has finished.
Thus far, I have been using musl's GCC wrapper, musl-gcc to compile things. But, with larger programs like MariaDB I struggle to get all the necessary libraries and headers and symlinking or adding environment variables for the compilation doesn't really help.
I see mention of building a cross-compiler targeting musl libc with additional documentation and code at this GitHub repo. From the documentation on the cross-compiler:
This gives you a full, relocatable musl-targeting toolchain, with C++ support and its own library paths you can install third-party libraries into.
It sounds like this could help me, but I am not sure how this is very different from musl's GCC wrapper, which as I understand, just alters where GCC looks for libraries and headers etc.
Ultimately, I am unsure how different this cross-compiler really is from the GCC wrapper and if it would be useful in my case. Why would I need my own library paths to install third-party libraries into when I can just symlink to existing libraries and use the GCC wrapper? Is the cross-compiler the way I should be compiling things, especially bigger code bases?
All the wrapper does is remove the default library and include paths and add replacement ones. Otherwise, it relies on the compiler's view of the ABI being sufficiently matched that a GCC that thinks it's targeting glibc (*-linux-gnu) works with a musl (*-linux-musl) target.
A full GCC toolchain has a number of "target libraries" - libraries that are linked into the output program to provide some functionality the compiler offers. This includes libgcc (software multiply or divide, software floating point, etc. according to whether the target arch needs these things, and unwinding support for exception handling), libstd++ (the C++ standard library), and a number of other things like libgomp (GNU OpenMP runtime implementation for use with #pragma OMP ...). In theory all of these possibly depend on the specific target ABI, including the libc, and potentially link to symbols from libc. In practice, for the most part libgcc doesn't, and is "safely" reusable with a different libc as long as the basic type definitions and a few other ABI things match.
For the other libraries with more complex dependencies on libc, it's generally not expected that a build against one libc would work with a different one. musl libc provides some degree of ABI-compat for using glibc-linked libraries, so there's some hope that they'd work anyway, but you'd need to copy them to the new library path. However, GCC's C++ standard library headers also seem to have some heavy dependency on the (libc) system headers for the target, and when setup for glibc do not seem to work with musl. There is probably some way to make this work (i.e. to add C++ support to the wrapper), but it's an open problem exactly how to do it.
Even if this could be made to work, though, the deeper you go, the more reasons you're likely to find that you'd rather just have a proper cross-compiler toolchain that knows it's targeting musl. And nowadays these are easy enough to build. But if you find you're needing additonal third party libraries too, and don't want to build them yourself, it probably makes more sense to just use a Docker image (or other container) with a distro that provides library binaries for you.

MinGW vs MinGW-W64 vs MSVC (VC++) in cross compiling

Let's put like this: We are going to create a library that needs to be cross platform and we choose GCC as compiler, it works awesomely on Linux and we need to compile it on Windows and we have the MinGW to do the work.
MinGW tries to implement a native way to compile C++ on Windows but it doesn't support some features like mutex and threads.
We have the MinGW-W64 that is a fork of MinGW that supports those features and I was wondering, which one to use? Knowing that GCC is one of the most used C++ compilers. Or it's better to use the MSVC (VC++) on Windows and GCC on Linux and use CMake to handle with the independent compiler?
Thanks in advance.
Personally, I prefer a MinGW based solution that cross compiles on Linux, because there are lots of platform independent libraries that are nearly impossible (or a huge PITA) to build on Windows. (For example, those that use ./configure scripts to setup their build environment.) But cross compiling all those libraries and their dependencies is also annoying even on Linux, if you have to ./configure and make each of them yourself. That's where MXE comes in.
From the comments, you seem to worry about dependencies. They are costly in terms of build environment setup when cross compiling, if you have to cross compile each library individually. But there is MXE. It builds a cross compiler and a large selection of platform independent libraries (like boost, QT, and lots of less notable libraries). With MXE, boost becomes a lot more attractive as a solution. I've used MXE to build a project that depends on Qt, boost, and libexiv2 with nearly no trouble.
Boost threads with MXE
To do this, first install mxe:
git clone -b master https://github.com/mxe/mxe.git
Then build the packages you want (gcc and boost):
make gcc boost
C++11 threads with MXE
If you would still prefer C++11 threads, then that too is possible with MXE, but it requires a two stage compilation of gcc.
First, checkout the master (development) branch of mxe (this is the normal way to install it):
git clone -b master https://github.com/mxe/mxe.git
Then build gcc and winpthreads without modification:
make gcc winpthreads
Now, edit mxe/src/gcc.mk. Find the line that starts with $(PKG)_DEPS := and add winpthreads to the end of the line. And find --enable-threads=win32 and replace it with --enable-threads=posix.
Now, recompile gcc and enjoy your C++11 threads.
make gcc
Note: You have to do this because the default configuration supports Win32 threads using the WINAPI instead of posix pthreads. But GCC's libstdc++, the library that implements std::thread and std::mutex, doesn't have code to use WINAPI threads, so they add a preprocessor block that strips std::thread and std::mutex from the library when Win32 threads are enabled. By using --enable-threads=posix and the winpthreads library, instead of having GCC try to interface with Win32 in it's libraries, which it doesn't fully support, we let the winpthreads act as glue code that presents a normal pthreads interface for GCC to use and uses the WINAPI functions to implement the pthreads library.
Final note
You can speed these compilations up by adding -jm and JOBS=n to the make command. -jm, where m is a number that means to build m packages concurrently. JOBS=n, where n is a number that means to use n processes building each package. So, in effect, they multiply, so only pick m and n so that m*n is at most not much more than the number of processor cores you have. E.g. if you have 8 cores, then m=3, n=4 would be about right.
Citations
http://blog.worldofcoding.com/2014_05_01_archive.html#windows
If you want portability, Use standard ways - <thread> library of C++11.
If you can't use C++11, pthread can be solution, although VC++ could not compile it.
Do you want not to use both of these? Then, just write your abstract layer of threading. For example, you can write class Thread, like this.
class Thread
{
public:
explicit Thread(int (*pf)(void *arg));
void run(void *arg);
int join();
void detach();
...
Then, write implementation of each platform you want to support. For example,
+src
|---thread.h
|--+win
|--|---thread.cpp
|--+linux
|--|---thread.cpp
After that, configure you build script to compile win/thread.cpp on windows, and linux/thread.cpp on linux.
You should definitely use Boost. It's really great and does all things.
Seriously, if you don't want to use some synchronization primitives that Boost.Thread doesn't support (such as std::async) take a look on the Boost library. Of course it's an extra dependency, but if you aren't scared of this, you will enjoy all advantages of Boost such as cross-compiling.
Learn about differences between Boost.Thread and the C++11 threads here.
I think this is a fairly generic list of considerations when you need to choose multi-platform tools or sets of tools, for a lot of these you probably already have an answer;
Tool support, who and how are you going to get support from if something doesn't work; how strong is the community and the vendor?
Native target support, how well does the tool understand the target platform?
Optimization potential?
Library support (now and in the intermediate future)?
Platform SDK support, if needed?
Build tools (although not directly asked here, do they work on both platforms; most of the popular ones do).
One thing I see that seems to not really have been dealt with is;
What is the target application expecting?
You mention you are building a library, so what application is going to use it and what does that application expect.
The constraint here being the target application dictates the most fundamental aspect of the system, the very tool used to built it. How is the application going to use the library;
What API and what kind of API is needed by or for that application?
What kind of API do you want to offer (C-style, vs. C++ classes, or a combination)?
What runtime is it using, will it be the same, or will there be conflicts?
Given these, and possible fact that the target application may still be unknown; maintain as much flexibility as possible. In this case, endeavour to maintain compatibility with gcc, mingw-w64 and msvc. They all offer a broad spectrum of C++11 language support (true, some more than others) and generally supported by other popular libraries (even if these other libraries are not needed right now).
I thought the comment by Hans Passant...
Do what works first
... really does apply here.
Since you mentioned it; the mingw-builds for mingw-w64 supports thread etc. with the posix build on Windows, both 64 bit and 32 bit.

Which version libstdc++.so is used in case of multiple GCC on the same system

I am trying to install the gcc 4.8 on a system where gcc 4.3 is installed and used currently. I did some research and knew that it is possible to keep multiple versions of gcc. And it seems for me that using --program-suffix= option is the best solution for me. But my question is, can I install new gcc 4.8 directly into the place where old gcc is installed? Can libraries from both versions be mixed in the same lib directory?
Some more details: the old gcc is installed in /usr/bin, /usr/lib64. If i install new gcc directly to the same location, new libraries will be also installed /usr/lib64. Is this a problem? Will gcc compiler know which library to use when linking?
Many thanks in advance!
I'm on Gentoo, which does support installing multiple versions of GCC at the same time. The libraries end up in /usr/lib/gcc/<target>/<version>. Ubuntu seems to install them in the same place, so I'd guess this to be a fairly common setup.
While gcc can apparently figure out the correct version to link against at compile time, the version used at runtime is configured using a file in /etc/ld.so.conf.d. So it might happen that a program gets compiled against one version of the gcc libraries, but executed with another.
If the ld.so.conf.d setting prefers newer versions over older, then this is mostly all right as long as gcc guys didn't introduce a new bug into one of these libraries, and as long as the configuration causes the libraries to be fully backwards-compatible.
In this bug we had a situation where libstdc++ broke backwards compatibility with regard to some C++11 features which were experimental and enabled using a custom configure switch. These things should be rare, but they can happen.
In a related gcc bug report I learned from Jonathan Wakely:
It is totally unsupported (and unlikely to work) to mix C++11 code built with GCC 4.x and 4.y, for any x!=y
Mixing code built with 4.8.x and 4.8.y should work, and does with the default configuration.
So while this setup works in practice on Gentoo, you are on your own if you try this yourself. Particularly since I know of no clean way to ensure that resulting binaries will link against the matching libraries at runtime.
You can try whether --program-suffix affects library names as well. If so, then the SONAME of the newer version libraries should be different from that of the older, helping to get the linking right at runtime. If the library name is unaffected, you could try examining the build system whether you can either change the SONAME of the generated libraries, or have the linker set the RPATH of all the programs it links. I have no experience with either of these approaches.
On Gentoo, /usr/bin/gcc appears to be some kind of wrapper, and the actual programs end up in /usr/<target>/gcc-bin/<version>/gcc and the likes. At least judging from the package web site, Ubuntu doesn't do this for the default version of gcc, although something similar is apparently used for cross-compilation to Android. I guess that setting is the result of a matching --bindir at configure time.

G++ ABI compatibility list

I have compiled my preload file on Ubuntu server (two files for x32 and x64). Where I can get list, in which I will see with what OS my compiled files are compatible and with what I should recompile for compatibility?
Thanks!
Use Linux App Checker developed by ISPRAS and The Linux Foundation. It's designed to perform cross-distro compatibility checks for Linux applications. See sample reports here.
I would start by attempting to execute the program on various Linux distributions in a virtual machine. Pick the top three most popular Linux distributions or the ones your users are most likely to have.
Also, you may be better off to distribute a statically linked binary and offer the source code to others who wish to build it themselves (if you are allowed to distribute source).
I don't know if I fully understand you, but, if my understanding is not that wrong, I'd start by ldd -v. Any OS that is architecture compatible and has the dependent libraries installed in compatible versions should work.
Next, if you plan to support more architectures, you need explicitly to know it and cross compile for every one of it.
So, you must recompile for:
1. Every different architecture.
2. When library versions are not compatible.
This last one is more tricky, since your code may need specific versions to work, but you must know it anyway from start.
Please tell me if it is not what you wanted.