From 5e0f7412cdb754f814e402fc0e24fc732dba6997 Mon Sep 17 00:00:00 2001 From: Ori Levari Date: Tue, 25 Feb 2020 17:47:02 -0800 Subject: [PATCH] Properly handle downlevel and WCOS scenarios (#3075) --- cmake/CMakeLists.txt | 1 + cmake/onnxruntime.cmake | 11 +++++++++ cmake/winml.cmake | 37 ++++++++-------------------- cmake/winml_unittests.cmake | 30 +++++++++++++++++++--- tools/ci_build/build.py | 2 ++ winml/adapter/pch.h | 2 +- winml/lib/Common/inc/onnx.h | 11 ++++++++- winml/lib/Common/inc/winrt_headers.h | 2 -- winml/test/common/dllload.cpp | 2 +- 9 files changed, 62 insertions(+), 36 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index c09029a54b..3cee60f3f8 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -93,6 +93,7 @@ option(onnxruntime_USE_WINML "Build with WinML support" OFF) option(onnxruntime_USE_ACL "Build with ACL support" OFF) option(onnxruntime_ENABLE_INSTRUMENT "Enable Instrument with Event Tracing for Windows (ETW)" OFF) option(onnxruntime_USE_TELEMETRY "Build with Telemetry" OFF) +option(onnxruntime_ENABLE_WCOS "Build for Windows Core OS" OFF) #The onnxruntime_PREFER_SYSTEM_LIB is mainly designed for package managers like apt/yum/vcpkg. #Please note, by default Protobuf_USE_STATIC_LIBS is OFF but it's recommended to turn it ON on Windows. You should set it properly when onnxruntime_PREFER_SYSTEM_LIB is ON otherwise you'll hit linkage errors. #If you have already installed protobuf(or the others) in your system at the default system paths(like /usr/include), then it's better to set onnxruntime_PREFER_SYSTEM_LIB ON. Otherwise onnxruntime may see two different protobuf versions and we won't know which one will be used, the worst case could be onnxruntime picked up header files from one of them but the binaries from the other one. diff --git a/cmake/onnxruntime.cmake b/cmake/onnxruntime.cmake index 5e92b72166..0d9b892372 100644 --- a/cmake/onnxruntime.cmake +++ b/cmake/onnxruntime.cmake @@ -107,3 +107,14 @@ install(TARGETS onnxruntime RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) set_target_properties(onnxruntime PROPERTIES FOLDER "ONNXRuntime") + +if (onnxruntime_ENABLE_WCOS) + if (NOT onnxruntime_BUILD_SHARED_LIB) + message( + FATAL_ERROR + "Option onnxruntime_ENABLE_WCOS can only be used when onnxruntime_BUILD_SHARED_LIB is also enabled") + endif() + target_link_libraries(onnxruntime PRIVATE windowsapp.lib) + target_link_options(onnxruntime PRIVATE /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:user32.lib /NODEFAULTLIB:gdi32.lib /NODEFAULTLIB:winspool.lib /NODEFAULTLIB:shell32.lib /NODEFAULTLIB:ole32.lib /NODEFAULTLIB:oleaut32.lib /NODEFAULTLIB:uuid.lib /NODEFAULTLIB:comdlg32.lib /NODEFAULTLIB:advapi32.lib) + target_link_options(onnxruntime PRIVATE /DELAYLOAD:api-ms-win-core-libraryloader-l1-2-1.dll) +endif() \ No newline at end of file diff --git a/cmake/winml.cmake b/cmake/winml.cmake index 6277ac4a16..3e0eaefc2c 100644 --- a/cmake/winml.cmake +++ b/cmake/winml.cmake @@ -7,6 +7,8 @@ include(winml_cppwinrt.cmake) # get the current nuget sdk kit directory get_sdk(sdk_folder sdk_version) +get_sdk_include_folder(${sdk_folder} ${sdk_version} sdk_include_folder) +set(dxcore_header "${sdk_include_folder}/um/dxcore.h") set(target_folder ONNXRuntime/winml) set(winml_adapter_dir ${REPO_ROOT}/winml/adapter) set(winml_api_root ${REPO_ROOT}/winml/api) @@ -225,12 +227,6 @@ add_dependencies(winml_adapter ${onnxruntime_EXTERNAL_DEPENDENCIES}) target_precompiled_header(winml_adapter pch.h) # Includes -target_include_directories(winml_adapter PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # windows machine learning generated component headers -target_include_directories(winml_adapter PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api) # windows machine learning generated component headers -target_include_directories(winml_adapter PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml_api/comp_generated) # windows machine learning generated component headers -target_include_directories(winml_adapter PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/winml/sdk/cppwinrt/include) # sdk cppwinrt headers -target_include_directories(winml_adapter PRIVATE ${winml_lib_api_dir}) # needed for generated headers -target_include_directories(winml_adapter PRIVATE ${winml_lib_dir}) target_include_directories(winml_adapter PRIVATE ${winml_adapter_dir}) target_include_directories(winml_adapter PRIVATE ${winml_lib_common_dir}/inc) @@ -239,12 +235,6 @@ set_target_properties(winml_adapter FOLDER ${target_folder}) -# Add deps -add_dependencies(winml_adapter winml_sdk_cppwinrt) -add_dependencies(winml_adapter winml_api) -add_dependencies(winml_adapter winml_api_native) -add_dependencies(winml_adapter winml_api_native_internal) - # Link libraries target_link_libraries(winml_adapter PRIVATE wil) if (onnxruntime_USE_DML) @@ -557,18 +547,11 @@ if (onnxruntime_USE_DML) set(delayload_dml "/DELAYLOAD:directml.dll") endif(onnxruntime_USE_DML) -# The default libraries to link with in Windows are kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib -# Remove them and use the onecore umbrella library instead -foreach(default_lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdgl32.lib advapi32.lib) - set(removed_libs "${removed_libs} /NODEFAULTLIB:${default_lib}") -endforeach() -set(CMAKE_C_STANDARD_LIBRARIES "${removed_libs} onecoreuap.lib") -set(CMAKE_CXX_STANDARD_LIBRARIES "${removed_libs} onecoreuap.lib") -set_target_properties(winml_dll - PROPERTIES - LINK_FLAGS - "/DEF:${WINML_DIR}/windows.ai.machinelearning.def ${os_component_link_flags} /DELAYLOAD:d3d12.dll /DELAYLOAD:d3d11.dll /DELAYLOAD:dxgi.dll ${delayload_dml}") +target_link_options(winml_dll PRIVATE /DEF:${WINML_DIR}/windows.ai.machinelearning.def ${os_component_link_flags} /DELAYLOAD:api-ms-win-core-libraryloader-l1-2-1.dll /DELAYLOAD:api-ms-win-core-threadpool-legacy-l1-1-0.dll /DELAYLOAD:api-ms-win-core-processtopology-obsolete-l1-1-0.dll /DELAYLOAD:api-ms-win-core-kernel32-legacy-l1-1-0.dll /DELAYLOAD:d3d12.dll /DELAYLOAD:d3d11.dll /DELAYLOAD:dxgi.dll ${delayload_dml}) +if (EXISTS ${dxcore_header}) + target_link_options(winml_dll PRIVATE /DELAYLOAD:ext-ms-win-dxcore-l1-*.dll) +endif() set_target_properties(winml_dll PROPERTIES @@ -618,7 +601,7 @@ endif() # When cuda is enabled in the pipeline, it sets CMAKE_SHARED_LINKER_FLAGS which affects all targets including winml_dll. # However, there are no cuda imports in winml_dll, and the linker throws the 4199 warning. # This is needed to allow winml_dll build with cuda enabled. -set_target_properties(winml_dll - PROPERTIES - LINK_FLAGS - "/ignore:4199") \ No newline at end of file +target_link_options(winml_dll PRIVATE /ignore:4199) + +target_link_libraries(winml_dll PRIVATE windowsapp.lib) +target_link_options(winml_dll PRIVATE /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:user32.lib /NODEFAULTLIB:gdi32.lib /NODEFAULTLIB:winspool.lib /NODEFAULTLIB:shell32.lib /NODEFAULTLIB:ole32.lib /NODEFAULTLIB:oleaut32.lib /NODEFAULTLIB:uuid.lib /NODEFAULTLIB:comdlg32.lib /NODEFAULTLIB:advapi32.lib) \ No newline at end of file diff --git a/cmake/winml_unittests.cmake b/cmake/winml_unittests.cmake index 8e35f7e75b..46c1f1cb8c 100644 --- a/cmake/winml_unittests.cmake +++ b/cmake/winml_unittests.cmake @@ -89,11 +89,21 @@ get_winml_test_api_src(${WINML_TEST_SRC_DIR} winml_test_api_src) add_winml_test( TARGET winml_test_api SOURCES ${winml_test_api_src} - LIBS winml_test_common + LIBS winml_test_common delayimp.lib ) target_compile_definitions(winml_test_api PRIVATE BUILD_GOOGLE_TEST) target_precompiled_header(winml_test_api testPch.h) +target_link_libraries(winml_test_api PRIVATE windowsapp.lib) +target_link_options(winml_test_api PRIVATE /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:user32.lib /NODEFAULTLIB:gdi32.lib /NODEFAULTLIB:winspool.lib /NODEFAULTLIB:shell32.lib /NODEFAULTLIB:ole32.lib /NODEFAULTLIB:oleaut32.lib /NODEFAULTLIB:uuid.lib /NODEFAULTLIB:comdlg32.lib /NODEFAULTLIB:advapi32.lib) +target_link_options(winml_test_api PRIVATE /DELAYLOAD:dxgi.dll /DELAYLOAD:d3d12.dll /DELAYLOAD:api-ms-win-core-file-l1-2-2.dll /DELAYLOAD:api-ms-win-core-synch-l1-2-1.dll) +if (onnxruntime_USE_DML) + target_link_options(winml_test_api PRIVATE /DELAYLOAD:directml.dll) +endif() +if (EXISTS ${dxcore_header}) + target_link_options(winml_test_api PRIVATE /DELAYLOAD:ext-ms-win-dxcore-l1-*.dll) +endif() + get_winml_test_scenario_src(${WINML_TEST_SRC_DIR} winml_test_scenario_src winml_test_scenario_libs) add_winml_test( TARGET winml_test_scenario @@ -102,9 +112,21 @@ add_winml_test( ) target_precompiled_header(winml_test_scenario testPch.h) target_compile_definitions(winml_test_scenario PRIVATE BUILD_GOOGLE_TEST) -set_target_properties(winml_test_scenario PROPERTIES LINK_FLAGS - "/DELAYLOAD:d2d1.dll /DELAYLOAD:d3d11.dll /DELAYLOAD:dxgi.dll" -) + +target_link_libraries(winml_test_scenario PRIVATE windowsapp.lib) +target_link_options(winml_test_scenario PRIVATE /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:user32.lib /NODEFAULTLIB:gdi32.lib /NODEFAULTLIB:winspool.lib /NODEFAULTLIB:shell32.lib /NODEFAULTLIB:ole32.lib /NODEFAULTLIB:oleaut32.lib /NODEFAULTLIB:uuid.lib /NODEFAULTLIB:comdlg32.lib /NODEFAULTLIB:advapi32.lib) +target_link_options(winml_test_scenario PRIVATE /DELAYLOAD:d2d1.dll /DELAYLOAD:d3d11.dll /DELAYLOAD:dxgi.dll /DELAYLOAD:d3d12.dll /DELAYLOAD:api-ms-win-core-libraryloader-l1-2-1.dll /DELAYLOAD:api-ms-win-core-file-l1-2-2.dll /DELAYLOAD:api-ms-win-core-synch-l1-2-1.dll) +if (onnxruntime_USE_DML) + target_link_options(winml_test_scenario PRIVATE /DELAYLOAD:directml.dll) +endif() +if (EXISTS ${dxcore_header}) + target_link_options(winml_test_scenario PRIVATE /DELAYLOAD:ext-ms-win-dxcore-l1-*.dll) +endif() + +# necessary for winml_test_scenario because of a still unknown reason, api-ms-win-core-libraryloader-l1-2-1.dll is linked against +# on dev machines but not on the aiinfra agent pool +target_link_options(winml_test_scenario PRIVATE /ignore:4199) + # During build time, copy any modified collaterals. # configure_file(source destination COPYONLY), which configures CMake to copy the file whenever source is modified, diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index f136dd8edd..67663fb6c1 100755 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -164,6 +164,7 @@ Use the individual flags to only run the specified stages. parser.add_argument("--use_dml", action='store_true', help="Build with DirectML.") parser.add_argument("--use_winml", action='store_true', help="Build with WinML.") parser.add_argument("--use_telemetry", action='store_true', help="Only official builds can set this flag to enable telemetry.") + parser.add_argument("--enable_wcos", action='store_true', help="Build for Windows Core OS.") parser.add_argument("--enable_lto", action='store_true', help="Enable Link Time Optimization") return parser.parse_args() @@ -343,6 +344,7 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home "-Donnxruntime_USE_DML=" + ("ON" if args.use_dml else "OFF"), "-Donnxruntime_USE_WINML=" + ("ON" if args.use_winml else "OFF"), "-Donnxruntime_USE_TELEMETRY=" + ("ON" if args.use_telemetry else "OFF"), + "-Donnxruntime_ENABLE_WCOS=" + ("ON" if args.enable_wcos else "OFF"), "-Donnxruntime_ENABLE_LTO=" + ("ON" if args.enable_lto else "OFF"), ] diff --git a/winml/adapter/pch.h b/winml/adapter/pch.h index c448ebc5f8..9e353e8890 100644 --- a/winml/adapter/pch.h +++ b/winml/adapter/pch.h @@ -3,7 +3,7 @@ #pragma once -#include "cppwinrt_onnx.h" +#include "onnx.h" #include "wil/wrl.h" #include "dx.h" diff --git a/winml/lib/Common/inc/onnx.h b/winml/lib/Common/inc/onnx.h index 9ef407d4a8..1519bc2948 100644 --- a/winml/lib/Common/inc/onnx.h +++ b/winml/lib/Common/inc/onnx.h @@ -3,7 +3,16 @@ #pragma once -#include "common.h" +// STL +#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING +#define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING + +#include +#ifdef OPTIONAL +#undef OPTIONAL +#endif + +#pragma warning(disable : 4100) // Needed to work around the fact that OnnxRuntime defines ERROR #ifdef ERROR diff --git a/winml/lib/Common/inc/winrt_headers.h b/winml/lib/Common/inc/winrt_headers.h index 3b02581a2c..0b31d32c44 100644 --- a/winml/lib/Common/inc/winrt_headers.h +++ b/winml/lib/Common/inc/winrt_headers.h @@ -15,6 +15,4 @@ #include "Windows.AI.MachineLearning.Native.h" #include "Windows.AI.MachineLearning.Native.Internal.h" -#pragma warning(disable : 4100) - #include "Errors.h" \ No newline at end of file diff --git a/winml/test/common/dllload.cpp b/winml/test/common/dllload.cpp index 01de69da11..db27ad1741 100644 --- a/winml/test/common/dllload.cpp +++ b/winml/test/common/dllload.cpp @@ -32,7 +32,7 @@ HRESULT __stdcall WINRT_RoGetActivationFactory(HSTRING classId_hstring, GUID con if (starts_with(name, L"Windows.AI.MachineLearning.")) { const wchar_t* libPath = winmlDllPath.c_str(); - library = LoadLibraryW(libPath); + library = LoadLibraryExW(libPath, nullptr, 0); } else {