Store/containerized apps support (#4651)

* Initial containerized/Store build

* Remove unsupported APIs

* Remove usage of STL ifstream

* Revert CMake changes

* Link to app runtime

* WCOS/Store cmake

* Update CMakeSettings.json

* Fix winapi family support

* Fix downlevel

* Downlevel build

* Remove downlevel workaround

* pep8 compliance

* Workaround WinRT headers bug

https://github.com/microsoft/cppwinrt/issues/584 in older SDK

* Always cross compile to avoid warnings as errors

* PR feedback

* More CI fixes

* PR feedback

* aiinfra build fix

* Win8 store
This commit is contained in:
Tiago Koji Castro Shibata 2020-09-09 14:36:35 -07:00 committed by GitHub
parent 924ecb0623
commit f7c3e4fa99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 75 additions and 28 deletions

View file

@ -171,7 +171,6 @@ if(NOT WIN32)
set(onnxruntime_ENABLE_INSTRUMENT OFF)
endif()
else()
add_compile_definitions(WINVER=0x0601) # Support Windows 7 and newer
if(WINDOWS_STORE)
# cmake/external/protobuf/src/google/protobuf/compiler/subprocess.cc and onnxruntime/core/platform/windows/env.cc call a bunch of Win32 APIs.
# For now, we'll set the API family to desktop globally to expose Win32 symbols in headers; this must be fixed!
@ -1252,6 +1251,27 @@ else()
list(APPEND onnxruntime_EXTERNAL_LIBRARIES ${CMAKE_DL_LIBS} Threads::Threads)
endif()
if (WIN32)
if (onnxruntime_BUILD_FOR_WINDOWS_STORE)
# Setting WINAPI_FAMILY, WINVER and _WIN32_WINNT restrict the APIs exposed in Windows headers to those available
# in store or desktop, and that support at least the version of Windows specified
# add_compile_definitions(WINAPI_FAMILY=2)
add_compile_definitions(WINVER=0x0A00 _WIN32_WINNT=0x0A00) # Support Windows 10
# /ZW adds /FUplatform.winmd and /FUwindows.winmd. windows.winmd, in turn, overrides the include path for
# the cppwinrt headers, which we set to use the WinML built ones.
# Instead, we use /ZW:nostdlib and force include platform.winml only.
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:SHELL:/ZW:nostdlib /FUplatform.winmd>")
get_filename_component(msvc_path "${CMAKE_C_COMPILER}/../../../.." ABSOLUTE)
link_directories("${msvc_path}/lib/${onnxruntime_target_platform}/store")
add_link_options(/APPCONTAINER)
else()
add_compile_definitions(WINVER=0x0601) # Support Windows 7 and newer
# add_compile_definitions(WINAPI_FAMILY=3)
# FIXME adding _WIN32_WINNT=0x0601 and WINAPI_FAMILY is desirable. However, it hides some symbols that are used in WRL
# headers and breaks the build of WinML. We should have separate WINVER/_WIN32_WINNT definitions for WinML
endif()
endif()
# Default version parts for Microsoft.AI.MachineLearning.dll and onnxruntime.dll in non-ADO pipeline local builds
set(VERSION_MAJOR_PART 0 CACHE STRING "First part of numeric file/product version.")
set(VERSION_MINOR_PART 0 CACHE STRING "Second part of numeric file/product version.")

View file

@ -3,4 +3,6 @@ set(CMAKE_SYSTEM_VERSION 10.0)
if (NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR})
endif()
set(CMAKE_VS_GLOBALS "AppContainerApplication=false")
if (NOT onnxruntime_BUILD_FOR_WINDOWS_STORE)
set(CMAKE_VS_GLOBALS "AppContainerApplication=false")
endif()

View file

