| 1 | function(add_idl target idl_files_with_proxy idl_files_no_proxy) |
| 2 | set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}) |
| 3 | file(MAKE_DIRECTORY ${OUTPUT_DIR}) |
| 4 | set(TARGET_OUTPUTS) |
| 5 | |
| 6 | set(IDL_DEFINITIONS "") |
| 7 | |
| 8 | get_directory_property(IDL_DEFS COMPILE_DEFINITIONS ) |
| 9 | foreach(e ${IDL_DEFS}) |
| 10 | set(IDL_DEFINITIONS ${IDL_DEFINITIONS} /D${e}) |
| 11 | endforeach() |
| 12 | |
| 13 | string(TOLOWER ${TARGET_PLATFORM} IDL_ENV) |
| 14 | set(PREVIOUS_OUTPUT "") |
| 15 | |
| 16 | set(IDL_DLLDATA ${OUTPUT_DIR}/dlldata_${TARGET_PLATFORM}.c) |
| 17 | |
| 18 | list(LENGTH idl_files_with_proxy PROXY_IDL_COUNT) |
| 19 | set(PROXY_IDL_INDEX 0) |
| 20 | |
| 21 | foreach(idl_file ${idl_files_with_proxy}) |
| 22 | |
| 23 | cmake_path(GET idl_file STEM IDL_NAME) |
| 24 | |
| 25 | set(IDL_HEADER ${OUTPUT_DIR}/${IDL_NAME}.h) |
| 26 | |
| 27 | # Adding a _${TARGET_PLATFORM} to work around object files having |
| 28 | # the same paths regardless of TARGET_PLATFORM, which can cause the linker to fail with: |
| 29 | # "fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'ARM64'" |
| 30 | set(IDL_I ${OUTPUT_DIR}/${IDL_NAME}_i_${TARGET_PLATFORM}.c) |
| 31 | set(IDL_P ${OUTPUT_DIR}/${IDL_NAME}_p_${TARGET_PLATFORM}.c) |
| 32 | |
| 33 | # Only list dlldata as a tracked output of the last MIDL command. |
| 34 | math(EXPR PROXY_IDL_INDEX "${PROXY_IDL_INDEX} + 1") |
| 35 | if(PROXY_IDL_INDEX EQUAL PROXY_IDL_COUNT) |
| 36 | set(MIDL_OUTPUT ${IDL_HEADER} ${IDL_I} ${IDL_P} ${IDL_DLLDATA}) |
| 37 | else() |
| 38 | set(MIDL_OUTPUT ${IDL_HEADER} ${IDL_I} ${IDL_P}) |
| 39 | endif() |
| 40 | |
| 41 | add_custom_command( |
| 42 | OUTPUT ${MIDL_OUTPUT} |
| 43 | COMMAND midl /nologo /target NT100 /env "${IDL_ENV}" /Zp8 /char unsigned /ms_ext /c_ext /h ${IDL_HEADER} /iid ${IDL_I} /proxy ${IDL_P} /dlldata ${IDL_DLLDATA} ${idl_file} ${IDL_DEFINITIONS} |
| 44 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} |
| 45 | DEPENDS ${idl_file} ${PREVIOUS_OUTPUT} |
| 46 | MAIN_DEPENDENCY ${idl_file} |
| 47 | VERBATIM |
| 48 | ) |
| 49 | |
| 50 | set(PREVIOUS_OUTPUT ${IDL_HEADER}) |
| 51 | |
| 52 | set_source_files_properties(${MIDL_OUTPUT} PROPERTIES GENERATED TRUE) |
| 53 | list(APPEND TARGET_OUTPUTS ${MIDL_OUTPUT}) |
| 54 | |
| 55 | endforeach() |
| 56 | |
| 57 | foreach(idl_file ${idl_files_no_proxy}) |
| 58 | |
| 59 | cmake_path(GET idl_file STEM IDL_NAME) |
| 60 | |
| 61 | set(IDL_HEADER ${OUTPUT_DIR}/${IDL_NAME}.h) |
| 62 | |
| 63 | add_custom_command( |
| 64 | OUTPUT ${IDL_HEADER} |
| 65 | COMMAND midl /nologo /target NT100 /env "${IDL_ENV}" /Zp8 /char unsigned /ms_ext /c_ext /h ${IDL_HEADER} /iid nul /proxy nul /dlldata nul ${idl_file} ${IDL_DEFINITIONS} |
| 66 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} |
| 67 | DEPENDS ${idl_file} |
| 68 | MAIN_DEPENDENCY ${idl_file} |
| 69 | VERBATIM |
| 70 | ) |
| 71 | |
| 72 | set_source_files_properties(${IDL_HEADER} PROPERTIES GENERATED TRUE) |
| 73 | list(APPEND TARGET_OUTPUTS ${IDL_HEADER}) |
| 74 | |
| 75 | endforeach() |
| 76 | |
| 77 | # Touch the stamp file so Visual Studio's incremental build can track the |
| 78 | # target as up-to-date. |
| 79 | add_custom_target(${target} |
| 80 | COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target} |
| 81 | DEPENDS ${TARGET_OUTPUTS} |
| 82 | SOURCES ${idl_files_with_proxy} ${idl_files_no_proxy}) |
| 83 | |
| 84 | endfunction() |
| 85 | |
| 86 | function(add_idl_winrt target idl_file) |
| 87 | set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}) |
| 88 | file(TO_NATIVE_PATH ${OUTPUT_DIR} OUTPUT_DIR) # midl is picky about path formats |
| 89 | file(MAKE_DIRECTORY ${OUTPUT_DIR}) |
| 90 | |
| 91 | set(IDL_DEFINITIONS "") |
| 92 | |
| 93 | get_directory_property(IDL_DEFS COMPILE_DEFINITIONS ) |
| 94 | foreach(e ${IDL_DEFS}) |
| 95 | set(IDL_DEFINITIONS ${IDL_DEFINITIONS} /D${e}) |
| 96 | endforeach() |
| 97 | |
| 98 | string(TOLOWER ${TARGET_PLATFORM} IDL_ENV) |
| 99 | |
| 100 | cmake_host_system_information( |
| 101 | RESULT WINDOWS_SDK_DIR |
| 102 | QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/Microsoft/Windows Kits/Installed Roots" |
| 103 | VALUE "KitsRoot10") |
| 104 | set(WINRT_METADATA_DIR "${WINDOWS_SDK_DIR}\\UnionMetadata\\${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") |
| 105 | set(WINRT_REFERENCE "${WINRT_METADATA_DIR}\\Windows.winmd") |
| 106 | set(WINRT_INCLUDE "${WINDOWS_SDK_DIR}\\Include\\${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}\\winrt") |
| 107 | |
| 108 | cmake_path(GET idl_file STEM IDL_NAME) |
| 109 | |
| 110 | set(IDL_WINMD ${OUTPUT_DIR}/${IDL_NAME}.winmd) |
| 111 | |
| 112 | add_custom_command( |
| 113 | OUTPUT ${IDL_WINMD} |
| 114 | COMMAND midl /nologo /nomidl /winrt /metadata_dir "${WINRT_METADATA_DIR}" /reference "${WINRT_REFERENCE}" /I "${WINRT_INCLUDE}" /env "${IDL_ENV}" /h nul /winmd ${IDL_WINMD} ${idl_file} ${IDL_DEFINITIONS} |
| 115 | COMMAND cppwinrt -input ${IDL_WINMD} -reference "${WINRT_REFERENCE}" -output ${OUTPUT_DIR} -comp ${OUTPUT_DIR}/implementation_base -optimize -pch precomp.h -prefix |
| 116 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} |
| 117 | DEPENDS ${idl_file} |
| 118 | MAIN_DEPENDENCY ${idl_file} |
| 119 | VERBATIM |
| 120 | ) |
| 121 | |
| 122 | set_source_files_properties(${IDL_WINMD} PROPERTIES GENERATED TRUE) |
| 123 | |
| 124 | add_custom_target(${target} |
| 125 | COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target} |
| 126 | DEPENDS ${IDL_WINMD} |
| 127 | SOURCES ${idl_file}) |
| 128 | |
| 129 | endfunction() |