Это своего рода продолжение Как использовать midlrt.exe для компиляции .idl в .winmd?
У меня есть это в моем CMakeLists.txt. Мои вопросы связаны не столько с логикой CMake, сколько с выводом команд midl и cppwinrt, а также с последующими ошибками при компиляции и компоновке. Я подозреваю, что мне не хватает некоторых параметров командной строки.
# Pathnames for WinRT References
set (WINSDKREFDIR "$ENV{WindowsSdkDir}References\\$ENV{WindowsSDKVersion}")
# Remove trailing \ from $ENV{WindowsSDKVersion}
string (REGEX MATCH "[^\\]*" WINSDKVER $ENV{WindowsSDKVersion})
# COMMAND lines wrapped in this post for readability, not wrapped in the actual CMakeLists.txt
add_custom_target (MYLIB_PREBUILD ALL
COMMAND midl /winrt /ns_prefix /x64 /nomidl
/metadata_dir
"${WINSDKREFDIR}windows.foundation.foundationcontract\\3.0.0.0"
/reference
"${WINSDKREFDIR}windows.foundation.foundationcontract\\3.0.0.0\\Windows.Foundation.FoundationContract.winmd"
/reference
"${WINSDKREFDIR}Windows.Foundation.UniversalApiContract\\8.0.0.0\\Windows.Foundation.UniversalApiContract.winmd"
/out "${MYDIR}\\GeneratedFiles" "${MYDIR}\\MyClass.idl"
COMMAND cppwinrt
-in "${MYDIR}\\GeneratedFiles\\MyClass.winmd"
-ref ${WINSDKVER} -component -pch "pch.h" -out "${MYDIR}\\GeneratedFiles"
)
add_dependencies (MYLIB MYLIB_PREBUILD)
В команде cppwinrt я пробовал разные формы параметров -ref [spec] и -pch, но, похоже, все равно получил те же результаты. Вот проблемы, с которыми я столкнулся:
MIDLRT создает заголовочный файл MyClass.h с несколькими проблемами:
- It #includes <windows.h>, which ultimately #defines preprocessor macros for GetClassName and GetCurrentTime that cause compiler errors in WinRT functions with those names.
- Я потратил несколько часов на отслеживание этого и научился компилировать с #define COM_NO_WINDOWS_H, чтобы предотвратить это.
- It #includes non-existent *.h files from WinRT References Contracts directories instead of the Include directories:
- #include "C:\Program Files (x86)\Windows Kits\10\References\10.0.18362.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.h"
- #include C: \ Program Files (x86) \ Windows Kits \ 10 \ References \ 10.0.18362.0 \ Windows.Foundation.UniversalApiContract \ 8.0.0.0 \ Windows.Foundation.UniversalApiContract.h
- Я сделал копию этого файла и заменил ее на #include ‹winrt / Windows.Foundation.h›
CPPWINRT создает module.g.cpp, который # включает MyNamespace.MyClass.h, но не создает также этот файл .h. Он генерирует MyNamespace / MyClass.h (примечание / вместо.), Поэтому я создал первый .h и просто #include второй .h из него.
CPPWINRT не генерирует все базовые заголовки, которые я вижу в примерах Microsoft. Он генерирует только заголовки, непосредственно связанные с MyClass - например, определение базового класса шаблона winrt :: MyNamespace :: implementation :: MyClassT ‹›, оболочки winrt :: MyNamespace :: MyClass и т. Д.
winrt :: MyNamespace :: factory_implementation :: MyClass не определен. MyClassT ‹› определен там, но не MyClass. Я нахожу для этого парадигму из примера Microsoft и вставляю ее:
// Missing from the generated stuff -- derived from a Microsoft example:
namespace winrt::MyNamespace::factory_implementation
{
struct MyClass : MyClassT<MyClass, implementation::MyClass>
{
};
}
- Я получил предупреждения компилятора о несогласованных определениях CHECK_NS_PREFIX_STATE: в некоторых местах это было всегда, а в других - никогда. Итак, теперь я #define MIDL_NS_PREFIX и #define CHECK_NS_PREFIX_STATE = always
Теперь сборка проходит через компилятор, но у меня в компоновщике есть неразрешенные внешние символы. Я думаю, что эти вещи должны быть определены встроенными в winrt / base.h, но cppwinrt не экспортировал такой файл (как я вижу в примерах Microsoft), а эквивалентный файл в системном каталоге содержит только прототипы, а не тела:
WINRT_GetRestrictedErrorInfo
WINRT_RoInitialize
WINRT_RoOriginateLanguageException
WINRT_SetRestrictedErrorInfo
WINRT_WindowsCreateString
WINRT_WindowsCreateStringReference
WINRT_WindowsDeleteString
WINRT_WindowsPreallocateStringBuffer
WINRT_WindowsDeleteStringBuffer
WINRT_WindowsPromoteStringBuffer
WINRT_WindowsGetStringRawBuffer
WINRT_RoGetActivationFactory
WINRT_WindowsDuplicateString
Я упустил какую-то простую вещь, которая решила бы все эти проблемы с отсутствующими, неполными или некорректно сгенерированными файлами?