@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
if (NOT WINDOWS_STORE)
if (CMAKE_CXX_STANDARD_LIBRARIES MATCHES kernel32.lib)
message(FATAL_ERROR "WinML is only supported on WCOS")
endif()
@ -339,7 +339,7 @@ add_library(winml_lib_image STATIC
# Compiler options
target_compile_features(winml_lib_image PRIVATE cxx_std_17)
target_compile_options(winml_lib_image PRIVATE /GR- /await /wd4238)
target_compile_options(winml_lib_image PRIVATE /GR- /await /wd4238 /wd5205)
# Compiler flags
target_compile_definitions(winml_lib_image PRIVATE WINML_ROOT_NS=${winml_root_ns})
@ -435,7 +435,7 @@ add_library(winml_lib_api STATIC
# Compiler options
target_compile_features(winml_lib_api PRIVATE cxx_std_17)
target_compile_options(winml_lib_api PRIVATE /GR- /await /bigobj /wd4238)
target_compile_options(winml_lib_api PRIVATE /GR- /await /bigobj /wd4238 /wd5205)
# Compiler flags
target_compile_definitions(winml_lib_api PRIVATE WINML_ROOT_NS=${winml_root_ns})

View file

@ -53,6 +53,7 @@ function(add_winml_test)
add_dependencies(${_UT_TARGET} ${_UT_DEPENDS})
endif()
target_link_libraries(${_UT_TARGET} PRIVATE ${_UT_LIBS} gtest winml_google_test_lib ${onnxruntime_EXTERNAL_LIBRARIES} winml_lib_common onnxruntime windowsapp.lib)
target_compile_options(${_UT_TARGET} PRIVATE /wd5205) # workaround cppwinrt SDK bug https://github.com/microsoft/cppwinrt/issues/584
add_test(NAME ${_UT_TARGET}
COMMAND ${_UT_TARGET}

View file

@ -67,7 +67,9 @@ class WindowsThread : public EnvThread {
// This function is called when the threadpool is cancelled.
// TODO: Find a way to avoid calling TerminateThread
void OnCancel() {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
TerminateThread(hThread.get(), 1);
#endif
}
private:
@ -77,9 +79,15 @@ class WindowsThread : public EnvThread {
// TODO: should I try to use SetThreadSelectedCpuSets?
if (!p->thread_options.affinity.empty())
SetThreadAffinityMask(GetCurrentThread(), p->thread_options.affinity[p->index]);
#if WINVER >= _WIN32_WINNT_WIN10
constexpr SetThreadDescriptionFunc pSetThrDesc = SetThreadDescription;
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
// kernel32.dll is always loaded
SetThreadDescriptionFunc pSetThrDesc =
auto pSetThrDesc =
(SetThreadDescriptionFunc)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetThreadDescription");
#else
constexpr SetThreadDescriptionFunc pSetThrDesc = nullptr;
#endif
if (pSetThrDesc != nullptr) {
const ORTCHAR_T* name_prefix =
(p->name_prefix == nullptr || wcslen(p->name_prefix) == 0) ? L"onnxruntime" : p->name_prefix;
@ -180,8 +188,13 @@ class WindowsEnv : public Env {
}
Status GetFileLength(_In_z_ const ORTCHAR_T* file_path, size_t& length) const override {
#if WINVER >= _WIN32_WINNT_WIN8
wil::unique_hfile file_handle{
CreateFileW(file_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)};
CreateFile2(file_path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, OPEN_EXISTING, NULL)};
#else
wil::unique_hfile file_handle{
CreateFileW(file_path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)};
#endif
LARGE_INTEGER filesize;
if (!GetFileSizeEx(file_handle.get(), &filesize)) {
const int err = GetLastError();
@ -223,9 +236,13 @@ class WindowsEnv : public Env {
ORT_RETURN_IF_NOT(file_path);
ORT_RETURN_IF_NOT(offset >= 0);
ORT_RETURN_IF_NOT(length <= buffer.size());
#if WINVER >= _WIN32_WINNT_WIN8
wil::unique_hfile file_handle{
CreateFile2(file_path, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, NULL)};
#else
wil::unique_hfile file_handle{
CreateFileW(file_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)};
#endif
if (file_handle.get() == INVALID_HANDLE_VALUE) {
const int err = GetLastError();
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "open file ", ToMBString(file_path), " fail, errcode = ", err);
@ -400,7 +417,14 @@ class WindowsEnv : public Env {
PathString& canonical_path) const override {
// adapted from MSVC STL std::filesystem::canonical() implementation
// https://github.com/microsoft/STL/blob/ed3cbf36416a385828e7a5987ca52cb42882d84b/stl/inc/filesystem#L2986
#if WINVER >= _WIN32_WINNT_WIN8
wil::unique_hfile file_handle{CreateFile2(
path.c_str(),
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
OPEN_EXISTING,
NULL)};
#else
wil::unique_hfile file_handle{CreateFileW(
path.c_str(),
FILE_READ_ATTRIBUTES,
@ -409,6 +433,7 @@ class WindowsEnv : public Env {
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
nullptr)};
#endif
if (file_handle.get() == INVALID_HANDLE_VALUE) {
const int err = GetLastError();
@ -472,7 +497,11 @@ class WindowsEnv : public Env {
}
virtual Status LoadDynamicLibrary(const std::string& library_filename, void** handle) const override {
#if WINAPI_FAMILY == WINAPI_FAMILY_PC_APP
*handle = ::LoadPackagedLibrary(ToWideString(library_filename).c_str(), 0);
#else
*handle = ::LoadLibraryExA(library_filename.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
#endif
if (!*handle) {
const auto error_code = GetLastError();
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to load library, error code: ", error_code);
@ -537,20 +566,7 @@ class WindowsEnv : public Env {
}
private:
WindowsEnv() : GetSystemTimePreciseAsFileTime_(nullptr) {
// GetSystemTimePreciseAsFileTime function is only available in the latest
// versions of Windows. For that reason, we try to look it up in
// kernel32.dll at runtime and use an alternative option if the function
// is not available.
HMODULE module = GetModuleHandleW(L"kernel32.dll");
if (module != nullptr) {
auto func = (FnGetSystemTimePreciseAsFileTime)GetProcAddress(module, "GetSystemTimePreciseAsFileTime");
GetSystemTimePreciseAsFileTime_ = func;
}
}
typedef VOID(WINAPI* FnGetSystemTimePreciseAsFileTime)(LPFILETIME);
FnGetSystemTimePreciseAsFileTime GetSystemTimePreciseAsFileTime_;
WindowsTelemetry telemetry_provider_;
};
} // namespace

View file

@ -28,9 +28,12 @@ namespace {
class WindowsEnvTime : public EnvTime {
public:
#if WINVER >= _WIN32_WINNT_WIN8
WindowsEnvTime() : GetSystemTimePreciseAsFileTime_(GetSystemTimePreciseAsFileTime) {}
#else
WindowsEnvTime() : GetSystemTimePreciseAsFileTime_(NULL) {
// GetSystemTimePreciseAsFileTime function is only available in the latest
// versions of Windows. For that reason, we try to look it up in
// GetSystemTimePreciseAsFileTime function is only available in
// Windows >= 8. For that reason, we try to look it up in
// kernel32.dll at runtime and use an alternative option if the function
// is not available.
HMODULE module = GetModuleHandleW(L"kernel32.dll");
@ -40,6 +43,7 @@ class WindowsEnvTime : public EnvTime {
GetSystemTimePreciseAsFileTime_ = func;
}
}
#endif
uint64_t NowMicros() override {
if (GetSystemTimePreciseAsFileTime_ != NULL) {

View file

@ -142,7 +142,7 @@ void EtwSink::SendImpl(const Timestamp& timestamp, const std::string& logger_id,
TRACE_LOG_WRITE(TRACE_LEVEL_CRITICAL);
break;
default:
ORT_THROW("Unexpected Severity of " + static_cast<int>(severity));
ORT_THROW("Unexpected Severity of " + std::to_string(static_cast<int>(severity)));
}
}

View file

@ -30,12 +30,16 @@ static bool IsCurrentModuleInSystem32() {
}
static HRESULT GetOnnxruntimeLibrary(HMODULE& module) {
#if WINAPI_FAMILY == WINAPI_FAMILY_PC_APP
auto out_module = LoadPackagedLibrary(L"onnxruntime.dll", 0);
#else
DWORD flags = 0;
#ifdef BUILD_INBOX
flags |= IsCurrentModuleInSystem32() ? LOAD_LIBRARY_SEARCH_SYSTEM32 : 0;
#endif
auto out_module = LoadLibraryExA("onnxruntime.dll", nullptr, flags);
#endif
if (out_module == nullptr) {
return HRESULT_FROM_WIN32(GetLastError());
}
@ -210,4 +214,4 @@ HRESULT OnnxruntimeEnvironment::GetOrtEnvironment(_Out_ OrtEnv** ort_env) {
HRESULT OnnxruntimeEnvironment::EnableDebugOutput(bool is_enabled) {
debug_output_ = is_enabled;
return S_OK;
}
}

View file

@ -1,6 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
#include <gtest/gtest.h>
#include "runtimeParameters.h"
@ -109,4 +109,4 @@ static bool SkipTestsImpactedByOpenMP() {
#else
return false;
#endif
}
}