Targeting C++/WinRT with CMake - c++

I'm working on compiling a CMake-based third party C++ shared library for use within a UWP application.
Per documentation on MSDN, I've been building with the flags -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0. While this is very useful for flagging any disallowed or unavailable APIs, my understanding is it sets the /ZW flag, which enables C++/CX.
This is mostly fine except for some minor points (for example: the library deals with networking, and makes use of the variable name interface which is apparently a reserved keyword by C++/CX).
More fundamentally, since I'm building a standard C++ library, I'd rather use standard C++ (C++/WinRT). Is there a way to tell CMake to target the WindowsStore SDK but without carrying along C++/CX?

This is a fallacious question. Underlying problem has nothing to do with C++/CX or UWP -- Including windows.h pulls in combaseapi.h which has #define interface __STRUCT__. And so, MSVC treats interface as the struct keyword.
[The original, incorrect answer cited interface being a reserved keyword on MSVC per https://learn.microsoft.com/en-us/cpp/cpp/interface?view=vs-2019. This is also not correct, as pointed out in the comments]

Related

Do users need to fulfill any prerequisites to run C++17 software?

My team and I are currently developing a piece of software that is built on C++14 specs. We are considering adding some C++17 features (primarily std::variants) in our code, but my supervisor was unsure if we could simply put these in our code, build with an appropriate compiler and then ship it.
From what I know, this should not make any difference if we pre-compile our application for our target platforms and make them available as executables, but I have never actually had to deal with deployment of software to customers yet, so I am unsure if I am overlooking anything here (like if we would have to also supply according C++ redistributables for Windows or so).
As background info: our software is heavily Qt-based and should thus be deployable to all major desktop operating systems. We're mainly working in a Windows environment, and for most testing purposes we are compiling with MSVC2017 at the moment.
We technically also plan to release an SDK/library to facilitate interfacing with the network part of our application, which may also benefit from C++17 features. I would assume that developers willing to use this SDK would then be forced to use a C++17-compliant build environment, even if the C++17 features are pretty much encapsulated in the library and not exposed in the headers - is that correct?
The answer is (as usual) "it depends."
If the C++17 features being used are built entirely from templates, and C++17 types/features are not exposed in your SDK header, then this absolutely should work fine, since the templates would be instantiated and included in your library's native code by your compiler.
If the C++17 features depend on some runtime library support, but are not exposed in your SDK, then you would just need to ship that runtime library or otherwise make it available.
Regardless of whether you use C++17 features, your SDK users should use exactly the same C++ environment (including the version, if possible) that you use, because there is no guarantee of ABI-compatibility between C++ versions, nor between different versions of the same compiler. If you use MSVC++2017, your SDK users must also use either MSVC++2017 or another environment that is explicitly documented to be compatible with the MSVC++2017 ABI. (So instead of asking if this will work, you should be asking what version of MSVC++ it is reasonable to require your SDK users to use, and that's a question I cannot answer for you.)
In all cases, end users who are not intending to use the SDK should be fine as long as you ship the required runtime libraries, which you are almost certainly already doing (though you may need to change which runtime library you ship).

C++ Using features of a newer compiler to generate code for use by an older compiler

I've been looking into some of the features of the "newer" C++ standards (C++11 and C++14), and that got me thinking about something. I'm currently using the VC++2008 compiler for my projects (for various reasons), which means that the newest standard I have access to is C++03, plus TR1. TR1 has some nice things in it, but there are features in C++11 and C++14 that would be nice to have.
My question is this: Would there be any way that I could build some code using a newer compiler (say MSVC2012 or 2013) to build libraries or DLLs using the newer C++11 and C++14 functionality and then link that into my project that's running the '08 compiler?
The only thing that I could think of that wouldn't work would be anywhere I had to have a C++11 or C++14 feature in a header included by my '08 compiler project. However as long as everything "new" were hidden behind my interface, shouldn't this work?
Yes but its going to get ugly.. since the ABI is not compatible you'll have to go down to the "extern "C" {}" ABIness.
That means you can't pass C++ objects at all.. like I said, painful. It also means it must be a DLL since you won't be able to link in a static lib with another ABI.
Its up to you if its worth wrapping up a DLL in a C API just to use a couple of new features or not, I would recommend just upgraded the whole project though.
I almost forgot, you probably can't link the import lib either, so you'll have to have some code that uses LoadLibrary, GetProcAddress and FreeLibrary (did I mention this is ugly/painful?).
Unfortunately, what you're trying to do is not possible with MSVC. They intentionally break binary compatibility with every major release as stated in MSDN documentation:
To enable new optimizations and debugging checks, the Visual Studio implementation of the C++ Standard Library intentionally breaks binary compatibility from one version to the next. Therefore, when the C++ Standard Library is used, object files and static libraries that are compiled by using different versions can't be mixed in one binary (EXE or DLL), and C++ Standard Library objects can't be passed between binaries that are compiled by using different versions. Such mixing emits linker errors about _MSC_VER mismatches. (_MSC_VER is the macro that contains the compiler's major version—for example, 1800 for Visual C++ in Visual Studio 2013.) This check cannot detect DLL mixing, and cannot detect mixing that involves Visual C++ 2008 or earlier.
Your options are to then only pass around POD types, or implement COM interfaces to interop between the DLLs compiled using different version of the VC compiler, neither of which is particularly palatable.
My advice would be, if you must stick with VS2008 for certain legacy applications, suck it up and deal with the feature set it supports (at least you have TR1). For newer projects, try and talk your team into using newer versions of VC.

zlib for WinRT?

I require zlib library for the development of Windows Store app.
Has anyone converted Win32 zlib project to WinRT yet?
Can anyone please describe the steps to convert the existing win32 static lib project to winRT?
Visual C++ is already a supported language for WinRT development, if you wan't to use zlib, just compile it together with your solution. There is nothing that is preventing you from reusing standard ISO C and C++ libraries from within the WinRT, if you are using the C++ language, you might have to expose certain aspects of your library as WinRT Components but only if you need to interface with facilities like XAML or other WinRT languages but that should be a walk in the park. Not something which is tremendously difficult to do.
The whole point of supporting C++ in the WinRT is to allow an existing ecosystem of largely native applications to be ported to the Windows Store. zlib is not an exception. Non-standard ISO C and C++ such as sockets are not supported but there you have alternatives that you can plug-in to, just check that the library you're using has some kind of portability support.
WinRT is very limited with regards to C library functions which are present. What this means is that virtually all cross-platform C libraries are (AFAIK, I'm not a WinRT dev) unusable for that target.
For the case of zlib, there is an alternative: see this question
EDIT: to clarify what I'm saying above, I dug up a list of all CRT functions that are absent for WinRT, which you can find here. As long as zlib or any other C library does not depend on these function calls, you should be able to use the WinRT tools to build that C library. I even found a project file for zlib on winrt by the Ogre team here, not sure how useful it is to you.
You could take a look into this WinRT (Un)Zip component. Its used in production code already.
See the unit tests inside on how to use the component. It compiles on all WinRT architectures including ARM. It has no custom asm for ARM though.

Creating Library with backward compatible ABI that uses Boost

I'm working on a certain C++ library (or more framework). I want to make it backward
compatible with previous versions preserving not only API compatibility but also ABI (like the great job Qt does).
I use lots of functionality of Boost and it seems for me that this makes backward compatibility just impossible, unless I force a user to have exactly the same (sometimes old) version of Boost.
Is there any way (without rewriting 1/2 of Boost) to make some "prefix" around its namespace/rename it in order to prevent it from interfering with a user version of Boost?
For example my libXYZ uses Boost 1.33 and it has class boost::foo. In version 1.35 boost::foo was upgraded and new member was added, so, boost::foo from 1.33 and 1.35 are
not ABI compatible. So, a user of libXYZ must use Boost 1.33 or recompile libXYZ with
Boost 1.35 (that may be already had broken some API in a way XYZ would not compile).
Note: I'm talking about UNIX/Linux OS with ELF where dynamic linking is similar to static linking, so you can't link with two different versions of libraries because symbols would interfere.
One suitable solution I may think of is putting Boost in some other private namespace. So, libXYZ would use ::XYZ::boost::foo instead of ::boost::foo. This would prevent collision with other version of Boost that user may use.
So, the libXYZ would continue to work with Boost 1.33 statically or dynamically linked with it withing other namespace, assuming, that it:
Would not expose Boost API outside.
Would keep stable private version of exposed API.
Is there any way to do such things with Boost?
Edit: Finally I decided to create a script that would rename all boost symbols in the source to some custom symbol.
Rationale: simplification of build process, independent of compiler visibility support, also, it visibility works on dynamic libraries only, for static this does not work, so I need separate builds and dependencies for each type of libraries.
The script is available there: http://art-blog.no-ip.info/files/rename.py
Edit 2: Latest version of Boost BCP supports namespace renaming.
Basically, just make sure the public interface to your library does not expose Boost. You can always use it however much you want internally. Generally, having the interface of a library depend on another library is bad (unless it depends on a standard library like STL). Boost almost fits into the "standard" library category, but its ABI changes so much that that your interface shouldn't use it.
To make sure you don't expose the Boost symbols, there are a few things you could do:
A. compile with -fvisibility=hidden and mark all public symbols with __attribute__((visibility("default"))). you could use a macro to make this easier:
#define ABI __attribute__((visibility("default")))
B. do something like this:
#pragma GCC visibility push(hidden)
#include <boost/whatever.hpp>
#pragma GCC visibility pop
You should also wrap this around all other internal symbols that you don't want exported, or declare this with __attribute__((visibility("hidden"))). Again, you could use a macro to make this easier:
#define INTERNAL __attribute__((visibility("hidden")))
Of these options, I like A better, because it makes you explicitly think about which symbols are exported, so you don't accidentally export things you don't want.
By the way, you can find a lot more information about making DSOs in Ulrich Drepper's How to Write Shared Libraries.
In general you can't rely on any type of ABI in C++ beyond standard C bindings. But Depending on how many assumptions you make, you can use more and more of C++ in your interface.
I found this great article on steps to make your API's turn into a stable ABI. For instance, never pass Standard C++ Library (or Boost) datatypes across your interface; it might break even with a small bug fix to the library.
Some examples of the issues to watch out for when publishing an ABI compatible API are:
Windows Debug heap. You have to be sure that all allocations and deallocations are on the same side of a "module" (that is, executable or DLL).
Fragile Binary Interface problem. Even if both sides of your system consistently use the same compiler and libraries, you have to be careful in C++ about what you publish in your .h files, and where allocations happen.
If you follow the linked article, you will find solutions for these and other issues.
Edit:
I also found an interesting article published by Microsoft which describes how COM interfaces work, by taking a C++ project and turning it into COM. It's my belief that one of the primary reasons that Microsoft developed COM was to solve the Fragile Binary Interface problem that C++ has, so they can ship DLLs with publish object oriented APIs.
Consider using abi-compliance-checker tool to maintain a stable API/ABI interface.
You should be able to do something like this:
namespace XYZ
{
#include <boost/my_library.hpp>
}
And it should dump the boost headers into namespace XYZ. Note, however, that this will only work with the header-only libraries.

Using Component Object Model (COM) on non-Microsoft platforms

I'm regularly running into similar situations :
I have a bunch of COM .DLLs (no IDL files) which I need to use and invoke to be able to access some foreign (non-open, non-documented) data format.
Microsoft's Visual Studio platform has very nice capabilities to import such COM DLLs and use them in my project (Visual C++'s #import directive, or picking and adding them using Visual Basic .NET's dialogs) - and that's the vendors recommended way to use them.
I would be interested into finding a way to use those DLLs on non-microsoft development platforms. Namely, using these COM classes in C++ project compiled with MinGW or Cygwin, or even Wine's GCC port to linux (compiles C++ targeting Win32 into binary running natively on Linux).
I have got some limited success using this driver, but this isn't successful in 100% of situations (I can't use COM objects returned by some methods).
Has someone had success in similar situations ?
Answering myself but I managed to find the perfect library for OLE/COM calling in non-Microsoft compilers : disphelper.
(it's available from sourceforge.net under a permissive BSD license).
It works both in C and C++ (and thus any other language with C bindings as well). It uses a printf/scanf-like format string syntax.
(You pass whatever you want as long as you specify it in the format string, unlike XYDispDriver which requires the arguments to exactly match whatever is specified in the type library).
I modified it a little bit to get it also compile under Linux with WineGCC (to produce native Linux elf out of Win32 code), and to handle "by ref" calls automatically (stock disthelper requires the programmer to setup his/her own VARIANT).
My patched version and patches are available as a fork on github:
https://github.com/DrYak/disphelper
And here are my patches :
patch for single source
patch for split source
The problem with the Ole/Com Object Viewer packaged with Visual Studio and Windows SDKs is that it produces a broken .IDL out of the .DLL, which can't further be compiled by MIDL into a .H/.CPP pair.
Wine's own reimplementation of OleViewer is currently unstable and crashes when trying to use those libraries.
I think you should be able to use the free tool Ole/Com Object Viewer to make the header files.