7

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.

SH.0x90
  • 532
  • 2
  • 7
  • 19
  • 1
    I prefer GCC mingw-w64 so I don't need another machine/OS, but I don't know if there's a majority one way or the other. – Mooing Duck Jun 25 '14 at 20:43
  • 1
    So many things will factor into the decision (and the answer might be that you have to produce multiple libraries for Windows). Will the library be DLL only? Will it export only C linkable objects? Will users want or need to use it with the compiler of their choice (be it and of the several versions of MSVC or MinGW)? – Michael Burr Jun 27 '14 at 21:00
  • 1
    Forks happen, this one for all the usual reasons. It is something you have to deal with when you use foss, it is up to you to make your choice. Do what works first. – Hans Passant Jun 27 '14 at 21:00

4 Answers4

10

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

Tyler
  • 1,818
  • 2
  • 13
  • 22
  • Actually, are any performance pitfalls of compiled executables comparing to manually line-by-line rewritten libs code to compile them on Windows in MSVC? I need high-performance code which uses lot of assembly optimizations and C intrinsics. But it can't compile on Windows. Here is an example: https://github.com/quantcast/qfs/blob/master/src/cc/qcrs/prim.h – Brian Cannard Jul 10 '14 at 09:28
  • 1
    It may be cross compilable, but I don't know how to cross compile projects that use cmake. Cross compiled executables are just as good as natively compiled as long as you use the right options with the compiler, like `-march`. You should look into how to cross compile cmake projects with mxe and possibly ask a new question on SO. – Tyler Jul 10 '14 at 17:29
  • any updates in 2021? – Sergey Kolesnik Dec 24 '21 at 00:41
7

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.

ikh
  • 10,119
  • 1
  • 31
  • 70
  • I don't use `` of C++11 because MinGW doesn't support it, but thanks for your idea, interesting, I will try it out. – SH.0x90 Jun 28 '14 at 01:24
  • @SH.0x90 Does *not* MingW support? Doesn't it support gcc 4.8.1? – ikh Jun 28 '14 at 01:27
  • It doesn't, unfortunately (even on 4.8.1). – SH.0x90 Jun 28 '14 at 01:28
  • @SH.0x90 Here is google's result: http://stackoverflow.com/questions/15718904/mingw-and-stdthread – ikh Jun 28 '14 at 01:39
  • Exactly, works only using MinGW-W64 and as I said on the question, MinGW-W64 is a fork of MinGW and I was wondering if supporting it and implementing those features to compile using MinGW-W64 won't make things bad. – SH.0x90 Jun 28 '14 at 02:28
  • @SH.0x90 Oh, I see.. then, I think pthread is good solution - if you don't use VC++. – ikh Jun 28 '14 at 02:32
  • 2
    It depends on the thread model enabled when gcc is compiled. By default, mingw uses the win32 thread model which isn't supported by libstdc++ (gcc's standard library), so `std::thread` gets disabled. With winpthreads and the POSIX thread model, it can use `std::thread`. And this is true even for gcc 4.9. For more info, see my answer. – Tyler Jul 02 '14 at 21:14
  • MinGW supports (GCC 4.9, 5.x). MinGW-w64 with POSIX threads supports but doesn't support with win32 threads. The solution for Win32-threads - custom headers you can take here: https://github.com/meganz/mingw-std-threads – Wohlstand Jun 13 '17 at 11:58
1

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.

newbie
  • 1,230
  • 1
  • 12
  • 21
  • Boost seems to be great, but I really don't like, as you said, extra dependency, but thanks anyway. – SH.0x90 Jun 28 '14 at 20:44
0

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.

Niall
  • 30,036
  • 10
  • 99
  • 142