Background: I need to build a Windows Runtime Component as part of a system that's set up to use CMake to generate its build system. As a preparatory step I'm trying to build it on the command line.
Starting with a bare-bones .idl file (MyType.idl)
namespace NS
{
[default_interface]
runtimeclass MyType
{
}
}
I'm trying to generate a matching .winmd file using the midlrt.exe tool. The following command line (split across several lines for readability)
midlrt
/metadata_dir "%WindowsSdkDir%References\%WindowsSDKVersion%Windows.Foundation.FoundationContract\3.0.0.0"
/reference "%WindowsSdkDir%References\%WindowsSDKVersion%Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd"
/winmd MyType.winmd
/notlb
/winrt
/nomidl
/nologo
/enum_class
/ns_prefix
/client none
/server none
MyType.idl
generates the MyType.winmd file just fine, but I don't know why. I'm particularly confused about the /metadata_dir
and /reference
options. Running midlrt /help
offers the following:
/metadata_dir Specify one or more directories containing platform metadata files
/reference Specify one or more WinMD files to import
The official documentation on /metadata_dir doesn't add much to that (other than a confusing remark: "Use this switch to specify the location of the main metadata file for Windows, which is named windows.winmd."). There is no documentation for /reference
.
Here's what I need help with:
/metadata_dir
option? As used in the command line above it looks like a redundant replication of part of the /reference
option. Leaving it out produces compiler errors, though./reference
s including their particular version(s)?/metadata_dir is required to tell MIDLRT where it can find the definitions of foundational types that MIDLRT requires for historical reasons. Practically, this must point to the directory containing the winmd that defines the types from the Windows.Foundation namespace in the Windows SDK, but you can use C:\Windows\System32\WinMetadata if you are in a pinch (as the former is hard to track down). Obviously, you'll only want to do this for testing/experimentation since you'll be at the whim of whatever build of the OS you happen to be running on. The correct form looks something like this:
midlrt sample.idl /metadata_dir "C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0"
Finding this path is tricky. Start by finding the SDK install path in the registry. Then pick the SDK version you wish to target. Then find the latest version of the foundation contract. You can look at how C++/WinRT does this here:
https://github.com/microsoft/xlang/blob/master/src/library/impl/cmd_reader_windows.h
/reference is a newer feature where you can use it to import the definitions from a winmd rather than having to import/include the definitions using IDL. This is mainly an optimization as this tends to be much faster than including the corresponding IDL definitions.
You still need to use /metadata_dir regardless of whether you use /reference as they are used for different things. This is different to cppwinrt.exe where it only has a single harmonized -reference flag.