|
| 1 | +include_guard(GLOBAL) |
| 2 | + |
| 3 | +if(NOT DEFINED BINARY_DIR) |
| 4 | + message(SEND_ERROR "Callers must provide BINARY_DIR") |
| 5 | +endif() |
| 6 | + |
| 7 | +if(NOT DEFINED BUILD_TYPE) |
| 8 | + message(SEND_ERROR "Callers must provide BUILD_TYPE") |
| 9 | +endif() |
| 10 | + |
| 11 | +if(NOT DEFINED ENV{USE_WARP_FROM_NUGET}) |
| 12 | + message(SEND_ERROR "Callers must set a string value for the environment variable USE_WARP_FROM_NUGET." |
| 13 | + "Either 'LATEST_RELEASE' or 'LATEST_PREVIEW'") |
| 14 | +endif() |
| 15 | + |
| 16 | +set(USE_WARP_FROM_NUGET $ENV{USE_WARP_FROM_NUGET}) |
| 17 | + |
| 18 | +# Downloads nuget.exe to the given path if it doesn't exist yet. |
| 19 | +function(EnsureNugetExists target_path) |
| 20 | + # Download the latest nuget.exe to the given path. |
| 21 | + if(NOT EXISTS ${target_path}) |
| 22 | + message(STATUS "Installing nuget.exe to ${target_path}...") |
| 23 | + file(DOWNLOAD |
| 24 | + https://dist.nuget.org/win-x86-commandline/latest/nuget.exe |
| 25 | + ${target_path} |
| 26 | + ) |
| 27 | + endif() |
| 28 | +endfunction() |
| 29 | + |
| 30 | +# Download the latest nuget package for the given ID. Can pass in a custom source, defaults to nuget public feed. |
| 31 | +function(GetNuGetPackageLatestVersion) |
| 32 | + set(params NAME ID SOURCE OUTPUT_DIR OUTPUT_VARIABLE PREVIEW) |
| 33 | + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "${params}" "") |
| 34 | + |
| 35 | + if(NOT ARG_OUTPUT_DIR) |
| 36 | + set(ARG_OUTPUT_DIR ) |
| 37 | + endif() |
| 38 | + |
| 39 | + set(nuget_exe_path "${ARG_OUTPUT_DIR}\\nuget.exe install") |
| 40 | + EnsureNugetExists(${nuget_exe_path}) |
| 41 | + |
| 42 | + if (${ARG_ID}_LATEST_VERSION) |
| 43 | + set(${ARG_OUTPUT_VARIABLE} ${${ARG_ID}_LATEST_VERSION} PARENT_SCOPE) |
| 44 | + else() |
| 45 | + if(NOT ARG_SOURCE) |
| 46 | + set(ARG_SOURCE https://api.nuget.org/v3/index.json) |
| 47 | + endif() |
| 48 | + |
| 49 | + if(NOT ARG_PREVIEW) |
| 50 | + set(ARG_PREVIEW OFF) |
| 51 | + endif() |
| 52 | + |
| 53 | + if(ARG_PREVIEW) |
| 54 | + # Note that '-Prerelease' options will only return a prerelease package if that is also the latest. |
| 55 | + # If you want a prerelease package with an older version number than the latest release package then you |
| 56 | + # need to pass a specific version number. |
| 57 | + message("Will add '-Prelease' to nuget list command") |
| 58 | + set(prerelease "-Prerelease") |
| 59 | + endif() |
| 60 | + |
| 61 | + execute_process( |
| 62 | + COMMAND ${nuget_exe_path} |
| 63 | + list ${ARG_ID} |
| 64 | + -Source ${ARG_SOURCE} |
| 65 | + ${prerelease} |
| 66 | + RESULT_VARIABLE result |
| 67 | + OUTPUT_VARIABLE nuget_list_output |
| 68 | + OUTPUT_STRIP_TRAILING_WHITESPACE |
| 69 | + ) |
| 70 | + |
| 71 | + if(NOT ${result} STREQUAL "0") |
| 72 | + message(FATAL_ERROR "NuGet failed to find latest version of package ${ARG_ID} with exit code ${result}.") |
| 73 | + endif() |
| 74 | + |
| 75 | + # Get last line of running nuget.exe list <ID>. |
| 76 | + string(REPLACE "\n" ";" nuget_list_output ${nuget_list_output}) |
| 77 | + list(POP_BACK nuget_list_output nuget_list_last_line) |
| 78 | + if(nuget_list_last_line STREQUAL "No packages found.") |
| 79 | + message(FATAL_ERROR "NuGet failed to find latest version of package ${ARG_ID}.") |
| 80 | + endif() |
| 81 | + |
| 82 | + # The last line should have the format <ID> <VERSION> |
| 83 | + string(REPLACE " " ";" nuget_list_last_line ${nuget_list_last_line}) |
| 84 | + list(POP_BACK nuget_list_last_line nuget_version) |
| 85 | + |
| 86 | + if(NOT nuget_version) |
| 87 | + message(FATAL_ERROR "NuGet failed to find latest version of package ${ARG_ID}.") |
| 88 | + endif() |
| 89 | + |
| 90 | + message("Nuget found version:${nuget_version} for ${ARG_ID}") |
| 91 | + |
| 92 | + # Save output variable and cache the result so subsequent calls to the version-unspecified package |
| 93 | + # are faster. |
| 94 | + set(${ARG_OUTPUT_VARIABLE} ${nuget_version} PARENT_SCOPE) |
| 95 | + set(${ARG_ID}_LATEST_VERSION ${nuget_version} CACHE INTERNAL "") |
| 96 | + endif() |
| 97 | +endfunction() |
| 98 | + |
| 99 | +# Installs a NuGet package under OUTPUT_DIR. |
| 100 | +# |
| 101 | +# FetchNuGetPackage( |
| 102 | +# ID Microsoft.Direct3D.WARP |
| 103 | +# VERSION 1.0.13 |
| 104 | +# SOURCE https://api.nuget.org/v3/index.json |
| 105 | +# ) |
| 106 | +# |
| 107 | +# This function sets a variable <name>_SOURCE_DIR (e.g. Microsoft.Direct3D.WARP_SOURCE_DIR in above example) to the |
| 108 | +# extract NuGet package contents. |
| 109 | +function(FetchNuGetPackage) |
| 110 | + set(params NAME ID VERSION SOURCE OUTPUT_DIR RELEASE_TYPE) |
| 111 | + cmake_parse_arguments(PARSE_ARGV 0 ARG "" "${params}" "") |
| 112 | + |
| 113 | + # The NAME parameter is optional: if it's not set then the package ID is used as the name. The |
| 114 | + # reason for having a separate NAME is to allow a consistent identifier for packages whose ID |
| 115 | + # changes with each release (e.g. GDK). |
| 116 | + if(NOT ARG_NAME) |
| 117 | + set(ARG_NAME ${ARG_ID}) |
| 118 | + endif() |
| 119 | + |
| 120 | + if(NOT ARG_OUTPUT_DIR) |
| 121 | + set(ARG_OUTPUT_DIR ${BINARY_DIR}/temp) |
| 122 | + endif() |
| 123 | + |
| 124 | + set(nuget_exe_path ${ARG_OUTPUT_DIR}/nuget.exe) |
| 125 | + |
| 126 | + if(NOT ARG_SOURCE) |
| 127 | + set(ARG_SOURCE https://api.nuget.org/v3/index.json) |
| 128 | + endif() |
| 129 | + |
| 130 | + if(NOT ARG_RELEASE_TYPE) |
| 131 | + set(ARG_RELEASE_TYPE "LATEST_RELEASE") |
| 132 | + endif() |
| 133 | + |
| 134 | + set(PREVIEW OFF) |
| 135 | + |
| 136 | + if(${ARG_RELEASE_TYPE} STREQUAL "LATEST_PREVIEW") |
| 137 | + set(PREVIEW ON) |
| 138 | + endif() |
| 139 | + |
| 140 | + # Default to latest version |
| 141 | + if(NOT ARG_VERSION) |
| 142 | + GetNuGetPackageLatestVersion( |
| 143 | + ID ${ARG_ID} |
| 144 | + SOURCE ${ARG_SOURCE} |
| 145 | + PREVIEW ${PREVIEW} |
| 146 | + OUTPUT_DIR ${ARG_OUTPUT_DIR} |
| 147 | + OUTPUT_VARIABLE ARG_VERSION |
| 148 | + ) |
| 149 | + endif() |
| 150 | + |
| 151 | + set(nupkg_path ${ARG_OUTPUT_DIR}/${ARG_ID}.${ARG_VERSION}/${ARG_ID}.${ARG_VERSION}.nupkg) |
| 152 | + |
| 153 | + if(NOT EXISTS ${nupkg_path}) |
| 154 | + message(STATUS "NuGet: adding package ${ARG_ID}.${ARG_VERSION}") |
| 155 | + |
| 156 | + EnsureNugetExists(${nuget_exe_path}) |
| 157 | + |
| 158 | + set(retry_count 0) |
| 159 | + set(max_retries 10) |
| 160 | + set(retry_delay 10) |
| 161 | + set(result 1) |
| 162 | + |
| 163 | + # Run NuGet CLI to download the package. |
| 164 | + while(NOT ${result} STREQUAL "0" AND ${retry_count} LESS ${max_retries}) |
| 165 | + message(STATUS "'${nuget_exe_path}' install '${ARG_ID}' -Version '${ARG_VERSION}' -Source '${ARG_SOURCE}' -OutputDirectory '${ARG_OUTPUT_DIR}' -DependencyVersion Ignore -Verbosity quiet") |
| 166 | + execute_process( |
| 167 | + COMMAND |
| 168 | + ${nuget_exe_path} |
| 169 | + install ${ARG_ID} |
| 170 | + -Version ${ARG_VERSION} |
| 171 | + -Source ${ARG_SOURCE} |
| 172 | + -OutputDirectory ${ARG_OUTPUT_DIR} |
| 173 | + -DependencyVersion Ignore |
| 174 | + -Verbosity quiet |
| 175 | + RESULT_VARIABLE result |
| 176 | + ) |
| 177 | + if(NOT ${result} STREQUAL "0") |
| 178 | + math(EXPR retry_count "${retry_count} + 1") |
| 179 | + |
| 180 | + message(STATUS "Nuget failed: '${result}'. Retrying in ${retry_delay} seconds...") |
| 181 | + execute_process( |
| 182 | + COMMAND |
| 183 | + ${CMAKE_COMMAND} -E sleep ${retry_delay} |
| 184 | + ) |
| 185 | + endif() |
| 186 | + endwhile() |
| 187 | + |
| 188 | + if(NOT ${result} STREQUAL "0") |
| 189 | + message(FATAL_ERROR "NuGet failed: '${result}' Package '${ARG_NAME}' (${ARG_ID}.${ARG_VERSION})") |
| 190 | + endif() |
| 191 | + endif() |
| 192 | + |
| 193 | + # Set output variable. The NAME parameter is optional: if it's not set then the package ID is used as the |
| 194 | + # name. The reason for having a separate NAME is for packages whose IDs change (e.g. GDK) so that callers |
| 195 | + # can use a fixed name in dependents. Example, targets can reference gdk_SOURCE_DIR with the snippet below |
| 196 | + # instead of having to reference Microsoft.GDK.PC.230300_SOURCE_DIR. |
| 197 | + # |
| 198 | + # FetchNuGetPackage( |
| 199 | + # NAME gdk |
| 200 | + # ID Microsoft.GDK.PC.220300 |
| 201 | + # VERSION 10.0.22621.3049 |
| 202 | + # ) |
| 203 | + set(${ARG_NAME}_SOURCE_DIR ${ARG_OUTPUT_DIR}/${ARG_ID}.${ARG_VERSION} PARENT_SCOPE) |
| 204 | +endfunction() |
| 205 | + |
| 206 | +# Begin the 'main' logic of this file. Previous code is all defintions. |
| 207 | +message("USE_WARP_FROM_NUGET: ${USE_WARP_FROM_NUGET}") |
| 208 | +if(${USE_WARP_FROM_NUGET} STREQUAL "LATEST_RELEASE" OR ${USE_WARP_FROM_NUGET} STREQUAL "LATEST_PREVIEW") |
| 209 | + |
| 210 | + message("Fetching warp from nuget") |
| 211 | + |
| 212 | + FetchNuGetPackage(ID Microsoft.Direct3D.WARP OUTPUT_DIR ${BINARY_DIR}/temp RELEASE_TYPE ${USE_WARP_FROM_NUGET}) |
| 213 | + |
| 214 | + if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") |
| 215 | + set(ARCH "x64") |
| 216 | + endif() |
| 217 | + if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "X86") |
| 218 | + set(ARCH "win32") |
| 219 | + endif() |
| 220 | + if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ARM64") |
| 221 | + set(ARCH "arm64") |
| 222 | + endif() |
| 223 | + |
| 224 | + set(WARP_SOURCE_PATH "${Microsoft.Direct3D.WARP_SOURCE_DIR}/build/native/bin/${ARCH}") |
| 225 | + set(WARP_DEST_PATH "${BINARY_DIR}/${BUILD_TYPE}/bin/") |
| 226 | + message("Copying d3d10warp.dll and d3d10warp.pdb \n" |
| 227 | + " from: ${WARP_SOURCE_PATH}\n" |
| 228 | + " to: ${WARP_DEST_PATH}") |
| 229 | + file(COPY "${WARP_SOURCE_PATH}/d3d10warp.dll" |
| 230 | + DESTINATION "${WARP_DEST_PATH}") |
| 231 | + file(COPY "${WARP_SOURCE_PATH}/d3d10warp.pdb" |
| 232 | + DESTINATION "${WARP_DEST_PATH}") |
| 233 | +endif() |
0 commit comments