UWP/WinRT Headers are Fun (not)

As established before, <windows.h> is a bit of a mess that has accumulated over 30+ years. Symbols in global namespace, preprocessor macros, ugh:

#include <windows.h>
// my code
void* GetObject(...);
// welp, GetObject is actually GetObjectW now

So naturally, someone at Microsoft decided it’s time to make a “v2” API set for programming Windows, without any of the horrors of the past, using more modern approaches, and so on. And so in 2012 Windows Runtime was born.

No more preprocessor hijacking identifiers! No more global namespaces! …hmm. or is it? Try this (tested with Windows SDK 10.0.16299.0, VS2017):

class Plane;
#include <windows.ui.core.h>

What does the compiler say?

Windows.Foundation.Numerics.h(490): error C2371: 'ABI::Windows::Foundation::Numerics::Plane': redefinition; different basic types
Windows.Foundation.Numerics.h(317): note: see declaration of 'ABI::Windows::Foundation::Numerics::Plane'

Compiling with /W3 tells more detail on why that happens:

Windows.Foundation.Numerics.h(317): warning C4099: 'Plane': type name first seen using 'class' now seen using 'struct'
test.cpp(2): note: see declaration of 'Plane'

Lo and behold, turns out that Windows.Foundation.Numerics.h (which is included by a lot of WinRT headers) has this:

namespace ABI {
    namespace Windows {
        namespace Foundation {
            namespace Numerics {                
                typedef struct Plane Plane;
            } 
        } 
    } 
} 

The code tried to be namespace-aware, but typedef struct Plane Plane apparently is not. Why does it have that thing in the first place? No idea!

But this means you can’t forward-declare classes/structs, that match WinRT structs/classes (even inside namespaces!), before including WinRT headers. Your own forward-declarations have to come after WinRT header inclusion.

Since that pattern in headers essentially creates code like this, which is a compile error on all C++ compilers:

class Plane;
namespace Test
{
    typedef struct Plane Plane;
    struct Plane { int a; };
}
// clang 5.0.0:
// warning: struct 'Plane' was previously declared as a class [-Wmismatched-tags]
// error: definition of type 'Plane' conflicts with typedef of the same name
//
// vs2017:
// warning C4099: 'Plane': type name first seen using 'class' now seen using 'struct'
// error C2371: 'Test::Plane': redefinition; different basic types
//
// gcc 7.2:
// error: using typedef-name 'Test::Plane' after 'struct'

“Great” job, WinRT headers. At least in WinAPI times I could undo most of the damage with some #undef

:sadpanda:


Header Hero Improvements

There’s a neat little tool for optimizing C++ codebase header #include dependencies: Header Hero (thanks Niklas for making it!).

It can give an estimate of “how many lines of code” end up being parsed by the compiler, when all the header files have been included. I suggest you read the original post about it. A more recent post from Niklas at how they are approaching the header file problem now is very interesting too; though I’m not convinced it scales beyond “a handful of people” team sizes.

Anyway. I just made some small improvements to Header Hero while using it on our codebase:

Precompiled Headers

I added a new field at the bottom of the main UI where a “precompiled header” file can be indicated. Everything included into that header file will be not counted into “lines of code parsed” lists that the UI shows in the report.

What goes into the precompiled header itself is shown at the bottom of the report window:

Small UI tweaks

Added quick links to “list of largest files” and “list of most included files” (hubs) at top of build report. Initially I did not even know the UI had the “hubs” list, since it was so far away on the scrollbar :)

Switched the “Includes” tab to have file lists with columns (listing include count / line count), and added a “go to previous file” button for navigation.

That’s it! Get them on bitbucket here.


Helped to Build a School in Cameroon

One thing led to another, and I funded construction of a new primary school in Cameroon. The school is built & working now. Yay!

What? How? Why?

It started out in a fairly unusual way, around September 2016. US election thing was nearing completion, and the guy who founded Oculus funded some shitposting campaign related to it. Cliff Harris wrote a blogpost about it:

The thing is, its really very EASY to do good things when you have a lot of spare money. I built a school in Africa for £18,000. Thats $23,000. I tried to work out what that was as a percentage of 700 million but my calculator goes into exponential results. Its fucking trivial. By the way, it involves zero effort just an email and then a bank transfer. You don’t get to have “a real jolly good time”, but you help people in the developing world get an education.

And that made me go “what? you can build a school?! that sounds interesting…”

For about a month I had this thought in the background, occasionally reading about various similar things. And then, because I’m generally a very unimaginative person with no original ideas, I just wrote an email to the same Building Schools for Africa (BSFA) organization that Cliff has built his school with.

Why? Because it sounded like a good thing to do, and my understanding is that more accessible primary education & clean water are fairly effective ways of help.

