[libcxx] Provide #include_next alternative for MSVC
Needs ReviewPublic

Authored by bcraig on Apr 23 2017, 6:58 PM.

Details

Summary

Visual Studio 2015 and 2017 don't implement include_next, so we'll use a combination of a computed include and CMAKE inputs to make it work. Also, retrofit all the existing invocations of #include_next that we could hit in a hypothetical MSVC build.

This relies on implementation defined behavior in the MSVC preprocessor.
See C11, 6.10.2.4 ("Source file inclusion") for the statement on implementation defined vs. undefined.

Diff Detail

bcraig created this revision.Apr 23 2017, 6:58 PM

Here is how we solved this problem in our libc++ fork:

#define _LIBCPP_UCRT_INCLUDE(x) <../ucrt/x>
#define _LIBCPP_MSVC_INCLUDE(x) <../../VC/include/x>
#ifdef _LIBCPP_COMPILER_MSVC
#include _LIBCPP_UCRT_INCLUDE(wchar.h)
#else
#include_next <wchar.h>
#endif

As far as I understand neither solution resolves the problem with original paths not excluded. Watch out for cycling dependencies created by MSVC includes using other includes which point right back to libc++ instead.

Also, there is a problem with errno macro. I solved it like this:

#ifdef _LIBCPP_COMPILER_MSVC
// errno is defined in several files so we can't use #ifndef errno here
#ifdef errno
// undefine errno to avoid substitution in errno.h include file name.
#pragma push_macro("errno")
#undef errno
#include _LIBCPP_UCRT_INCLUDE(errno.h)
#pragma pop_macro("errno")
#else
#include _LIBCPP_UCRT_INCLUDE(errno.h)
#endif
#else
#include_next <errno.h>
#endif

BTW, the list of include files which are located in [PROGRAM_FILES]\Microsoft Visual Studio 14.0\VC\include directory is

  • stdbool.h
  • limits.h
  • stdint.h
  • setjmp.h

The rest is in [PROGRAM_FILES]\Windows Kits\10\Include\10.0.whatever.0\ucrt directory. Which directory @_LIBCPP_INCLUDE_NEXT@ is supposed to point to?

BTW, the list of include files which are located in [PROGRAM_FILES]\Microsoft Visual Studio 14.0\VC\include directory is

  • stdbool.h
  • limits.h
  • stdint.h
  • setjmp.h

    The rest is in [PROGRAM_FILES]\Windows Kits\10\Include\10.0.whatever.0\ucrt directory. Which directory @_LIBCPP_INCLUDE_NEXT@ is supposed to point to?

My immediate goal is getting a sort-of freestanding implementation of libc++ to work in the Windows kernel. That means that I have _LIBCPP_INCLUDE_NEXT defined as ../../km/crt.

I'll have to stew on what I want the solution to this to be. I don't feel bad at all switching between one compiler extension (#include_next) and another (computed includes). I would feel a little bad cooking in more knowledge of the MSVC directory layout though. Maybe that's just the cost to pay though. There is some pretty deep knowledge of glibc headers in libc++, so it wouldn't be terribly unusual to have similar knowledge of the MSVC CRT.

The errno changes you are suggesting may be fine, but I wasn't planning on addressing them with this patch.

bcraig added a comment.May 4 2017, 7:18 PM

I'm still working on this.

Things I've learned: A clang install is bundled with re-implementations of several of these headers. The default #include_next behavior ends up pulling in lots of those.

I have been able to get things working with a VC include path and a UCRT include path, but the default include paths set by the compiler driver cause the clang versions of stdarg.h and vadefs.h to get pulled in. The combination of clang include path and ucrt include path also works.

I did end up running into the same errno problems that were mentioned earlier, and ended up coming to the same workaround.

bcraig updated this revision to Diff 100650.May 29 2017, 6:40 PM
bcraig edited the summary of this revision. (Show Details)
smeenai resigned from this revision.Tue, Jun 27, 10:01 AM

Sorry, I've been meaning to respond for a while.

This is kinda ugly, but I can't think of a better way to do it. I'm fine with this, but given that it's a pretty invasive change, I'm not comfortable accepting. You may wanna ping @EricWF and @mclow.lists directly.

@smeenai wrote:

This is kinda ugly, but I can't think of a better way to do it. I'm fine with this, but given that it's a pretty invasive change, I'm not comfortable accepting. You may wanna ping @EricWF and @mclow.lists directly.

I'll be meeting with the MS compiler engineers next week; I'll see when/if they plan on implemementing include_next.

@smeenai wrote:

This is kinda ugly, but I can't think of a better way to do it. I'm fine with this, but given that it's a pretty invasive change, I'm not comfortable accepting. You may wanna ping @EricWF and @mclow.lists directly.

I'll be meeting with the MS compiler engineers next week; I'll see when/if they plan on implemementing include_next.

How was a meeting in Toronto? Did they say anything about #include_next?