Issue
I'm actually coding a library and I'm willing to make it multiplatform. I already use multiplatform dependencies (boost mainly) and I've been initiated to CMake.
I've been using CLion for the past few months, and while it is a very great IDE, it's very complicated to use it on Windows, because it either require MinGW or Cygwin. I've been using Cygwin until then, because the emulation of Unix satisfied me, but since the last update, boost is totally unusable on it.
I decided that the best for me was to go back on Visual Studio. But how to use it along with CMake ? My library needs to be deployed under multiple versions of VS (starting from VS2013, up to 2015)
So far, what I've been doing was regenerating the project everytime I added a file, but I find this solution very unproductive as you can guess. I also need to be able to compile into different locations, depending on the compiler. For example:
- include
- lib
- VS2013-x64
- Debug
- Release
- VS2013-x86
- Debug
- Release
- VS2015-x64
- Debug
- Release
- VS2015-x86
- Debug
- Release
- VS2013-x64
- src
Is that possible to handle it with CMake ? And if so, how ?
Solution
This is not a Visual Studio specific problem.
In general, C++ does not guarantee that a library built with one version of a compiler will work with an executable built by a different version of the same compiler, or by a different compiler. This is because C++ gives compilers certain freedoms in how to generate the binary layout of its objects.
This is a very old problem and there is no easy solution. If you don't want to accept any restrictions on the library's interface, you will need to rebuild the library for every supported compiler version with a breaking ABI change (which usually means a separate build for every compiler and major version bump in the compiler version).
CMake cannot do this for you, as each CMake configure run will only generate a CMake configuration for one specific compiler. The best thing you can do here is write a shell script that repeatedly calls cmake
and cmake --build
from different binary directories to automatically build on all supported compilers one after the other. Since this is still tedious to do manually, you might want to setup a continuous integration system to help with that.
The alternative is to restrict your library interface in a way that its binary interface becomes well-defined. Typically this means one of two things:
- Use a C API as the outer library interface. Your code can still be C++, but an application that wants to interact with your library has to go through the C API. The obvious downside here is that you no longer have classes on the interface, but structs and free functions. This solution is more common than you might think. Stefanus Du Toit gave a talk (video; slides) about this approach at CppCon 2014.
- Use an object model technology like Microsoft's COM. The lack of a standardized ABI has bothered people for a long time now and the industry has come up with several solutions on how to get classes and objects on the interface. Unfortunately, understanding these technologies is no small feat, so be prepared to do some serious research if you decide to go down this road. This approach is very common in the Windows world.
Answered By - ComicSansMS