The Process

By middle of November 2016 I’ve agreed with BSFA that I’m willing to fund construction of a new primary school, and they with their Cameroon partner SHUMAS will start researching for possible locations & evaluating things.

However at end of 2016 a crisis between Anglophone and Francophone parts of Cameroon has emerged, including a teachers strike and an internet ban, and the school finding process has dragged out a bit.

A proposal for a school site, including feasibility analysis & budgeting, was done by February 2017. The proposed location is in Meyomessala village, Dja et Lobo division of the South region of Cameroon. Somewhere here is my guess. The village is home to some 7500 people.

A bilingual primary school has already existed in the village since 2009. Currently about 200 children attend it. However it never had any classrooms or equipment (!), borrowing temporary space from another nearby French school instead.

So the proposal was:

  • Construction of 3 new classrooms and an office.
  • Construction of a toilet block with associated hand-washing facilities.
  • Equipment of these classrooms with benches, tables and chairs.
  • Water provision for the school through the construction of a water borehole.

The total cost of funding was about 25 thousand Euros. This isn’t a trivial amount of money, but on the other hand, it’s basically as much as a new fairly non-remarkable car. So YMMV.

By April a 40 meter water borehole got constructed (funding for it was provided by someone else; not part of my budget):

During June-August most of the school construction was happening:

And then the school was almost done!

The Result

By November the school was operating, and the formal handover to BSFA happened on their Cameroon trip in December.

I will get updates on how the school is doing from BSFA after 1 and 2 years, will be interesting to see.

Thanks BSFA and SHUMAS for doing the actual work of school construction, and Cliff for being an inspiration.


Minimizing <windows.h>

I’ve been looking at our (Unity game engine) C++ codebase header file hygiene a bit, and this is a short rant-post about <windows.h>.

On all Microsoft platforms, our precompiled header was including <windows.h> since about forever, and so effectively the whole codebase was getting all the symbols and macros from it. Now of course, the part of the codebase that actually needs to use Windows API is very small, so I thought “hey, let’s see what happens if I stop making windows headers be included everywhere”.

But why would you want that?

Good question! I don’t know if I do, yet. Conceptually, since only very small part of the codebase needs to use stuff from windows headers, it “feels wrong” to include it everywhere. It might still make sense to keep it in the precompiled header, if that helps with build performance.

“Precompiled headers, grandpa?! What about C++ modules?”

It’s true that C++ modules perhaps one day will make precompiled headers obsolete. Good to see that the major compilers (MSVC, clang, gcc) have some level of implementation of them now.

Not all our platforms are on these compilers; and some others are not on recent enough versions yet. So… I dunno, some years in the future? But maybe we’ll just be writing Rust by then, who knows :)

Anyway. Just how large <windows.h> actually is? In VS2017 (version 15.5, Windows SDK 10.0.16299), after preprocessing and ignoring empty lines, it ends up being 69100 lines of actual code. When defining WIN32_LEAN_AND_MEAN before inclusion to cut down some rarely used parts, it ends up being 33375 lines. That’s not massive, but not trivially small either.

For comparison, here are line counts (after preprocessing, removing empty lines) of various STL headers in the same compiler:

  • <vector> 20354
  • <string> 26355
  • <unordered_map> 24291
  • <map> 21144
  • <algorithm> 18578
  • vector+string+unordered_map+algorithm 35957
  • <cstdlib> 1800; just <stdlib.h> itself: 1184. C was small and neat!

Actual problem with windows.h: macros

Back to task at hand! So, remove <windows.h> from precompiled header, hit build and off you go, perhaps sprinkling a now-needed windows include here and there, right? Of course, wrong :)

Others have said it in harsher words, but the gist is: Windows headers define a lot of symbols as preprocessor macros. While min and max are optional (define NOMINMAX before including), some others like near and far are not.

And then of course a bunch of function names that Windows maps to either ANSI or Unicode variants with a preprocessor. SendMessage, GetObject, RegisterClass, DrawText, CreateFile and so on. Good thing these are obscure names that another codebase would never want to use… oh wait. These are the exact function names that caused problems in my attempt.

If you have a central place where you include the windows headers, you could #undef them after inclusion, and make your own code explicitly do SendMessageW instead of using a macro.

But then there’s some 3rd party libraries that include windows.h from their own header files. I’m looking at you, Enlighten, Oculus PC SDK, CEF and others. Ugh!

Modular/smaller windows.h

There are other ways to approach this problem, of course.

One is to not have any Windows-specific things in many/any of your header files, wrap everything into a nice little set of Windows-specific source files, only include windows headers there, and go on doing fun things. That would be ideal, but is not a five minute job in a large existing codebase.

If you don’t need many things from Windows headers, you could declare the minimal set that you need yourself, manually. Contrary to what some Stack Overflow threads say (“why WAIT_OBJECT_0 is defined to be STATUS_WAIT_0 + 0? because the values might not be the same in the future!” – err nope, they can’t realistically ever change their values), it’s not a terribly dangerous thing to do. Windows API is one of the most stable APIs in the history of computing, after all.

Here’s an example of a minimal set of manually defined Windows things that Direct3D 9 needs, from @zeuxcg: Minimal set of headers for D3D9.

Another example is hand-crafted, quite extensive windows headers replacement from @ArvidGerstmann: Modular Windows.h Header File.

However, even Windows headers themselves can be used in a much more modular way directly! What I found so far is this:

  • Preprocessor macro _AMD64_ (for x64), _X86_ (for x86) or _ARM_ (for ARM) has to be defined by you, and then,
  • You can include one of the many “smaller” headers:
    • <windef.h> to get most of the base types (DWORD, HWND, …) as well as atomic functions and stuff. 7811 lines of actual code.
    • <fileapi.h> for file functions (CreateFile, FindFirstFile, …), 7773 lines.
    • <synchapi.h> for synchronization primitives (WaitForMultipleObjects, InitializeCriticalSection, …), 8450 lines.
    • <debugapi.h> for IsDebuggerPresent, OutputDebugString etc. No need to include whole thing for it :)
  • The Windows SDK headers, at least in Win10 versions, seem to be structured in a fairly stable way, and with same partition of these smaller header files across Win32, XboxOne and UWP platforms.

This is all.


2017 Holidays Giveaway

I told the internet I’d buy books and stuff for people, and you won’t believe what happened next!

45 people got books and stuff.

FIN.

Backstory

I wrote this on both mastodon and twitter:

Let’s try some “we’ll probably make it through 2017” gifts. Do you need a book, a course, an app, a workshop, github, hosting, or something else that would help you? Something in $50-$100 range; ping me and I’ll try to do it!

Why? Dunno, sounded like that would be a nice thing to do. And then I got two requests, which I fulfilled, and then… nothing. However, I repeated the same thing the next day, during a more US-friendly hour, and then the requests started flowing in.

Expectations

This being the internet, I expected totally random and weird things. A million requests, a bunch of trolls, a bunch of nonsense, etc.

I’m happy to report that the internet managed to pleasantly surprise me in how well it behaved in this particular occasion!

Requests

In the end I gave gifts to 45 strangers on the internet before calling it a day, and here’s what they turned out to be.

Unsurprisingly enough, majority were something about computers.

  • 13 books: 11 on programming, 2 on art/design.
  • 5 courses or tutorials: 3 on programming, 2 on art.
  • 9 items of physical hardware: a couple of Raspberry Pi 3s, leapmotion, 360 camera, daydream VR viewer etc.
  • 4 software licenses: Git Tower (twice), Gamemaker Studio 2, ArtStation Pro.

Of course, the most interesting requests are those that are not computer related :)

Was really surprised by amount of people saying “I don’t need anything myself, but if you could donate to charity/nonprofit X that would be great”. 13% of all requests being of that kind is pretty sweet! For some of the requests I decided to go for a larger than $50-$100 contribution. Here’s what people asked to donate to:

And of course, “everything else” is where it was fairly random. I bought tree saplings, socks, room heater, covered an electricity bill, vet expenses and so on. Very interesting!

Tips and Findings

  • Buying stuff for strangers on the internet is easiest via Amazon wishlists. I pretty much got this ready-to-paste for inquiries: “Can you create a wishlist on Amazon, add the item to it, setup a shipping address and give me the link?” One big advantage – it does not disclose actual address, phone or other personal details to me; and overall it’s way easier than filling in whole shipping forms.
  • Keep on mind though that for each and every new shipping address, Amazon will ask you to re-enter your credit card details. This makes sense for security purposes, but in this particular scenario it means re-entering them each.and.every.time. Your own Amazon UI for shipping address choices will become a mess in the end as well, and will need some cleanup.
  • Shipping costs are very real! Both you & me probably have a “oh yeah, a book is like $50” mental image, but depending on where it needs to be shipped that can end up anywhere in $50 to $100 for the same book.
  • Time investment wise, I probably have spent 15-20 hours on all this, during evenings over a few days. With some people it took quite a few roundtrips of back & forth messaging until I got a concrete actionable thing (URL of a thing: actionable, “I want a book I saw last week”: not so much :)). Maybe next time it would be easier, given that now I know I should just tell people “yo, gimmeh your amazon wishlist” fast-track.

It was quite a lot of fun and felt good! If you have money to spare, I can definitely recommend.