From be7ddfc4cd020ce47dfa35783307b880e952c050 Mon Sep 17 00:00:00 2001
From: cdevelop <cdevelop@qq.com>
Date: 星期一, 13 十一月 2023 16:15:05 +0800
Subject: [PATCH] runtime windows build (#1082)

---
 runtime/onnxruntime/src/precomp.h                                      |   15 
 runtime/onnxruntime/third_party/glog/src/logging.cc                    |   99 ++
 runtime/onnxruntime/third_party/glog/src/glog/vlog_is_on.h.in          |    8 
 runtime/onnxruntime/third_party/openfst/src/lib/CMakeLists.txt         |    2 
 runtime/onnxruntime/third_party/glog/src/stacktrace_libunwind-inl.h    |    2 
 runtime/onnxruntime/third_party/glog/src/stacktrace_unittest.cc        |    9 
 runtime/onnxruntime/third_party/glog/src/windows/dirent.h              | 1145 ++++++++++++++++++++++++++++
 runtime/onnxruntime/third_party/yaml-cpp/include/yaml-cpp/exceptions.h |    2 
 runtime/onnxruntime/src/vocab.cpp                                      |    2 
 runtime/onnxruntime/src/audio.cpp                                      |    2 
 runtime/onnxruntime/third_party/glog/src/stacktrace.h                  |    2 
 runtime/onnxruntime/third_party/glog/src/config.h.cmake.in             |    5 
 runtime/onnxruntime/third_party/yaml-cpp/src/exceptions.cpp            |    2 
 runtime/onnxruntime/bin/CMakeLists.txt                                 |   29 
 runtime/onnxruntime/third_party/glog/src/demangle.cc                   |   68 +
 runtime/onnxruntime/CMakeLists.txt                                     |    5 
 runtime/onnxruntime/third_party/jieba/include/limonp/Logging.hpp       |    2 
 runtime/onnxruntime/third_party/glog/src/raw_logging.cc                |   13 
 runtime/onnxruntime/third_party/glog/src/glog/raw_logging.h.in         |    7 
 runtime/onnxruntime/third_party/glog/src/vlog_is_on.cc                 |   12 
 runtime/onnxruntime/src/funasrruntime.cpp                              |    4 
 runtime/onnxruntime/third_party/glog/src/windows/port.cc               |   75 +
 runtime/onnxruntime/third_party/glog/src/base/commandlineflags.h       |    9 
 runtime/onnxruntime/src/bias-lm.h                                      |    3 
 runtime/websocket/bin/funasr-wss-server-2pass.cpp                      |    7 
 runtime/websocket/bin/funasr-wss-server.cpp                            |    4 
 runtime/onnxruntime/src/win_func.h                                     |   38 
 runtime/onnxruntime/third_party/glog/cmake/GetCacheVariables.cmake     |    2 
 runtime/onnxruntime/readme.md                                          |   90 +
 runtime/onnxruntime/src/CMakeLists.txt                                 |   20 
 runtime/websocket/CMakeLists.txt                                       |    9 
 runtime/onnxruntime/third_party/kaldi/CMakeLists.txt                   |   26 
 runtime/onnxruntime/third_party/glog/CMakeLists.txt                    |  148 ++-
 runtime/onnxruntime/third_party/glog/cmake/TestPackageConfig.cmake     |   18 
 runtime/onnxruntime/third_party/glog/src/glog/logging.h.in             |   65 
 runtime/websocket/readme_zh.md                                         |   40 
 runtime/onnxruntime/third_party/glog/src/utilities.cc                  |    2 
 runtime/onnxruntime/third_party/glog/src/demangle.h                    |    2 
 /dev/null                                                              |  120 ---
 runtime/onnxruntime/third_party/glog/src/symbolize.h                   |    4 
 runtime/onnxruntime/third_party/glog/src/signalhandler.cc              |   10 
 runtime/onnxruntime/third_party/glog/src/utilities.h                   |    9 
 runtime/onnxruntime/third_party/glog/src/windows/port.h                |  181 ++++
 runtime/onnxruntime/third_party/glog/src/stacktrace_powerpc-inl.h      |    2 
 runtime/onnxruntime/third_party/glog/src/mock-log.h                    |    7 
 runtime/onnxruntime/third_party/glog/src/symbolize.cc                  |    4 
 runtime/onnxruntime/third_party/openfst/src/include/fst/log.h          |    2 
 runtime/websocket/bin/CMakeLists.txt                                   |   33 
 48 files changed, 1,978 insertions(+), 387 deletions(-)

diff --git a/runtime/onnxruntime/CMakeLists.txt b/runtime/onnxruntime/CMakeLists.txt
index 2f193b0..a922f21 100644
--- a/runtime/onnxruntime/CMakeLists.txt
+++ b/runtime/onnxruntime/CMakeLists.txt
@@ -20,11 +20,6 @@
 
 # for onnxruntime
 IF(WIN32)
-	if(CMAKE_CL_64)
-		link_directories(${ONNXRUNTIME_DIR}\\lib)
-	else()
-		add_definitions(-D_WIN_X86)
-	endif()
 ELSE()
     link_directories(${ONNXRUNTIME_DIR}/lib)
     link_directories(${FFMPEG_DIR}/lib)
diff --git a/runtime/onnxruntime/bin/CMakeLists.txt b/runtime/onnxruntime/bin/CMakeLists.txt
index 4870922..856ab68 100644
--- a/runtime/onnxruntime/bin/CMakeLists.txt
+++ b/runtime/onnxruntime/bin/CMakeLists.txt
@@ -1,33 +1,42 @@
 include_directories(${CMAKE_SOURCE_DIR}/include)
 
-add_executable(funasr-onnx-offline "funasr-onnx-offline.cpp")
+if(WIN32)
+add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/execution-charset:utf-8>")
+add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/source-charset:utf-8>")
+include_directories(${ONNXRUNTIME_DIR}/include)
+include_directories(${FFMPEG_DIR}/include)
+include_directories(${PROJECT_SOURCE_DIR}/third_party)
+SET(RELATION_SOURCE "../src/audio.cpp" "../src/resample.cpp" "../src/util.cpp" "../src/alignedmem.cpp" "../src/encode_converter.cpp")
+endif()
+
+add_executable(funasr-onnx-offline "funasr-onnx-offline.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-offline PUBLIC funasr)
 
-add_executable(funasr-onnx-offline-vad "funasr-onnx-offline-vad.cpp")
+add_executable(funasr-onnx-offline-vad "funasr-onnx-offline-vad.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-offline-vad PUBLIC funasr)
 
-add_executable(funasr-onnx-online-vad "funasr-onnx-online-vad.cpp")
+add_executable(funasr-onnx-online-vad "funasr-onnx-online-vad.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-online-vad PUBLIC funasr)
 
-add_executable(funasr-onnx-online-asr "funasr-onnx-online-asr.cpp")
+add_executable(funasr-onnx-online-asr "funasr-onnx-online-asr.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-online-asr PUBLIC funasr)
 
-add_executable(funasr-onnx-offline-punc "funasr-onnx-offline-punc.cpp")
+add_executable(funasr-onnx-offline-punc "funasr-onnx-offline-punc.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-offline-punc PUBLIC funasr)
 
-add_executable(funasr-onnx-online-punc "funasr-onnx-online-punc.cpp")
+add_executable(funasr-onnx-online-punc "funasr-onnx-online-punc.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-online-punc PUBLIC funasr)
 
-add_executable(funasr-onnx-offline-rtf "funasr-onnx-offline-rtf.cpp")
+add_executable(funasr-onnx-offline-rtf "funasr-onnx-offline-rtf.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-offline-rtf PUBLIC funasr)
 
-add_executable(funasr-onnx-2pass "funasr-onnx-2pass.cpp")
+add_executable(funasr-onnx-2pass "funasr-onnx-2pass.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-2pass PUBLIC funasr)
 
-add_executable(funasr-onnx-2pass-rtf "funasr-onnx-2pass-rtf.cpp")
+add_executable(funasr-onnx-2pass-rtf "funasr-onnx-2pass-rtf.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-2pass-rtf PUBLIC funasr)
 
-add_executable(funasr-onnx-online-rtf "funasr-onnx-online-rtf.cpp")
+add_executable(funasr-onnx-online-rtf "funasr-onnx-online-rtf.cpp" ${RELATION_SOURCE})
 target_link_libraries(funasr-onnx-online-rtf PUBLIC funasr)
 
 # include_directories(${FFMPEG_DIR}/include)
diff --git a/runtime/onnxruntime/readme.md b/runtime/onnxruntime/readme.md
index d63010f..1309717 100644
--- a/runtime/onnxruntime/readme.md
+++ b/runtime/onnxruntime/readme.md
@@ -1,34 +1,56 @@
-# Please ref to [websocket service](https://github.com/alibaba-damo-academy/FunASR/tree/main/runtime/websocket)
-
-# If you want to compile the file yourself, you can follow the steps below.
-## Building for Linux/Unix
-### Download onnxruntime
-```shell
-wget https://github.com/microsoft/onnxruntime/releases/download/v1.14.0/onnxruntime-linux-x64-1.14.0.tgz
-tar -zxvf onnxruntime-linux-x64-1.14.0.tgz
-```
-
-### Download ffmpeg
-```shell
-wget https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/dep_libs/ffmpeg-N-111383-g20b8688092-linux64-gpl-shared.tar.xz
-tar -xvf ffmpeg-N-111383-g20b8688092-linux64-gpl-shared.tar.xz
-```
-
-### Install deps
-```shell
-# openblas
-sudo apt-get install libopenblas-dev #ubuntu
-# sudo yum -y install openblas-devel #centos
-
-# openssl
-apt-get install libssl-dev #ubuntu 
-# yum install openssl-devel #centos
-```
-
-### Build runtime
-```shell
-git clone https://github.com/alibaba-damo-academy/FunASR.git && cd FunASR/runtime/onnxruntime
-mkdir build && cd build
-cmake  -DCMAKE_BUILD_TYPE=release .. -DONNXRUNTIME_DIR=/path/to/onnxruntime-linux-x64-1.14.0 -DFFMPEG_DIR=/path/to/ffmpeg-N-111383-g20b8688092-linux64-gpl-shared
-make -j 4
-```
\ No newline at end of file
+# Please ref to [websocket service](https://github.com/alibaba-damo-academy/FunASR/tree/main/runtime/websocket)
+
+# If you want to compile the file yourself, you can follow the steps below.
+## Building for Linux/Unix
+### Download onnxruntime
+```shell
+wget https://github.com/microsoft/onnxruntime/releases/download/v1.14.0/onnxruntime-linux-x64-1.14.0.tgz
+tar -zxvf onnxruntime-linux-x64-1.14.0.tgz
+```
+
+### Download ffmpeg
+```shell
+wget https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/dep_libs/ffmpeg-N-111383-g20b8688092-linux64-gpl-shared.tar.xz
+tar -xvf ffmpeg-N-111383-g20b8688092-linux64-gpl-shared.tar.xz
+```
+
+### Install deps
+```shell
+# openblas
+sudo apt-get install libopenblas-dev #ubuntu
+# sudo yum -y install openblas-devel #centos
+
+# openssl
+apt-get install libssl-dev #ubuntu 
+# yum install openssl-devel #centos
+```
+
+### Build runtime
+```shell
+git clone https://github.com/alibaba-damo-academy/FunASR.git && cd FunASR/runtime/onnxruntime
+mkdir build && cd build
+cmake  -DCMAKE_BUILD_TYPE=release .. -DONNXRUNTIME_DIR=/path/to/onnxruntime-linux-x64-1.14.0 -DFFMPEG_DIR=/path/to/ffmpeg-N-111383-g20b8688092-linux64-gpl-shared
+make -j 4
+```
+
+
+## Building for Windows
+### Download onnxruntime
+https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl-\shared.zip
+
+Download and unzip to d:\ffmpeg-master-latest-win64-gpl-shared
+
+### Download ffmpeg
+https://github.com/microsoft/onnxruntime/releases/download/v1.16.1/onnxruntime-win-x64-1.16.1.zip
+
+Download and unzip to d:\onnxruntime-win-x64-1.16.1
+
+### Build runtime
+```
+git clone https://github.com/alibaba-damo-academy/FunASR.git
+cd FunASR/runtime/onnxruntime
+mkdir build
+cd build
+cmake ../ -D FFMPEG_DIR=d:/ffmpeg-master-latest-win64-gpl-shared -D ONNXRUNTIME_DIR=d:/onnxruntime-win-x64-1.16.1
+```
+Visual Studio open FunASROnnx.sln start build
\ No newline at end of file
diff --git a/runtime/onnxruntime/src/CMakeLists.txt b/runtime/onnxruntime/src/CMakeLists.txt
index 042be49..1a2ca63 100644
--- a/runtime/onnxruntime/src/CMakeLists.txt
+++ b/runtime/onnxruntime/src/CMakeLists.txt
@@ -4,18 +4,20 @@
 
 message("files: "${files})
 
+if(WIN32)
+add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/execution-charset:utf-8>")
+add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/source-charset:utf-8>")
+endif()
+
 add_library(funasr SHARED ${files})
 
 if(WIN32)
-    set(EXTRA_LIBS pthread yaml-cpp csrc kaldi-decoder fst glog gflags)
-    if(CMAKE_CL_64)
-        target_link_directories(funasr PUBLIC ${CMAKE_SOURCE_DIR}/win/lib/x64)
-    else()
-        target_link_directories(funasr PUBLIC ${CMAKE_SOURCE_DIR}/win/lib/x86)
-    endif()
-    target_include_directories(funasr PUBLIC ${CMAKE_SOURCE_DIR}/win/include )
-    
-    target_compile_definitions(funasr PUBLIC -D_FUNASR_API_EXPORT)
+    set(EXTRA_LIBS yaml-cpp csrc kaldi-decoder fst glog gflags avutil avcodec avformat swresample onnxruntime)
+    include_directories(${ONNXRUNTIME_DIR}/include)
+    include_directories(${FFMPEG_DIR}/include)
+    target_link_directories(funasr PUBLIC ${ONNXRUNTIME_DIR}/lib)
+    target_link_directories(funasr PUBLIC ${FFMPEG_DIR}/lib)
+    target_compile_definitions(funasr PUBLIC -D_FUNASR_API_EXPORT -DNOMINMAX -DYAML_CPP_DLL)
 else()
     set(EXTRA_LIBS pthread yaml-cpp csrc kaldi-decoder fst glog gflags avutil avcodec avformat swresample)
     include_directories(${ONNXRUNTIME_DIR}/include)
diff --git a/runtime/onnxruntime/src/audio.cpp b/runtime/onnxruntime/src/audio.cpp
index 76a01f9..b543797 100644
--- a/runtime/onnxruntime/src/audio.cpp
+++ b/runtime/onnxruntime/src/audio.cpp
@@ -1193,7 +1193,7 @@
                 }
 
             }else if(speech_end_i != -1){ // [-1,100]
-                if(speech_start == -1 or speech_offline_start == -1){
+                if(speech_start == -1 || speech_offline_start == -1){
                     LOG(ERROR) <<"Vad start is null while vad end is available. Set vad start 0" ;
                     speech_start = 0;
                 }
diff --git a/runtime/onnxruntime/src/bias-lm.h b/runtime/onnxruntime/src/bias-lm.h
index 7254d49..e2d28a2 100644
--- a/runtime/onnxruntime/src/bias-lm.h
+++ b/runtime/onnxruntime/src/bias-lm.h
@@ -7,6 +7,9 @@
 #include "vocab.h"
 #include "util/text-utils.h"
 #include <yaml-cpp/yaml.h>
+#ifdef _WIN32
+#include "win_func.h"
+#endif
 // node type
 #define ROOT_NODE 0
 #define VALUE_ZERO 0.0f
diff --git a/runtime/onnxruntime/src/funasrruntime.cpp b/runtime/onnxruntime/src/funasrruntime.cpp
index dd6bb17..3523bba 100644
--- a/runtime/onnxruntime/src/funasrruntime.cpp
+++ b/runtime/onnxruntime/src/funasrruntime.cpp
@@ -266,7 +266,7 @@
 			if(msg_vec.size()==0){
 				continue;
 			}
-			if(lang == "en-bpe" and p_result->msg != ""){
+			if(lang == "en-bpe" && p_result->msg != ""){
 				p_result->msg += " ";
 			}
 			p_result->msg += msg_vec[0];
@@ -355,7 +355,7 @@
 			if(msg_vec.size()==0){
 				continue;
 			}
-			if(lang == "en-bpe" and p_result->msg != ""){
+			if(lang == "en-bpe" && p_result->msg != ""){
 				p_result->msg += " ";
 			}
 			p_result->msg += msg_vec[0];
diff --git a/runtime/onnxruntime/src/precomp.h b/runtime/onnxruntime/src/precomp.h
index d74608c..776de8e 100644
--- a/runtime/onnxruntime/src/precomp.h
+++ b/runtime/onnxruntime/src/precomp.h
@@ -18,20 +18,7 @@
 #include <cstring>
 
 #ifdef _WIN32
-#include<io.h>
-#ifndef R_OK
-#define R_OK 4
-#endif
-#ifndef W_OK
-#define W_OK 2
-#endif
-#ifndef X_OK
-#define X_OK 0 
-#endif
-#ifndef F_OK
-#define F_OK 0
-#endif
-#define access _access
+#include <win_func.h>
 #else
 #include <unistd.h>
 #endif
diff --git a/runtime/onnxruntime/src/vocab.cpp b/runtime/onnxruntime/src/vocab.cpp
index bdedd84..d29281c 100644
--- a/runtime/onnxruntime/src/vocab.cpp
+++ b/runtime/onnxruntime/src/vocab.cpp
@@ -199,7 +199,7 @@
         }
     }
 
-    if (language == "en-bpe" and combine != ""){
+    if (language == "en-bpe" && combine != ""){
         combine = WordFormat(combine);
         if (words.size() != 0){
             combine = " " + combine;
diff --git a/runtime/onnxruntime/src/win_func.h b/runtime/onnxruntime/src/win_func.h
new file mode 100644
index 0000000..b5a16df
--- /dev/null
+++ b/runtime/onnxruntime/src/win_func.h
@@ -0,0 +1,38 @@
+#ifndef WIN_FUNC_
+#define WIN_FUNC_
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define  WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <winsock.h>
+#include<io.h>
+
+#ifndef R_OK
+#define R_OK 4
+#endif
+#ifndef W_OK
+#define W_OK 2
+#endif
+#ifndef X_OK
+#define X_OK 0 
+#endif
+#ifndef F_OK
+#define F_OK 0
+#endif
+#define access _access
+
+static inline int gettimeofday(struct timeval* tv, void* /*tz*/) {
+    FILETIME ft;
+    ULARGE_INTEGER li;
+    ULONGLONG tt;
+    GetSystemTimeAsFileTime(&ft);
+    li.LowPart = ft.dwLowDateTime;
+    li.HighPart = ft.dwHighDateTime;
+    tt = (li.QuadPart - 116444736000000000ULL) / 10;
+    tv->tv_sec = tt / 1000000;
+    tv->tv_usec = tt % 1000000;
+    return 0;
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/runtime/onnxruntime/third_party/glog/CMakeLists.txt b/runtime/onnxruntime/third_party/glog/CMakeLists.txt
index f5c1e55..b6b3a1a 100644
--- a/runtime/onnxruntime/third_party/glog/CMakeLists.txt
+++ b/runtime/onnxruntime/third_party/glog/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 3.16)
+cmake_minimum_required (VERSION 3.21)
 project (glog
   VERSION 0.7.0
   DESCRIPTION "C++ implementation of the Google logging module"
@@ -131,6 +131,7 @@
 check_cxx_symbol_exists (backtrace execinfo.h HAVE_EXECINFO_BACKTRACE)
 check_cxx_symbol_exists (backtrace_symbols execinfo.h
   HAVE_EXECINFO_BACKTRACE_SYMBOLS)
+check_cxx_symbol_exists (_chsize_s io.h HAVE__CHSIZE_S)
 
 # NOTE gcc does not fail if you pass a non-existent -Wno-* option as an
 # argument. However, it will happily fail if you pass the corresponding -W*
@@ -213,50 +214,61 @@
 endif (WITH_TLS)
 
 set (_PC_FIELDS
-  "gregs[REG_PC]"
-  "gregs[REG_EIP]"
-  "gregs[REG_RIP]"
-  "sc_ip"
-  "uc_regs->gregs[PT_NIP]"
-  "gregs[R15]"
-  "arm_pc"
-  "mc_eip"
-  "mc_rip"
-  "__gregs[REG_EIP]"
-  "__gregs[REG_RIP]"
-  "ss.eip"
-  "__ss.__eip"
-  "ss.rip"
-  "__ss.__rip"
-  "ss.srr0"
-  "__ss.__srr0"
+  "uc_mcontext.gregs[REG_PC]"          # Solaris x86 (32 + 64 bit)
+  "uc_mcontext.gregs[REG_EIP]"         # Linux (i386)
+  "uc_mcontext.gregs[REG_RIP]"         # Linux (x86_64)
+  "uc_mcontext.sc_ip"                  # Linux (ia64)
+  "uc_mcontext.pc"                     # Linux (mips)
+  "uc_mcontext.uc_regs->gregs[PT_NIP]" # Linux (ppc)
+  "uc_mcontext.gregs[R15]"             # Linux (arm old [untested])
+  "uc_mcontext.arm_pc"                 # Linux (arm arch 5)
+  "uc_mcontext.gp_regs[PT_NIP]"        # Suse SLES 11 (ppc64)
+  "uc_mcontext.mc_eip"                 # FreeBSD (i386)
+  "uc_mcontext.mc_rip"                 # FreeBSD (x86_64 [untested])
+  "uc_mcontext.__gregs[_REG_EIP]"      # NetBSD (i386)
+  "uc_mcontext.__gregs[_REG_RIP]"      # NetBSD (x86_64)
+  "uc_mcontext->ss.eip"                # OS X (i386, <=10.4)
+  "uc_mcontext->__ss.__eip"            # OS X (i386, >=10.5)
+  "uc_mcontext->ss.rip"                # OS X (x86_64)
+  "uc_mcontext->__ss.__rip"            # OS X (>=10.5 [untested])
+  "uc_mcontext->ss.srr0"               # OS X (ppc, ppc64 [untested])
+  "uc_mcontext->__ss.__srr0"           # OS X (>=10.5 [untested])
 )
 
-set (_PC_HEADERS ucontext.h signal.h)
+if (HAVE_UCONTEXT_H AND NOT DEFINED PC_FROM_UCONTEXT)
+  cmake_push_check_state (RESET)
 
-if (HAVE_UCONTEXT_H AND NOT PC_FROM_UCONTEXT)
-  foreach (_PC_FIELD ${_PC_FIELDS})
-    foreach (_PC_HEADER ${_PC_HEADERS})
-      set (_TMP
-      ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/uctfield.cpp)
-      file (WRITE ${_TMP} "
-#define _GNU_SOURCE 1
-#include <${_PC_HEADER}>
-int main(void)
-{
-  ucontext_t u;
-  return u.${_PC_FIELD} == 0;
-}
-")
-      try_compile (HAVE_PC_FROM_UCONTEXT ${CMAKE_CURRENT_BINARY_DIR} ${_TMP}
-        COMPILE_DEFINITIONS _GNU_SOURCE=1)
+  set (CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
+  set (_PC_HEADERS ucontext.h signal.h)
 
-      if (HAVE_PC_FROM_UCONTEXT)
-        set (PC_FROM_UCONTEXT ${_PC_FIELD} CACHE)
-      endif (HAVE_PC_FROM_UCONTEXT)
+  foreach (_PC_FIELD IN LISTS _PC_FIELDS)
+    foreach (_PC_HEADER IN LISTS _PC_HEADERS)
+      # Replace non-alphanumeric characters by underscores since the name will be
+      # used as preprocessor definition.
+      string (REGEX REPLACE "[^a-zA-Z0-9]" "_" HAVE_UCONTEXT_FIELD_NAME
+        "HAVE_PC_FROM_UCONTEXT_${_PC_FIELD}")
+      # Strip trailing underscores for readability
+      string (REGEX REPLACE "_+$" "" HAVE_UCONTEXT_FIELD_NAME
+        "${HAVE_UCONTEXT_FIELD_NAME}")
+
+      check_struct_has_member (ucontext_t ${_PC_FIELD} ${_PC_HEADER}
+        ${HAVE_UCONTEXT_FIELD_NAME} LANGUAGE CXX)
+
+      if (${HAVE_UCONTEXT_FIELD_NAME})
+        set (PC_FROM_UCONTEXT ${_PC_FIELD} CACHE STRING
+          "<${_PC_HEADER}> ucontext_t PC member")
+        mark_as_advanced (PC_FROM_UCONTEXT)
+        break ()
+      endif (${HAVE_UCONTEXT_FIELD_NAME})
     endforeach (_PC_HEADER)
+
+    if (${HAVE_UCONTEXT_FIELD_NAME})
+      break ()
+    endif (${HAVE_UCONTEXT_FIELD_NAME})
   endforeach (_PC_FIELD)
-endif  (HAVE_UCONTEXT_H AND NOT PC_FROM_UCONTEXT)
+
+  cmake_pop_check_state ()
+endif (HAVE_UCONTEXT_H AND NOT DEFINED PC_FROM_UCONTEXT)
 
 set (GOOGLE_NAMESPACE google)
 set (_START_GOOGLE_NAMESPACE_ "namespace ${GOOGLE_NAMESPACE} {")
@@ -468,16 +480,13 @@
   src/demangle.h
   src/logging.cc
   src/raw_logging.cc
+  src/signalhandler.cc
   src/symbolize.cc
   src/symbolize.h
   src/utilities.cc
   src/utilities.h
   src/vlog_is_on.cc
 )
-
-if (HAVE_PTHREAD OR WIN32 OR CYGWIN)
-  list (APPEND GLOG_SRCS src/signalhandler.cc)
-endif (HAVE_PTHREAD OR WIN32 OR CYGWIN)
 
 if (CYGWIN OR WIN32)
   list (APPEND GLOG_SRCS
@@ -491,9 +500,20 @@
   ${GLOG_SRCS}
 )
 target_compile_features (glog_internal PUBLIC $<TARGET_PROPERTY:glog,COMPILE_FEATURES>)
+set_target_properties (glog_internal PROPERTIES DEFINE_SYMBOL GOOGLE_GLOG_IS_A_DLL)
+
+# Some generators (such as Xcode) do not generate any output if the target does
+# not reference at least one source file.
+set (_glog_EMPTY_SOURCE ${glog_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/glog.cc)
+
+add_custom_command (
+  OUTPUT ${_glog_EMPTY_SOURCE}
+  COMMAND ${CMAKE_COMMAND} -E touch ${_glog_EMPTY_SOURCE}
+)
 
 add_library (glog
   $<TARGET_OBJECTS:glog_internal>
+  ${_glog_EMPTY_SOURCE}
 )
 target_compile_features (glog PUBLIC cxx_std_14)
 
@@ -615,38 +635,30 @@
 endif (NOT WITH_FUZZING STREQUAL "none")
 
 if (BUILD_TESTING)
-  add_library (glogtest STATIC
-    $<TARGET_OBJECTS:glog_internal>
-  )
-
-  target_include_directories (glogtest PUBLIC
-    $<TARGET_PROPERTY:glog,INCLUDE_DIRECTORIES>)
-  target_compile_definitions (glogtest PUBLIC
-    $<TARGET_PROPERTY:glog,COMPILE_DEFINITIONS> GLOG_STATIC_DEFINE)
-  target_link_libraries (glogtest PUBLIC
-    $<TARGET_PROPERTY:glog,LINK_LIBRARIES>)
-
-  set (_GLOG_TEST_LIBS glogtest)
+  add_library (glog_test INTERFACE)
+  target_link_libraries (glog_test INTERFACE $<TARGET_OBJECTS:glog_internal> $<TARGET_PROPERTY:glog,LINK_LIBRARIES>)
+  target_compile_definitions (glog_test INTERFACE GLOG_STATIC_DEFINE $<TARGET_PROPERTY:glog,COMPILE_DEFINITIONS>)
+  target_include_directories (glog_test INTERFACE $<TARGET_PROPERTY:glog,INCLUDE_DIRECTORIES>)
 
   if (HAVE_LIB_GTEST)
-    list (APPEND _GLOG_TEST_LIBS GTest::gtest)
+    target_link_libraries (glog_test INTERFACE GTest::gtest)
   endif (HAVE_LIB_GTEST)
 
   if (HAVE_LIB_GMOCK)
-    list (APPEND _GLOG_TEST_LIBS GTest::gmock)
+    target_link_libraries (glog_test INTERFACE GTest::gmock)
   endif (HAVE_LIB_GMOCK)
 
   add_executable (logging_unittest
     src/logging_unittest.cc
   )
 
-  target_link_libraries (logging_unittest PRIVATE ${_GLOG_TEST_LIBS})
+  target_link_libraries (logging_unittest PRIVATE glog_test)
 
   add_executable (stl_logging_unittest
     src/stl_logging_unittest.cc
   )
 
-  target_link_libraries (stl_logging_unittest PRIVATE ${_GLOG_TEST_LIBS})
+  target_link_libraries (stl_logging_unittest PRIVATE glog_test)
 
   if (HAVE_NO_DEPRECATED)
     set_property (TARGET stl_logging_unittest APPEND PROPERTY COMPILE_OPTIONS
@@ -663,35 +675,35 @@
       src/symbolize_unittest.cc
     )
 
-    target_link_libraries (symbolize_unittest PRIVATE ${_GLOG_TEST_LIBS})
+    target_link_libraries (symbolize_unittest PRIVATE glog_test)
   endif (HAVE_SYMBOLIZE)
 
   add_executable (demangle_unittest
     src/demangle_unittest.cc
   )
 
-  target_link_libraries (demangle_unittest PRIVATE ${_GLOG_TEST_LIBS})
+  target_link_libraries (demangle_unittest PRIVATE glog_test)
 
   if (HAVE_STACKTRACE)
     add_executable (stacktrace_unittest
       src/stacktrace_unittest.cc
     )
 
-    target_link_libraries (stacktrace_unittest PRIVATE ${_GLOG_TEST_LIBS})
+    target_link_libraries (stacktrace_unittest PRIVATE glog_test)
   endif (HAVE_STACKTRACE)
 
   add_executable (utilities_unittest
     src/utilities_unittest.cc
   )
 
-  target_link_libraries (utilities_unittest PRIVATE ${_GLOG_TEST_LIBS})
+  target_link_libraries (utilities_unittest PRIVATE glog_test)
 
   if (HAVE_STACKTRACE AND HAVE_SYMBOLIZE)
     add_executable (signalhandler_unittest
       src/signalhandler_unittest.cc
     )
 
-    target_link_libraries (signalhandler_unittest PRIVATE ${_GLOG_TEST_LIBS})
+    target_link_libraries (signalhandler_unittest PRIVATE glog_test)
   endif (HAVE_STACKTRACE AND HAVE_SYMBOLIZE)
 
   add_test (NAME demangle COMMAND demangle_unittest)
@@ -737,7 +749,7 @@
       src/mock-log.h
     )
 
-    target_link_libraries (mock-log_unittest PRIVATE ${_GLOG_TEST_LIBS})
+    target_link_libraries (mock-log_unittest PRIVATE glog_test)
 
     add_test (NAME mock-log COMMAND mock-log_unittest)
   endif (HAVE_LIB_GMOCK)
@@ -799,17 +811,17 @@
   add_executable (cleanup_immediately_unittest
     src/cleanup_immediately_unittest.cc)
 
-  target_link_libraries (cleanup_immediately_unittest PRIVATE ${_GLOG_TEST_LIBS})
+  target_link_libraries (cleanup_immediately_unittest PRIVATE glog_test)
 
   add_executable (cleanup_with_absolute_prefix_unittest
     src/cleanup_with_absolute_prefix_unittest.cc)
 
-  target_link_libraries (cleanup_with_absolute_prefix_unittest PRIVATE ${_GLOG_TEST_LIBS})
+  target_link_libraries (cleanup_with_absolute_prefix_unittest PRIVATE glog_test)
 
   add_executable (cleanup_with_relative_prefix_unittest
     src/cleanup_with_relative_prefix_unittest.cc)
 
-  target_link_libraries (cleanup_with_relative_prefix_unittest PRIVATE ${_GLOG_TEST_LIBS})
+  target_link_libraries (cleanup_with_relative_prefix_unittest PRIVATE glog_test)
 
   set (CLEANUP_LOG_DIR ${CMAKE_CURRENT_BINARY_DIR}/cleanup_tests)
 
diff --git a/runtime/onnxruntime/third_party/glog/cmake/GetCacheVariables.cmake b/runtime/onnxruntime/third_party/glog/cmake/GetCacheVariables.cmake
index ead3589..76f2b16 100644
--- a/runtime/onnxruntime/third_party/glog/cmake/GetCacheVariables.cmake
+++ b/runtime/onnxruntime/third_party/glog/cmake/GetCacheVariables.cmake
@@ -1,5 +1,5 @@
 cmake_policy (PUSH)
-cmake_policy (VERSION 3.3)
+cmake_policy (VERSION 3.16...3.27)
 
 include (CMakeParseArguments)
 
diff --git a/runtime/onnxruntime/third_party/glog/cmake/TestPackageConfig.cmake b/runtime/onnxruntime/third_party/glog/cmake/TestPackageConfig.cmake
index 97244ab..2b66c23 100644
--- a/runtime/onnxruntime/third_party/glog/cmake/TestPackageConfig.cmake
+++ b/runtime/onnxruntime/third_party/glog/cmake/TestPackageConfig.cmake
@@ -1,13 +1,3 @@
-# Create the build directory
-execute_process (
-  COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_BINARY_DIR}
-  RESULT_VARIABLE _DIRECTORY_CREATED_SUCCEEDED
-)
-
-if (NOT _DIRECTORY_CREATED_SUCCEEDED EQUAL 0)
-  message (FATAL_ERROR "Failed to create build directory")
-endif (NOT _DIRECTORY_CREATED_SUCCEEDED EQUAL 0)
-
 if (GENERATOR_TOOLSET)
   list (APPEND _ADDITIONAL_ARGS -T ${GENERATOR_TOOLSET})
 endif (GENERATOR_TOOLSET)
@@ -21,7 +11,7 @@
   # Capture the PATH environment variable content set during project generation
   # stage. This is required because later during the build stage the PATH is
   # modified again (e.g., for MinGW AppVeyor CI builds) by adding back the
-  # directory containing git.exe. Incidently, the Git installation directory
+  # directory containing git.exe. Incidentally, the Git installation directory
   # also contains sh.exe which causes MinGW Makefile generation to fail.
   COMMAND ${CMAKE_COMMAND} -E env PATH=${PATH}
   ${CMAKE_COMMAND} -C ${INITIAL_CACHE}
@@ -29,9 +19,9 @@
     ${_ADDITIONAL_ARGS}
     -DCMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=ON
     -DCMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY=ON
-    -DCMAKE_PREFIX_PATH=${PACKAGE_DIR}
-    ${SOURCE_DIR}
-  WORKING_DIRECTORY ${TEST_BINARY_DIR}
+    -Dglog_ROOT=${PACKAGE_DIR}
+    -S ${SOURCE_DIR}
+    -B ${TEST_BINARY_DIR}
   RESULT_VARIABLE _GENERATE_SUCCEEDED
 )
 
diff --git a/runtime/onnxruntime/third_party/glog/src/base/commandlineflags.h b/runtime/onnxruntime/third_party/glog/src/base/commandlineflags.h
index c011df4..66c0dae 100644
--- a/runtime/onnxruntime/third_party/glog/src/base/commandlineflags.h
+++ b/runtime/onnxruntime/third_party/glog/src/base/commandlineflags.h
@@ -59,7 +59,7 @@
 
 #else
 
-#include <glog/logging.h>
+#include "glog/logging.h"
 
 #define DECLARE_VARIABLE(type, shorttype, name, tn) \
   namespace fL##shorttype {                         \
@@ -140,9 +140,12 @@
                     : memchr("tTyY1\0", getenv(envname)[0], 6) != nullptr)
 
 #define EnvToInt(envname, dflt) \
-  (!getenv(envname) ? (dflt) : strtol(getenv(envname), nullptr, 10))
+  (!getenv(envname) ? (dflt)    \
+                    : static_cast<int>(strtol(getenv(envname), nullptr, 10)))
 
 #define EnvToUInt(envname, dflt) \
-  (!getenv(envname) ? (dflt) : strtoul(getenv(envname), nullptr, 10))
+  (!getenv(envname)              \
+       ? (dflt)                  \
+       : static_cast<unsigned>(strtoul(getenv(envname), nullptr, 10)))
 
 #endif  // BASE_COMMANDLINEFLAGS_H__
diff --git a/runtime/onnxruntime/third_party/glog/src/config.h b/runtime/onnxruntime/third_party/glog/src/config.h
deleted file mode 100644
index fb17d23..0000000
--- a/runtime/onnxruntime/third_party/glog/src/config.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef GLOG_CONFIG_H
-#define GLOG_CONFIG_H
-
-/* Namespace for Google classes */
-#define GOOGLE_NAMESPACE google
-
-/* Define if you have the `dladdr' function */
-#define HAVE_DLADDR
-
-/* Define if you have the `snprintf' function */
-#define HAVE_SNPRINTF
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H
-
-/* Define if you have the `backtrace' function in <execinfo.h> */
-#define HAVE_EXECINFO_BACKTRACE
-
-/* Define if you have the `backtrace_symbols' function in <execinfo.h> */
-#define HAVE_EXECINFO_BACKTRACE_SYMBOLS
-
-/* Define if you have the `fcntl' function */
-#define HAVE_FCNTL
-
-/* Define to 1 if you have the <glob.h> header file. */
-#define HAVE_GLOB_H
-
-/* Define to 1 if you have the `pthread' library (-lpthread). */
-/* #undef HAVE_LIBPTHREAD */
-
-/* define if you have google gflags library */
-/* #undef HAVE_LIB_GFLAGS */
-
-/* define if you have google gmock library */
-/* #undef HAVE_LIB_GMOCK */
-
-/* define if you have google gtest library */
-/* #undef HAVE_LIB_GTEST */
-
-/* define if you have dbghelp library */
-/* #undef HAVE_DBGHELP */
-
-/* define if you have libunwind */
-/* #undef HAVE_LIB_UNWIND */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H
-
-/* define to disable multithreading support. */
-/* #undef NO_THREADS */
-
-/* Define if you have the 'pread' function */
-#define HAVE_PREAD
-
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H
-
-/* Define if you have the 'pwrite' function */
-#define HAVE_PWRITE
-
-/* define if the compiler implements pthread_rwlock_* */
-#define HAVE_RWLOCK
-
-/* Define if you have the 'sigaction' function */
-#define HAVE_SIGACTION
-
-/* Define if you have the `sigaltstack' function */
-#define HAVE_SIGALTSTACK
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H
-
-/* Define to 1 if you have the <syscall.h> header file. */
-/* #undef HAVE_SYSCALL_H */
-
-/* Define to 1 if you have the <syslog.h> header file. */
-#define HAVE_SYSLOG_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/syscall.h> header file. */
-#define HAVE_SYS_SYSCALL_H
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/ucontext.h> header file. */
-/* #undef HAVE_SYS_UCONTEXT_H */
-
-/* Define to 1 if you have the <sys/utsname.h> header file. */
-#define HAVE_SYS_UTSNAME_H
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H
-
-/* Define to 1 if you have the <ucontext.h> header file. */
-/* #undef HAVE_UCONTEXT_H */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define if you linking to _Unwind_Backtrace is possible. */
-#define HAVE__UNWIND_BACKTRACE
-
-/* Define if you linking to _Unwind_GetIP is possible. */
-#define HAVE__UNWIND_GETIP
-
-/* define if your compiler has __attribute__ */
-#define HAVE___ATTRIBUTE__
-
-/* define if your compiler has __builtin_expect */
-#define HAVE___BUILTIN_EXPECT 1
-
-/* define if your compiler has __sync_val_compare_and_swap */
-#define HAVE___SYNC_VAL_COMPARE_AND_SWAP
-
-/* define if symbolize support is available */
-/* #undef HAVE_SYMBOLIZE */
-
-/* define if localtime_r is available in time.h */
-#define HAVE_LOCALTIME_R
-
-/* define if gmtime_r is available in time.h */
-/* #undef HAVE_GMTIME_R */
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
-   */
-/* #undef LT_OBJDIR */
-
-/* How to access the PC from a struct ucontext */
-/* #undef PC_FROM_UCONTEXT */
-
-/* define if we should print file offsets in traces instead of symbolizing. */
-/* #undef PRINT_UNSYMBOLIZED_STACK_TRACES */
-
-/* Define to necessary symbol if this constant uses a non-standard name on
-   your system. */
-/* #undef PTHREAD_CREATE_JOINABLE */
-
-/* The size of `void *', as computed by sizeof. */
-#define SIZEOF_VOID_P 8
-
-/* location of source code */
-#define TEST_SRC_DIR "/Users/qiuwei/Documents/閭卞▉/璇煶璇嗗埆-asr/to_alibaba-damo-academy/FunASR/funasr/runtime/onnxruntime/third_party/glog"
-
-/* Define if thread-local storage is enabled. */
-#define GLOG_THREAD_LOCAL_STORAGE
-
-#ifdef GLOG_BAZEL_BUILD
-
-/* TODO(rodrigoq): remove this workaround once bazel#3979 is resolved:
- * https://github.com/bazelbuild/bazel/issues/3979 */
-#define _START_GOOGLE_NAMESPACE_ namespace GOOGLE_NAMESPACE {
-
-#define _END_GOOGLE_NAMESPACE_ }
-
-#else
-
-/* Stops putting the code inside the Google namespace */
-#define _END_GOOGLE_NAMESPACE_ }
-
-/* Puts following code inside the Google namespace */
-#define _START_GOOGLE_NAMESPACE_ namespace google {
-
-#endif
-
-/* Replacement for deprecated syscall(SYS_gettid) on macOS. */
-#define HAVE_PTHREAD_THREADID_NP 1
-
-#endif  // GLOG_CONFIG_H
diff --git a/runtime/onnxruntime/third_party/glog/src/config.h.cmake.in b/runtime/onnxruntime/third_party/glog/src/config.h.cmake.in
index 9d61010..3fed2a6 100644
--- a/runtime/onnxruntime/third_party/glog/src/config.h.cmake.in
+++ b/runtime/onnxruntime/third_party/glog/src/config.h.cmake.in
@@ -130,12 +130,15 @@
 /* define if gmtime_r is available in time.h */
 #cmakedefine HAVE_GMTIME_R
 
+/* define if _chsize_s is available in io.h */
+#cmakedefine HAVE__CHSIZE_S
+
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
 #cmakedefine LT_OBJDIR
 
 /* How to access the PC from a struct ucontext */
-#cmakedefine PC_FROM_UCONTEXT
+#cmakedefine PC_FROM_UCONTEXT ${PC_FROM_UCONTEXT}
 
 /* define if we should print file offsets in traces instead of symbolizing. */
 #cmakedefine PRINT_UNSYMBOLIZED_STACK_TRACES
diff --git a/runtime/onnxruntime/third_party/glog/src/demangle.cc b/runtime/onnxruntime/third_party/glog/src/demangle.cc
index b19d446..74dff70 100644
--- a/runtime/onnxruntime/third_party/glog/src/demangle.cc
+++ b/runtime/onnxruntime/third_party/glog/src/demangle.cc
@@ -36,7 +36,9 @@
 
 #include "demangle.h"
 
+#include <cstddef>
 #include <cstdio>  // for nullptr
+#include <limits>
 
 #include "utilities.h"
 
@@ -109,6 +111,9 @@
   short nest_level;          // For nested names.
   bool append;               // Append flag.
   bool overflowed;           // True if output gets overflowed.
+  uint32 local_level;
+  uint32 expr_level;
+  uint32 arg_level;
 };
 
 // We don't use strlen() in libc since it's not guaranteed to be async
@@ -153,6 +158,9 @@
   state->nest_level = -1;
   state->append = true;
   state->overflowed = false;
+  state->local_level = 0;
+  state->expr_level = 0;
+  state->arg_level = 0;
 }
 
 // Returns true and advances "mangled_cur" if we find "one_char_token"
@@ -221,6 +229,10 @@
 // is set to true for later use.  The output string is ensured to
 // always terminate with '\0' as long as there is no overflow.
 static void Append(State *state, const char * const str, ssize_t length) {
+  if (state->out_cur == nullptr) {
+    state->overflowed = true;
+    return;
+  }
   for (ssize_t i = 0; i < length; ++i) {
     if (state->out_cur + 1 < state->out_end) {  // +1 for '\0'
       *state->out_cur = str[i];
@@ -294,7 +306,7 @@
   }
 }
 
-// A convenient wrapper arount MaybeAppendWithLength().
+// A convenient wrapper around MaybeAppendWithLength().
 static bool MaybeAppend(State *state, const char * const str) {
   if (state->append) {
     size_t length = StrLen(str);
@@ -592,9 +604,23 @@
   }
   const char *p = state->mangled_cur;
   int number = 0;
+  constexpr int int_max_by_10 = std::numeric_limits<int>::max() / 10;
   for (;*p != '\0'; ++p) {
     if (IsDigit(*p)) {
-      number = number * 10 + (*p - '0');
+      // Prevent signed integer overflow when multiplying
+      if (number > int_max_by_10) {
+        return false;
+      }
+
+      const int digit = *p - '0';
+      const int shifted = number * 10;
+
+      // Prevent signed integer overflow when summing
+      if (digit > std::numeric_limits<int>::max() - shifted) {
+        return false;
+      }
+
+      number = shifted + digit;
     } else {
       break;
     }
@@ -651,6 +677,10 @@
     MaybeAppend(state, "(anonymous namespace)");
   } else {
     MaybeAppendWithLength(state, state->mangled_cur, length);
+  }
+  if (length < 0 ||
+      static_cast<std::size_t>(length) > StrLen(state->mangled_cur)) {
+    return false;
   }
   state->mangled_cur += length;
   return true;
@@ -1067,22 +1097,33 @@
 //                 ::= J <template-arg>* E        # argument pack
 //                 ::= X <expression> E
 static bool ParseTemplateArg(State *state) {
+  // Avoid recursion above max_levels
+  constexpr uint32 max_levels = 5;
+
+  if (state->arg_level > max_levels) {
+    return false;
+  }
+  ++state->arg_level;
+
   State copy = *state;
   if ((ParseOneCharToken(state, 'I') || ParseOneCharToken(state, 'J')) &&
       ZeroOrMore(ParseTemplateArg, state) &&
       ParseOneCharToken(state, 'E')) {
+    --state->arg_level;
     return true;
   }
   *state = copy;
 
   if (ParseType(state) ||
       ParseExprPrimary(state)) {
+    --state->arg_level;
     return true;
   }
   *state = copy;
 
   if (ParseOneCharToken(state, 'X') && ParseExpression(state) &&
       ParseOneCharToken(state, 'E')) {
+    --state->arg_level;
     return true;
   }
   *state = copy;
@@ -1103,11 +1144,20 @@
     return true;
   }
 
+  // Avoid recursion above max_levels
+  constexpr uint32 max_levels = 5;
+
+  if (state->expr_level > max_levels) {
+    return false;
+  }
+  ++state->expr_level;
+
   State copy = *state;
   if (ParseOperatorName(state) &&
       ParseExpression(state) &&
       ParseExpression(state) &&
       ParseExpression(state)) {
+    --state->expr_level;
     return true;
   }
   *state = copy;
@@ -1115,30 +1165,35 @@
   if (ParseOperatorName(state) &&
       ParseExpression(state) &&
       ParseExpression(state)) {
+    --state->expr_level;
     return true;
   }
   *state = copy;
 
   if (ParseOperatorName(state) &&
       ParseExpression(state)) {
+    --state->expr_level;
     return true;
   }
   *state = copy;
 
   if (ParseTwoCharToken(state, "st") && ParseType(state)) {
     return true;
+    --state->expr_level;
   }
   *state = copy;
 
   if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
       ParseUnqualifiedName(state) &&
       ParseTemplateArgs(state)) {
+    --state->expr_level;
     return true;
   }
   *state = copy;
 
   if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
       ParseUnqualifiedName(state)) {
+    --state->expr_level;
     return true;
   }
   *state = copy;
@@ -1184,16 +1239,25 @@
 //                 [<discriminator>]
 //              := Z <(function) encoding> E s [<discriminator>]
 static bool ParseLocalName(State *state) {
+  // Avoid recursion above max_levels
+  constexpr uint32 max_levels = 5;
+  if (state->local_level > max_levels) {
+    return false;
+  }
+  ++state->local_level;
+
   State copy = *state;
   if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
       ParseOneCharToken(state, 'E') && MaybeAppend(state, "::") &&
       ParseName(state) && Optional(ParseDiscriminator(state))) {
+    --state->local_level;
     return true;
   }
   *state = copy;
 
   if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
       ParseTwoCharToken(state, "Es") && Optional(ParseDiscriminator(state))) {
+    --state->local_level;
     return true;
   }
   *state = copy;
diff --git a/runtime/onnxruntime/third_party/glog/src/demangle.h b/runtime/onnxruntime/third_party/glog/src/demangle.h
index f347b98..416f7ee 100644
--- a/runtime/onnxruntime/third_party/glog/src/demangle.h
+++ b/runtime/onnxruntime/third_party/glog/src/demangle.h
@@ -71,7 +71,7 @@
 #define BASE_DEMANGLE_H_
 
 #include "config.h"
-#include <glog/logging.h>
+#include "glog/logging.h"
 
 _START_GOOGLE_NAMESPACE_
 
diff --git a/runtime/onnxruntime/third_party/glog/src/glog/export.h b/runtime/onnxruntime/third_party/glog/src/glog/export.h
deleted file mode 100644
index 6e2691e..0000000
--- a/runtime/onnxruntime/third_party/glog/src/glog/export.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-#ifndef GLOG_EXPORT_H
-#define GLOG_EXPORT_H
-
-#ifdef GLOG_STATIC_DEFINE
-#  define GLOG_EXPORT
-#  define GLOG_NO_EXPORT
-#else
-#  ifndef GLOG_EXPORT
-#    ifdef GOOGLE_GLOG_IS_A_DLL
-        /* We are building this library */
-#      define GLOG_EXPORT __attribute__((visibility("default")))
-#    else
-        /* We are using this library */
-#      define GLOG_EXPORT __attribute__((visibility("default")))
-#    endif
-#  endif
-
-#  ifndef GLOG_NO_EXPORT
-#    define GLOG_NO_EXPORT __attribute__((visibility("hidden")))
-#  endif
-#endif
-
-#ifndef GLOG_DEPRECATED
-#  define GLOG_DEPRECATED __attribute__ ((__deprecated__))
-#endif
-
-#ifndef GLOG_DEPRECATED_EXPORT
-#  define GLOG_DEPRECATED_EXPORT GLOG_EXPORT GLOG_DEPRECATED
-#endif
-
-#ifndef GLOG_DEPRECATED_NO_EXPORT
-#  define GLOG_DEPRECATED_NO_EXPORT GLOG_NO_EXPORT GLOG_DEPRECATED
-#endif
-
-#if 0 /* DEFINE_NO_DEPRECATED */
-#  ifndef GLOG_NO_DEPRECATED
-#    define GLOG_NO_DEPRECATED
-#  endif
-#endif
-
-#endif /* GLOG_EXPORT_H */
diff --git a/runtime/onnxruntime/third_party/glog/src/glog/logging.h b/runtime/onnxruntime/third_party/glog/src/glog/logging.h
deleted file mode 100644
index 6f6685a..0000000
--- a/runtime/onnxruntime/third_party/glog/src/glog/logging.h
+++ /dev/null
@@ -1,1842 +0,0 @@
-// Copyright (c) 2023, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: Ray Sidney
-//
-// This file contains #include information about logging-related stuff.
-// Pretty much everybody needs to #include this file so that they can
-// log various happenings.
-//
-#ifndef GLOG_LOGGING_H
-#define GLOG_LOGGING_H
-
-#include <cerrno>
-#include <chrono>
-#include <cstddef>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
-#include <iosfwd>
-#include <ostream>
-#include <sstream>
-#include <string>
-#if 1
-# include <unistd.h>
-#endif
-#include <vector>
-
-#if defined(_MSC_VER)
-#define GLOG_MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
-                                     __pragma(warning(disable:n))
-#define GLOG_MSVC_POP_WARNING() __pragma(warning(pop))
-#else
-#define GLOG_MSVC_PUSH_DISABLE_WARNING(n)
-#define GLOG_MSVC_POP_WARNING()
-#endif
-
-#include <glog/platform.h>
-
-#if 1
-#include <glog/export.h>
-#endif
-
-// We care a lot about number of bits things take up.  Unfortunately,
-// systems define their bit-specific ints in a lot of different ways.
-// We use our own way, and have a typedef to get there.
-// Note: these commands below may look like "#if 1" or "#if 0", but
-// that's because they were constructed that way at ./configure time.
-// Look at logging.h.in to see how they're calculated (based on your config).
-#include <cstdint>  // the normal place uint16_t is defined
-#if 1
-#include <sys/types.h>          // the normal place u_int16_t is defined
-#endif
-
-#if 0
-#include <gflags/gflags.h>
-#endif
-
-#include <atomic>
-
-namespace google {
-
-    typedef std::int32_t int32;
-typedef std::uint32_t uint32;
-typedef std::int64_t int64;
-typedef std::uint64_t uint64;
-
-#if !(1)
-typedef ptrdiff_t ssize_t;
-#endif
-
-#if !(1)
-typedef int mode_t;
-#endif
-
-typedef double WallTime;
-
-struct GLOG_EXPORT LogMessageTime {
-  LogMessageTime();
-  LogMessageTime(std::tm t);
-  LogMessageTime(std::time_t timestamp, WallTime now);
-
-  const time_t& timestamp() const { return timestamp_; }
-  const int& sec() const { return time_struct_.tm_sec; }
-  const int32_t& usec() const { return usecs_; }
-  const int&(min)() const { return time_struct_.tm_min; }
-  const int& hour() const { return time_struct_.tm_hour; }
-  const int& day() const { return time_struct_.tm_mday; }
-  const int& month() const { return time_struct_.tm_mon; }
-  const int& year() const { return time_struct_.tm_year; }
-  const int& dayOfWeek() const { return time_struct_.tm_wday; }
-  const int& dayInYear() const { return time_struct_.tm_yday; }
-  const int& dst() const { return time_struct_.tm_isdst; }
-  const long int& gmtoff() const { return gmtoffset_; }
-  const std::tm& tm() const { return time_struct_; }
-
- private:
-  void init(const std::tm& t, std::time_t timestamp, WallTime now);
-  std::tm time_struct_;  // Time of creation of LogMessage
-  time_t timestamp_;     // Time of creation of LogMessage in seconds
-  int32_t usecs_;        // Time of creation of LogMessage - microseconds part
-  long int gmtoffset_;
-
-  void CalcGmtOffset();
-};
-
-struct LogMessageInfo {
-  explicit LogMessageInfo(const char* const severity_,
-                          const char* const filename_,
-                          const int& line_number_,
-                          const int& thread_id_,
-                          const LogMessageTime& time_):
-      severity(severity_), filename(filename_), line_number(line_number_),
-      thread_id(thread_id_), time(time_)
-  {}
-
-  const char* const severity;
-  const char* const filename;
-  const int &line_number;
-  const int &thread_id;
-  const LogMessageTime& time;
-};
-
-typedef void(*CustomPrefixCallback)(std::ostream& s, const LogMessageInfo& l, void* data);
-
-}
-
-
-// The global value of GOOGLE_STRIP_LOG. All the messages logged to
-// LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed.
-// If it can be determined at compile time that the message will not be
-// printed, the statement will be compiled out.
-//
-// Example: to strip out all INFO and WARNING messages, use the value
-// of 2 below. To make an exception for WARNING messages from a single
-// file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including
-// base/logging.h
-#ifndef GOOGLE_STRIP_LOG
-#define GOOGLE_STRIP_LOG 0
-#endif
-
-// GCC can be told that a certain branch is not likely to be taken (for
-// instance, a CHECK failure), and use that information in static analysis.
-// Giving it this information can help it optimize for the common case in
-// the absence of better information (ie. -fprofile-arcs).
-//
-#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN
-#if 1
-#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0))
-#else
-#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x
-#endif
-#endif
-
-#ifndef GOOGLE_PREDICT_FALSE
-#if 1
-#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0))
-#else
-#define GOOGLE_PREDICT_FALSE(x) x
-#endif
-#endif
-
-#ifndef GOOGLE_PREDICT_TRUE
-#if 1
-#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
-#else
-#define GOOGLE_PREDICT_TRUE(x) x
-#endif
-#endif
-
-
-// Make a bunch of macros for logging.  The way to log things is to stream
-// things to LOG(<a particular severity level>).  E.g.,
-//
-//   LOG(INFO) << "Found " << num_cookies << " cookies";
-//
-// You can capture log messages in a string, rather than reporting them
-// immediately:
-//
-//   vector<string> errors;
-//   LOG_STRING(ERROR, &errors) << "Couldn't parse cookie #" << cookie_num;
-//
-// This pushes back the new error onto 'errors'; if given a NULL pointer,
-// it reports the error via LOG(ERROR).
-//
-// You can also do conditional logging:
-//
-//   LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
-//
-// You can also do occasional logging (log every n'th occurrence of an
-// event):
-//
-//   LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
-//
-// The above will cause log messages to be output on the 1st, 11th, 21st, ...
-// times it is executed.  Note that the special google::COUNTER value is used
-// to identify which repetition is happening.
-//
-// You can also do occasional conditional logging (log every n'th
-// occurrence of an event, when condition is satisfied):
-//
-//   LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
-//                                           << "th big cookie";
-//
-// You can log messages the first N times your code executes a line. E.g.
-//
-//   LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
-//
-// Outputs log messages for the first 20 times it is executed.
-//
-// Analogous SYSLOG, SYSLOG_IF, and SYSLOG_EVERY_N macros are available.
-// These log to syslog as well as to the normal logs.  If you use these at
-// all, you need to be aware that syslog can drastically reduce performance,
-// especially if it is configured for remote logging!  Don't use these
-// unless you fully understand this and have a concrete need to use them.
-// Even then, try to minimize your use of them.
-//
-// There are also "debug mode" logging macros like the ones above:
-//
-//   DLOG(INFO) << "Found cookies";
-//
-//   DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
-//
-//   DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
-//
-// All "debug mode" logging is compiled away to nothing for non-debug mode
-// compiles.
-//
-// We also have
-//
-//   LOG_ASSERT(assertion);
-//   DLOG_ASSERT(assertion);
-//
-// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion;
-//
-// There are "verbose level" logging macros.  They look like
-//
-//   VLOG(1) << "I'm printed when you run the program with --v=1 or more";
-//   VLOG(2) << "I'm printed when you run the program with --v=2 or more";
-//
-// These always log at the INFO log level (when they log at all).
-// The verbose logging can also be turned on module-by-module.  For instance,
-//    --vmodule=mapreduce=2,file=1,gfs*=3 --v=0
-// will cause:
-//   a. VLOG(2) and lower messages to be printed from mapreduce.{h,cc}
-//   b. VLOG(1) and lower messages to be printed from file.{h,cc}
-//   c. VLOG(3) and lower messages to be printed from files prefixed with "gfs"
-//   d. VLOG(0) and lower messages to be printed from elsewhere
-//
-// The wildcarding functionality shown by (c) supports both '*' (match
-// 0 or more characters) and '?' (match any single character) wildcards.
-//
-// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as
-//
-//   if (VLOG_IS_ON(2)) {
-//     // do some logging preparation and logging
-//     // that can't be accomplished with just VLOG(2) << ...;
-//   }
-//
-// There are also VLOG_IF, VLOG_EVERY_N and VLOG_IF_EVERY_N "verbose level"
-// condition macros for sample cases, when some extra computation and
-// preparation for logs is not needed.
-//   VLOG_IF(1, (size > 1024))
-//      << "I'm printed when size is more than 1024 and when you run the "
-//         "program with --v=1 or more";
-//   VLOG_EVERY_N(1, 10)
-//      << "I'm printed every 10th occurrence, and when you run the program "
-//         "with --v=1 or more. Present occurence is " << google::COUNTER;
-//   VLOG_IF_EVERY_N(1, (size > 1024), 10)
-//      << "I'm printed on every 10th occurence of case when size is more "
-//         " than 1024, when you run the program with --v=1 or more. ";
-//         "Present occurence is " << google::COUNTER;
-//
-// The supported severity levels for macros that allow you to specify one
-// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
-// Note that messages of a given severity are logged not only in the
-// logfile for that severity, but also in all logfiles of lower severity.
-// E.g., a message of severity FATAL will be logged to the logfiles of
-// severity FATAL, ERROR, WARNING, and INFO.
-//
-// There is also the special severity of DFATAL, which logs FATAL in
-// debug mode, ERROR in normal mode.
-//
-// Very important: logging a message at the FATAL severity level causes
-// the program to terminate (after the message is logged).
-//
-// Unless otherwise specified, logs will be written to the filename
-// "<program name>.<hostname>.<user name>.log.<severity level>.", followed
-// by the date, time, and pid (you can't prevent the date, time, and pid
-// from being in the filename).
-//
-// The logging code takes two flags:
-//     --v=#           set the verbose level
-//     --logtostderr   log all the messages to stderr instead of to logfiles
-
-// LOG LINE PREFIX FORMAT
-//
-// Log lines have this form:
-//
-//     Lyyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg...
-//
-// where the fields are defined as follows:
-//
-//   L                A single character, representing the log level
-//                    (eg 'I' for INFO)
-//   yyyy             The year
-//   mm               The month (zero padded; ie May is '05')
-//   dd               The day (zero padded)
-//   hh:mm:ss.uuuuuu  Time in hours, minutes and fractional seconds
-//   threadid         The space-padded thread ID as returned by GetTID()
-//                    (this matches the PID on Linux)
-//   file             The file name
-//   line             The line number
-//   msg              The user-supplied message
-//
-// Example:
-//
-//   I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog
-//   I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395
-//
-// NOTE: although the microseconds are useful for comparing events on
-// a single machine, clocks on different machines may not be well
-// synchronized.  Hence, use caution when comparing the low bits of
-// timestamps from different machines.
-
-#pragma push_macro("DECLARE_VARIABLE")
-#pragma push_macro("DECLARE_bool")
-#pragma push_macro("DECLARE_string")
-#pragma push_macro("DECLARE_int32")
-#pragma push_macro("DECLARE_uint32")
-
-#ifdef DECLARE_VARIABLE
-#undef DECLARE_VARIABLE
-#endif
-
-#ifdef DECLARE_bool
-#undef DECLARE_bool
-#endif
-
-#ifdef DECLARE_string
-#undef DECLARE_string
-#endif
-
-#ifdef DECLARE_int32
-#undef DECLARE_int32
-#endif
-
-#ifdef DECLARE_uint32
-#undef DECLARE_uint32
-#endif
-
-#ifndef DECLARE_VARIABLE
-#define DECLARE_VARIABLE(type, shorttype, name, tn)                     \
-  namespace fL##shorttype {                                             \
-    extern GLOG_EXPORT type FLAGS_##name;                      \
-  }                                                                     \
-  using fL##shorttype::FLAGS_##name
-
-// bool specialization
-#define DECLARE_bool(name) \
-  DECLARE_VARIABLE(bool, B, name, bool)
-
-// int32 specialization
-#define DECLARE_int32(name) \
-  DECLARE_VARIABLE(google::int32, I, name, int32)
-
-#if !defined(DECLARE_uint32)
-// uint32 specialization
-#define DECLARE_uint32(name) \
-  DECLARE_VARIABLE(google::uint32, U, name, uint32)
-#endif // !defined(DECLARE_uint32) && !(0)
-
-// Special case for string, because we have to specify the namespace
-// std::string, which doesn't play nicely with our FLAG__namespace hackery.
-#define DECLARE_string(name)                                            \
-  namespace fLS {                                                       \
-    extern GLOG_EXPORT std::string& FLAGS_##name;              \
-  }                                                                     \
-  using fLS::FLAGS_##name
-#endif
-
-// Set whether appending a timestamp to the log file name
-DECLARE_bool(timestamp_in_logfile_name);
-
-// Set whether log messages go to stdout instead of logfiles
-DECLARE_bool(logtostdout);
-
-// Set color messages logged to stdout (if supported by terminal).
-DECLARE_bool(colorlogtostdout);
-
-// Set whether log messages go to stderr instead of logfiles
-DECLARE_bool(logtostderr);
-
-// Set whether log messages go to stderr in addition to logfiles.
-DECLARE_bool(alsologtostderr);
-
-// Set color messages logged to stderr (if supported by terminal).
-DECLARE_bool(colorlogtostderr);
-
-// Log messages at a level >= this flag are automatically sent to
-// stderr in addition to log files.
-DECLARE_int32(stderrthreshold);
-
-// Set whether the log file header should be written upon creating a file.
-DECLARE_bool(log_file_header);
-
-// Set whether the log prefix should be prepended to each line of output.
-DECLARE_bool(log_prefix);
-
-// Set whether the year should be included in the log prefix.
-DECLARE_bool(log_year_in_prefix);
-
-// Log messages at a level <= this flag are buffered.
-// Log messages at a higher level are flushed immediately.
-DECLARE_int32(logbuflevel);
-
-// Sets the maximum number of seconds which logs may be buffered for.
-DECLARE_int32(logbufsecs);
-
-// Log suppression level: messages logged at a lower level than this
-// are suppressed.
-DECLARE_int32(minloglevel);
-
-// If specified, logfiles are written into this directory instead of the
-// default logging directory.
-DECLARE_string(log_dir);
-
-// Set the log file mode.
-DECLARE_int32(logfile_mode);
-
-// Sets the path of the directory into which to put additional links
-// to the log files.
-DECLARE_string(log_link);
-
-DECLARE_int32(v);  // in vlog_is_on.cc
-
-DECLARE_string(vmodule); // also in vlog_is_on.cc
-
-// Sets the maximum log file size (in MB).
-DECLARE_uint32(max_log_size);
-
-// Sets whether to avoid logging to the disk if the disk is full.
-DECLARE_bool(stop_logging_if_full_disk);
-
-// Use UTC time for logging
-DECLARE_bool(log_utc_time);
-
-// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for
-// security reasons. See LOG(severtiy) below.
-
-// A few definitions of macros that don't generate much code.  Since
-// LOG(INFO) and its ilk are used all over our code, it's
-// better to have compact code for these operations.
-
-#if GOOGLE_STRIP_LOG == 0
-#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \
-      __FILE__, __LINE__)
-#define LOG_TO_STRING_INFO(message) google::LogMessage( \
-      __FILE__, __LINE__, google::GLOG_INFO, message)
-#else
-#define COMPACT_GOOGLE_LOG_INFO google::NullStream()
-#define LOG_TO_STRING_INFO(message) google::NullStream()
-#endif
-
-#if GOOGLE_STRIP_LOG <= 1
-#define COMPACT_GOOGLE_LOG_WARNING google::LogMessage( \
-      __FILE__, __LINE__, google::GLOG_WARNING)
-#define LOG_TO_STRING_WARNING(message) google::LogMessage( \
-      __FILE__, __LINE__, google::GLOG_WARNING, message)
-#else
-#define COMPACT_GOOGLE_LOG_WARNING google::NullStream()
-#define LOG_TO_STRING_WARNING(message) google::NullStream()
-#endif
-
-#if GOOGLE_STRIP_LOG <= 2
-#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage( \
-      __FILE__, __LINE__, google::GLOG_ERROR)
-#define LOG_TO_STRING_ERROR(message) google::LogMessage( \
-      __FILE__, __LINE__, google::GLOG_ERROR, message)
-#else
-#define COMPACT_GOOGLE_LOG_ERROR google::NullStream()
-#define LOG_TO_STRING_ERROR(message) google::NullStream()
-#endif
-
-#if GOOGLE_STRIP_LOG <= 3
-#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal( \
-      __FILE__, __LINE__)
-#define LOG_TO_STRING_FATAL(message) google::LogMessage( \
-      __FILE__, __LINE__, google::GLOG_FATAL, message)
-#else
-#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal()
-#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal()
-#endif
-
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-#define DCHECK_IS_ON() 0
-#else
-#define DCHECK_IS_ON() 1
-#endif
-
-// For DFATAL, we want to use LogMessage (as opposed to
-// LogMessageFatal), to be consistent with the original behavior.
-#if !DCHECK_IS_ON()
-#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR
-#elif GOOGLE_STRIP_LOG <= 3
-#define COMPACT_GOOGLE_LOG_DFATAL google::LogMessage( \
-      __FILE__, __LINE__, google::GLOG_FATAL)
-#else
-#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal()
-#endif
-
-#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, &google::LogMessage::SendToLog)
-#define SYSLOG_INFO(counter) \
-  google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, \
-  &google::LogMessage::SendToSyslogAndLog)
-#define GOOGLE_LOG_WARNING(counter)  \
-  google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
-  &google::LogMessage::SendToLog)
-#define SYSLOG_WARNING(counter)  \
-  google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
-  &google::LogMessage::SendToSyslogAndLog)
-#define GOOGLE_LOG_ERROR(counter)  \
-  google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
-  &google::LogMessage::SendToLog)
-#define SYSLOG_ERROR(counter)  \
-  google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
-  &google::LogMessage::SendToSyslogAndLog)
-#define GOOGLE_LOG_FATAL(counter) \
-  google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
-  &google::LogMessage::SendToLog)
-#define SYSLOG_FATAL(counter) \
-  google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
-  &google::LogMessage::SendToSyslogAndLog)
-#define GOOGLE_LOG_DFATAL(counter) \
-  google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
-  &google::LogMessage::SendToLog)
-#define SYSLOG_DFATAL(counter) \
-  google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
-  &google::LogMessage::SendToSyslogAndLog)
-
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-// A very useful logging macro to log windows errors:
-#define LOG_SYSRESULT(result) \
-  if (FAILED(HRESULT_FROM_WIN32(result))) { \
-    LPSTR message = NULL; \
-    LPSTR msg = reinterpret_cast<LPSTR>(&message); \
-    DWORD message_length = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | \
-                         FORMAT_MESSAGE_FROM_SYSTEM | \
-                         FORMAT_MESSAGE_IGNORE_INSERTS, \
-                         0, result, 0, msg, 100, NULL); \
-    if (message_length > 0) { \
-      google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
-          &google::LogMessage::SendToLog).stream() \
-          << reinterpret_cast<const char*>(message); \
-      LocalFree(message); \
-    } \
-  }
-#endif
-
-// We use the preprocessor's merging operator, "##", so that, e.g.,
-// LOG(INFO) becomes the token GOOGLE_LOG_INFO.  There's some funny
-// subtle difference between ostream member streaming functions (e.g.,
-// ostream::operator<<(int) and ostream non-member streaming functions
-// (e.g., ::operator<<(ostream&, string&): it turns out that it's
-// impossible to stream something like a string directly to an unnamed
-// ostream. We employ a neat hack by calling the stream() member
-// function of LogMessage which seems to avoid the problem.
-#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
-#define SYSLOG(severity) SYSLOG_ ## severity(0).stream()
-
-namespace google {
-
-// They need the definitions of integer types.
-#include <glog/log_severity.h>
-#include <glog/vlog_is_on.h>
-
-// Initialize google's logging library. You will see the program name
-// specified by argv0 in log outputs.
-GLOG_EXPORT void InitGoogleLogging(const char* argv0);
-
-GLOG_EXPORT void InitGoogleLogging(const char* argv0,
-                                   CustomPrefixCallback prefix_callback,
-                                   void* prefix_callback_data = NULL);
-
-// Check if google's logging library has been initialized.
-GLOG_EXPORT bool IsGoogleLoggingInitialized();
-
-// Shutdown google's logging library.
-GLOG_EXPORT void ShutdownGoogleLogging();
-
-#if defined(__GNUC__)
-typedef void (*logging_fail_func_t)() __attribute__((noreturn));
-#else
-typedef void (*logging_fail_func_t)();
-#endif
-
-// Install a function which will be called after LOG(FATAL).
-GLOG_EXPORT void InstallFailureFunction(logging_fail_func_t fail_func);
-
-// Enable/Disable old log cleaner.
-GLOG_EXPORT void EnableLogCleaner(unsigned int overdue_days);
-GLOG_EXPORT void DisableLogCleaner();
-GLOG_EXPORT void SetApplicationFingerprint(const std::string& fingerprint);
-
-class LogSink;  // defined below
-
-// If a non-NULL sink pointer is given, we push this message to that sink.
-// For LOG_TO_SINK we then do normal LOG(severity) logging as well.
-// This is useful for capturing messages and passing/storing them
-// somewhere more specific than the global log of the process.
-// Argument types:
-//   LogSink* sink;
-//   LogSeverity severity;
-// The cast is to disambiguate NULL arguments.
-#define LOG_TO_SINK(sink, severity) \
-  google::LogMessage(                                    \
-      __FILE__, __LINE__,                                               \
-      google::GLOG_ ## severity,                         \
-      static_cast<google::LogSink*>(sink), true).stream()
-#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity)                  \
-  google::LogMessage(                                    \
-      __FILE__, __LINE__,                                               \
-      google::GLOG_ ## severity,                         \
-      static_cast<google::LogSink*>(sink), false).stream()
-
-// If a non-NULL string pointer is given, we write this message to that string.
-// We then do normal LOG(severity) logging as well.
-// This is useful for capturing messages and storing them somewhere more
-// specific than the global log of the process.
-// Argument types:
-//   string* message;
-//   LogSeverity severity;
-// The cast is to disambiguate NULL arguments.
-// NOTE: LOG(severity) expands to LogMessage().stream() for the specified
-// severity.
-#define LOG_TO_STRING(severity, message) \
-  LOG_TO_STRING_##severity(static_cast<std::string*>(message)).stream()
-
-// If a non-NULL pointer is given, we push the message onto the end
-// of a vector of strings; otherwise, we report it with LOG(severity).
-// This is handy for capturing messages and perhaps passing them back
-// to the caller, rather than reporting them immediately.
-// Argument types:
-//   LogSeverity severity;
-//   vector<string> *outvec;
-// The cast is to disambiguate NULL arguments.
-#define LOG_STRING(severity, outvec) \
-  LOG_TO_STRING_##severity(static_cast<std::vector<std::string>*>(outvec)).stream()
-
-#define LOG_IF(severity, condition) \
-  static_cast<void>(0),             \
-  !(condition) ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-#define SYSLOG_IF(severity, condition) \
-  static_cast<void>(0),                \
-  !(condition) ? (void) 0 : google::LogMessageVoidify() & SYSLOG(severity)
-
-#define LOG_ASSERT(condition)  \
-  LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
-#define SYSLOG_ASSERT(condition) \
-  SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
-
-// CHECK dies with a fatal error if condition is not true.  It is *not*
-// controlled by DCHECK_IS_ON(), so the check will be executed regardless of
-// compilation mode.  Therefore, it is safe to do things like:
-//    CHECK(fp->Write(x) == 4)
-#define CHECK(condition)  \
-      LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
-             << "Check failed: " #condition " "
-
-// A container for a string pointer which can be evaluated to a bool -
-// true iff the pointer is NULL.
-struct CheckOpString {
-  CheckOpString(std::string* str) : str_(str) { }
-  // No destructor: if str_ is non-NULL, we're about to LOG(FATAL),
-  // so there's no point in cleaning up str_.
-  operator bool() const {
-    return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != NULL);
-  }
-  std::string* str_;
-};
-
-// Function is overloaded for integral types to allow static const
-// integrals declared in classes and not defined to be used as arguments to
-// CHECK* macros. It's not encouraged though.
-template <class T>
-inline const T&       GetReferenceableValue(const T&           t) { return t; }
-inline char           GetReferenceableValue(char               t) { return t; }
-inline unsigned char  GetReferenceableValue(unsigned char      t) { return t; }
-inline signed char    GetReferenceableValue(signed char        t) { return t; }
-inline short          GetReferenceableValue(short              t) { return t; }
-inline unsigned short GetReferenceableValue(unsigned short     t) { return t; }
-inline int            GetReferenceableValue(int                t) { return t; }
-inline unsigned int   GetReferenceableValue(unsigned int       t) { return t; }
-inline long           GetReferenceableValue(long               t) { return t; }
-inline unsigned long GetReferenceableValue(unsigned long t) { return t; }
-inline long long      GetReferenceableValue(long long          t) { return t; }
-inline unsigned long long GetReferenceableValue(unsigned long long t) {
-  return t;
-}
-
-// This is a dummy class to define the following operator.
-struct DummyClassToDefineOperator {};
-
-}
-
-// Define global operator<< to declare using ::operator<<.
-// This declaration will allow use to use CHECK macros for user
-// defined classes which have operator<< (e.g., stl_logging.h).
-inline std::ostream& operator<<(
-    std::ostream& out, const google::DummyClassToDefineOperator&) {
-  return out;
-}
-
-namespace google {
-
-// This formats a value for a failing CHECK_XX statement.  Ordinarily,
-// it uses the definition for operator<<, with a few special cases below.
-template <typename T>
-inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
-  (*os) << v;
-}
-
-// Overrides for char types provide readable values for unprintable
-// characters.
-template <> GLOG_EXPORT
-void MakeCheckOpValueString(std::ostream* os, const char& v);
-template <> GLOG_EXPORT
-void MakeCheckOpValueString(std::ostream* os, const signed char& v);
-template <> GLOG_EXPORT
-void MakeCheckOpValueString(std::ostream* os, const unsigned char& v);
-
-// Provide printable value for nullptr_t
-template <>
-GLOG_EXPORT void MakeCheckOpValueString(std::ostream* os,
-                                        const std::nullptr_t& v);
-
-// Build the error message string. Specify no inlining for code size.
-template <typename T1, typename T2>
-std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
-    __attribute__((noinline));
-
-namespace base {
-namespace internal {
-
-// If "s" is less than base_logging::INFO, returns base_logging::INFO.
-// If "s" is greater than base_logging::FATAL, returns
-// base_logging::ERROR.  Otherwise, returns "s".
-LogSeverity NormalizeSeverity(LogSeverity s);
-
-}  // namespace internal
-
-// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
-// statement.  See MakeCheckOpString for sample usage.  Other
-// approaches were considered: use of a template method (e.g.,
-// base::BuildCheckOpString(exprtext, base::Print<T1>, &v1,
-// base::Print<T2>, &v2), however this approach has complications
-// related to volatile arguments and function-pointer arguments).
-class GLOG_EXPORT CheckOpMessageBuilder {
- public:
-  // Inserts "exprtext" and " (" to the stream.
-  explicit CheckOpMessageBuilder(const char *exprtext);
-  // Deletes "stream_".
-  ~CheckOpMessageBuilder();
-  // For inserting the first variable.
-  std::ostream* ForVar1() { return stream_; }
-  // For inserting the second variable (adds an intermediate " vs. ").
-  std::ostream* ForVar2();
-  // Get the result (inserts the closing ")").
-  std::string* NewString();
-
- private:
-  std::ostringstream *stream_;
-};
-
-}  // namespace base
-
-template <typename T1, typename T2>
-std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
-  base::CheckOpMessageBuilder comb(exprtext);
-  MakeCheckOpValueString(comb.ForVar1(), v1);
-  MakeCheckOpValueString(comb.ForVar2(), v2);
-  return comb.NewString();
-}
-
-// Helper functions for CHECK_OP macro.
-// The (int, int) specialization works around the issue that the compiler
-// will not instantiate the template version of the function on values of
-// unnamed enum type - see comment below.
-#define DEFINE_CHECK_OP_IMPL(name, op) \
-  template <typename T1, typename T2> \
-  inline std::string* name##Impl(const T1& v1, const T2& v2,    \
-                            const char* exprtext) { \
-    if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
-    else return MakeCheckOpString(v1, v2, exprtext); \
-  } \
-  inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
-    return name##Impl<int, int>(v1, v2, exprtext); \
-  }
-
-// We use the full name Check_EQ, Check_NE, etc. in case the file including
-// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
-// This happens if, for example, those are used as token names in a
-// yacc grammar.
-DEFINE_CHECK_OP_IMPL(Check_EQ, ==)  // Compilation error with CHECK_EQ(NULL, x)?
-DEFINE_CHECK_OP_IMPL(Check_NE, !=)  // Use CHECK(x == NULL) instead.
-DEFINE_CHECK_OP_IMPL(Check_LE, <=)
-DEFINE_CHECK_OP_IMPL(Check_LT, < )
-DEFINE_CHECK_OP_IMPL(Check_GE, >=)
-DEFINE_CHECK_OP_IMPL(Check_GT, > )
-#undef DEFINE_CHECK_OP_IMPL
-
-// Helper macro for binary operators.
-// Don't use this macro directly in your code, use CHECK_EQ et al below.
-
-#if defined(STATIC_ANALYSIS)
-// Only for static analysis tool to know that it is equivalent to assert
-#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2))
-#elif DCHECK_IS_ON()
-// In debug mode, avoid constructing CheckOpStrings if possible,
-// to reduce the overhead of CHECK statments by 2x.
-// Real DCHECK-heavy tests have seen 1.5x speedups.
-
-// The meaning of "string" might be different between now and
-// when this macro gets invoked (e.g., if someone is experimenting
-// with other string implementations that get defined after this
-// file is included).  Save the current meaning now and use it
-// in the macro.
-typedef std::string _Check_string;
-#define CHECK_OP_LOG(name, op, val1, val2, log)                         \
-  while (google::_Check_string* _result =                \
-         google::Check##name##Impl(                      \
-             google::GetReferenceableValue(val1),        \
-             google::GetReferenceableValue(val2),        \
-             #val1 " " #op " " #val2))                                  \
-    log(__FILE__, __LINE__,                                             \
-        google::CheckOpString(_result)).stream()
-#else
-// In optimized mode, use CheckOpString to hint to compiler that
-// the while condition is unlikely.
-#define CHECK_OP_LOG(name, op, val1, val2, log)                         \
-  while (google::CheckOpString _result =                 \
-         google::Check##name##Impl(                      \
-             google::GetReferenceableValue(val1),        \
-             google::GetReferenceableValue(val2),        \
-             #val1 " " #op " " #val2))                                  \
-    log(__FILE__, __LINE__, _result).stream()
-#endif  // STATIC_ANALYSIS, DCHECK_IS_ON()
-
-#if GOOGLE_STRIP_LOG <= 3
-#define CHECK_OP(name, op, val1, val2) \
-  CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal)
-#else
-#define CHECK_OP(name, op, val1, val2) \
-  CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal)
-#endif // STRIP_LOG <= 3
-
-// Equality/Inequality checks - compare two values, and log a FATAL message
-// including the two values when the result is not as expected.  The values
-// must have operator<<(ostream, ...) defined.
-//
-// You may append to the error message like so:
-//   CHECK_NE(1, 2) << ": The world must be ending!";
-//
-// We are very careful to ensure that each argument is evaluated exactly
-// once, and that anything which is legal to pass as a function argument is
-// legal here.  In particular, the arguments may be temporary expressions
-// which will end up being destroyed at the end of the apparent statement,
-// for example:
-//   CHECK_EQ(string("abc")[1], 'b');
-//
-// WARNING: These don't compile correctly if one of the arguments is a pointer
-// and the other is NULL. To work around this, simply static_cast NULL to the
-// type of the desired pointer.
-
-#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2)
-#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2)
-#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2)
-#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2)
-#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2)
-#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2)
-
-// Check that the input is non NULL.  This very useful in constructor
-// initializer lists.
-
-#define CHECK_NOTNULL(val) \
-  google::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
-
-// Helper functions for string comparisons.
-// To avoid bloat, the definitions are in logging.cc.
-#define DECLARE_CHECK_STROP_IMPL(func, expected) \
-  GLOG_EXPORT std::string* Check##func##expected##Impl( \
-      const char* s1, const char* s2, const char* names);
-DECLARE_CHECK_STROP_IMPL(strcmp, true)
-DECLARE_CHECK_STROP_IMPL(strcmp, false)
-DECLARE_CHECK_STROP_IMPL(strcasecmp, true)
-DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
-#undef DECLARE_CHECK_STROP_IMPL
-
-// Helper macro for string comparisons.
-// Don't use this macro directly in your code, use CHECK_STREQ et al below.
-#define CHECK_STROP(func, op, expected, s1, s2) \
-  while (google::CheckOpString _result = \
-         google::Check##func##expected##Impl((s1), (s2), \
-                                     #s1 " " #op " " #s2)) \
-    LOG(FATAL) << *_result.str_
-
-
-// String (char*) equality/inequality checks.
-// CASE versions are case-insensitive.
-//
-// Note that "s1" and "s2" may be temporary strings which are destroyed
-// by the compiler at the end of the current "full expression"
-// (e.g. CHECK_STREQ(Foo().c_str(), Bar().c_str())).
-
-#define CHECK_STREQ(s1, s2) CHECK_STROP(strcmp, ==, true, s1, s2)
-#define CHECK_STRNE(s1, s2) CHECK_STROP(strcmp, !=, false, s1, s2)
-#define CHECK_STRCASEEQ(s1, s2) CHECK_STROP(strcasecmp, ==, true, s1, s2)
-#define CHECK_STRCASENE(s1, s2) CHECK_STROP(strcasecmp, !=, false, s1, s2)
-
-#define CHECK_INDEX(I,A) CHECK(I < (sizeof(A)/sizeof(A[0])))
-#define CHECK_BOUND(B,A) CHECK(B <= (sizeof(A)/sizeof(A[0])))
-
-#define CHECK_DOUBLE_EQ(val1, val2)              \
-  do {                                           \
-    CHECK_LE((val1), (val2)+0.000000000000001L); \
-    CHECK_GE((val1), (val2)-0.000000000000001L); \
-  } while (0)
-
-#define CHECK_NEAR(val1, val2, margin)           \
-  do {                                           \
-    CHECK_LE((val1), (val2)+(margin));           \
-    CHECK_GE((val1), (val2)-(margin));           \
-  } while (0)
-
-// perror()..googly style!
-//
-// PLOG() and PLOG_IF() and PCHECK() behave exactly like their LOG* and
-// CHECK equivalents with the addition that they postpend a description
-// of the current state of errno to their output lines.
-
-#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream()
-
-#define GOOGLE_PLOG(severity, counter)  \
-  google::ErrnoLogMessage( \
-      __FILE__, __LINE__, google::GLOG_ ## severity, counter, \
-      &google::LogMessage::SendToLog)
-
-#define PLOG_IF(severity, condition) \
-  static_cast<void>(0),              \
-  !(condition) ? (void) 0 : google::LogMessageVoidify() & PLOG(severity)
-
-// A CHECK() macro that postpends errno if the condition is false. E.g.
-//
-// if (poll(fds, nfds, timeout) == -1) { PCHECK(errno == EINTR); ... }
-#define PCHECK(condition)  \
-      PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
-              << "Check failed: " #condition " "
-
-// A CHECK() macro that lets you assert the success of a function that
-// returns -1 and sets errno in case of an error. E.g.
-//
-// CHECK_ERR(mkdir(path, 0700));
-//
-// or
-//
-// int fd = open(filename, flags); CHECK_ERR(fd) << ": open " << filename;
-#define CHECK_ERR(invocation)                                          \
-PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1))    \
-        << #invocation
-
-// Use macro expansion to create, for each use of LOG_EVERY_N(), static
-// variables with the __LINE__ expansion as part of the variable name.
-#define LOG_EVERY_N_VARNAME(base, line) LOG_EVERY_N_VARNAME_CONCAT(base, line)
-#define LOG_EVERY_N_VARNAME_CONCAT(base, line) base ## line
-
-#define LOG_OCCURRENCES LOG_EVERY_N_VARNAME(occurrences_, __LINE__)
-#define LOG_OCCURRENCES_MOD_N LOG_EVERY_N_VARNAME(occurrences_mod_n_, __LINE__)
-
-#define LOG_TIME_PERIOD LOG_EVERY_N_VARNAME(timePeriod_, __LINE__)
-#define LOG_PREVIOUS_TIME_RAW LOG_EVERY_N_VARNAME(previousTimeRaw_, __LINE__)
-#define LOG_TIME_DELTA LOG_EVERY_N_VARNAME(deltaTime_, __LINE__)
-#define LOG_CURRENT_TIME LOG_EVERY_N_VARNAME(currentTime_, __LINE__)
-#define LOG_PREVIOUS_TIME LOG_EVERY_N_VARNAME(previousTime_, __LINE__)
-
-#if defined(__has_feature)
-#  if __has_feature(thread_sanitizer)
-#    define GLOG_SANITIZE_THREAD 1
-#  endif
-#endif
-
-#if !defined(GLOG_SANITIZE_THREAD) && defined(__SANITIZE_THREAD__) && __SANITIZE_THREAD__
-#  define GLOG_SANITIZE_THREAD 1
-#endif
-
-#if defined(GLOG_SANITIZE_THREAD)
-#define GLOG_IFDEF_THREAD_SANITIZER(X) X
-#else
-#define GLOG_IFDEF_THREAD_SANITIZER(X)
-#endif
-
-#if defined(GLOG_SANITIZE_THREAD)
-} // namespace google
-
-// We need to identify the static variables as "benign" races
-// to avoid noisy reports from TSAN.
-extern "C" void AnnotateBenignRaceSized(
-  const char *file,
-  int line,
-  const volatile void *mem,
-  size_t size,
-  const char *description);
-
-namespace google {
-#endif
-
-#define SOME_KIND_OF_LOG_EVERY_T(severity, seconds)                            \
-  constexpr std::chrono::nanoseconds LOG_TIME_PERIOD =                         \
-      std::chrono::duration_cast<std::chrono::nanoseconds>(                    \
-          std::chrono::duration<double>(seconds));                             \
-  static std::atomic<google ::int64> LOG_PREVIOUS_TIME_RAW;    \
-  GLOG_IFDEF_THREAD_SANITIZER(                                                 \
-      AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_TIME_PERIOD,            \
-                              sizeof(@ac_google_namespace @ ::int64), ""));    \
-  GLOG_IFDEF_THREAD_SANITIZER(                                                 \
-      AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_PREVIOUS_TIME_RAW,      \
-                              sizeof(@ac_google_namespace @ ::int64), ""));    \
-  const auto LOG_CURRENT_TIME =                                                \
-      std::chrono::duration_cast<std::chrono::nanoseconds>(                    \
-          std::chrono::steady_clock::now().time_since_epoch());                \
-  const auto LOG_PREVIOUS_TIME =                                               \
-      LOG_PREVIOUS_TIME_RAW.load(std::memory_order_relaxed);                   \
-  const auto LOG_TIME_DELTA =                                                  \
-      LOG_CURRENT_TIME - std::chrono::nanoseconds(LOG_PREVIOUS_TIME);          \
-  if (LOG_TIME_DELTA > LOG_TIME_PERIOD)                                        \
-    LOG_PREVIOUS_TIME_RAW.store(                                               \
-        std::chrono::duration_cast<std::chrono::nanoseconds>(LOG_CURRENT_TIME) \
-            .count(),                                                          \
-        std::memory_order_relaxed);                                            \
-  if (LOG_TIME_DELTA > LOG_TIME_PERIOD)                                        \
-  google ::LogMessage(                                         \
-      __FILE__, __LINE__, google ::GLOG_##severity)            \
-      .stream()
-
-#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
-  static std::atomic<int> LOG_OCCURRENCES(0), LOG_OCCURRENCES_MOD_N(0); \
-  GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES, sizeof(int), "")); \
-  GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES_MOD_N, sizeof(int), "")); \
-  ++LOG_OCCURRENCES; \
-  if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
-  if (LOG_OCCURRENCES_MOD_N == 1) \
-    google::LogMessage( \
-        __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
-        &what_to_do).stream()
-
-#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
-  static std::atomic<int> LOG_OCCURRENCES(0), LOG_OCCURRENCES_MOD_N(0); \
-  GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES, sizeof(int), "")); \
-  GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES_MOD_N, sizeof(int), "")); \
-  ++LOG_OCCURRENCES; \
-  if ((condition) && \
-      ((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \
-    google::LogMessage( \
-        __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
-                 &what_to_do).stream()
-
-#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
-  static std::atomic<int> LOG_OCCURRENCES(0), LOG_OCCURRENCES_MOD_N(0); \
-  GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES, sizeof(int), "")); \
-  GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES_MOD_N, sizeof(int), "")); \
-  ++LOG_OCCURRENCES; \
-  if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
-  if (LOG_OCCURRENCES_MOD_N == 1) \
-    google::ErrnoLogMessage( \
-        __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
-        &what_to_do).stream()
-
-#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
-  static std::atomic<int> LOG_OCCURRENCES(0); \
-  GLOG_IFDEF_THREAD_SANITIZER(AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_OCCURRENCES, sizeof(int), "")); \
-  if (LOG_OCCURRENCES <= n) \
-    ++LOG_OCCURRENCES; \
-  if (LOG_OCCURRENCES <= n) \
-    google::LogMessage( \
-        __FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
-        &what_to_do).stream()
-
-namespace glog_internal_namespace_ {
-template <bool>
-struct CompileAssert {
-};
-struct CrashReason;
-
-// Returns true if FailureSignalHandler is installed.
-// Needs to be exported since it's used by the signalhandler_unittest.
-GLOG_EXPORT bool IsFailureSignalHandlerInstalled();
-}  // namespace glog_internal_namespace_
-
-#define LOG_EVERY_N(severity, n)                                        \
-  SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
-
-#define LOG_EVERY_T(severity, T) SOME_KIND_OF_LOG_EVERY_T(severity, (T))
-
-#define SYSLOG_EVERY_N(severity, n) \
-  SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToSyslogAndLog)
-
-#define PLOG_EVERY_N(severity, n) \
-  SOME_KIND_OF_PLOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
-
-#define LOG_FIRST_N(severity, n) \
-  SOME_KIND_OF_LOG_FIRST_N(severity, (n), google::LogMessage::SendToLog)
-
-#define LOG_IF_EVERY_N(severity, condition, n) \
-  SOME_KIND_OF_LOG_IF_EVERY_N(severity, (condition), (n), google::LogMessage::SendToLog)
-
-// We want the special COUNTER value available for LOG_EVERY_X()'ed messages
-enum PRIVATE_Counter {COUNTER};
-
-#ifdef GLOG_NO_ABBREVIATED_SEVERITIES
-// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
-// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
-// to keep using this syntax, we define this macro to do the same thing
-// as COMPACT_GOOGLE_LOG_ERROR.
-#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
-#define SYSLOG_0 SYSLOG_ERROR
-#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR
-// Needed for LOG_IS_ON(ERROR).
-const LogSeverity GLOG_0 = GLOG_ERROR;
-#else
-// Users may include windows.h after logging.h without
-// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN.
-// For this case, we cannot detect if ERROR is defined before users
-// actually use ERROR. Let's make an undefined symbol to warn users.
-# define GLOG_ERROR_MSG ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail
-# define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG
-# define SYSLOG_0 GLOG_ERROR_MSG
-# define LOG_TO_STRING_0 GLOG_ERROR_MSG
-# define GLOG_0 GLOG_ERROR_MSG
-#endif
-
-// Plus some debug-logging macros that get compiled to nothing for production
-
-#if DCHECK_IS_ON()
-
-#define DLOG(severity) LOG(severity)
-#define DVLOG(verboselevel) VLOG(verboselevel)
-#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
-#define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n)
-#define DLOG_IF_EVERY_N(severity, condition, n) \
-  LOG_IF_EVERY_N(severity, condition, n)
-#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
-
-// debug-only checking.  executed if DCHECK_IS_ON().
-#define DCHECK(condition) CHECK(condition)
-#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2)
-#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2)
-#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2)
-#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2)
-#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2)
-#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2)
-#define DCHECK_NOTNULL(val) CHECK_NOTNULL(val)
-#define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2)
-#define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2)
-#define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2)
-#define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2)
-
-#else  // !DCHECK_IS_ON()
-
-#define DLOG(severity)  \
-  static_cast<void>(0), \
-  true ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-
-#define DVLOG(verboselevel)             \
-  static_cast<void>(0),                 \
-  (true || !VLOG_IS_ON(verboselevel)) ? \
-      (void) 0 : google::LogMessageVoidify() & LOG(INFO)
-
-#define DLOG_IF(severity, condition) \
-  static_cast<void>(0),              \
-  (true || !(condition)) ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-
-#define DLOG_EVERY_N(severity, n) \
-  static_cast<void>(0),           \
-  true ? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-
-#define DLOG_IF_EVERY_N(severity, condition, n) \
-  static_cast<void>(0),                         \
-  (true || !(condition))? (void) 0 : google::LogMessageVoidify() & LOG(severity)
-
-#define DLOG_ASSERT(condition) \
-  static_cast<void>(0),        \
-  true ? (void) 0 : LOG_ASSERT(condition)
-
-// MSVC warning C4127: conditional expression is constant
-#define DCHECK(condition) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK(condition)
-
-#define DCHECK_EQ(val1, val2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_EQ(val1, val2)
-
-#define DCHECK_NE(val1, val2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_NE(val1, val2)
-
-#define DCHECK_LE(val1, val2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_LE(val1, val2)
-
-#define DCHECK_LT(val1, val2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_LT(val1, val2)
-
-#define DCHECK_GE(val1, val2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_GE(val1, val2)
-
-#define DCHECK_GT(val1, val2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_GT(val1, val2)
-
-// You may see warnings in release mode if you don't use the return
-// value of DCHECK_NOTNULL. Please just use DCHECK for such cases.
-#define DCHECK_NOTNULL(val) (val)
-
-#define DCHECK_STREQ(str1, str2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_STREQ(str1, str2)
-
-#define DCHECK_STRCASEEQ(str1, str2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_STRCASEEQ(str1, str2)
-
-#define DCHECK_STRNE(str1, str2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_STRNE(str1, str2)
-
-#define DCHECK_STRCASENE(str1, str2) \
-  GLOG_MSVC_PUSH_DISABLE_WARNING(4127) \
-  while (false) \
-    GLOG_MSVC_POP_WARNING() CHECK_STRCASENE(str1, str2)
-
-#endif  // DCHECK_IS_ON()
-
-// Log only in verbose mode.
-
-#define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel))
-
-#define VLOG_IF(verboselevel, condition) \
-  LOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel))
-
-#define VLOG_EVERY_N(verboselevel, n) \
-  LOG_IF_EVERY_N(INFO, VLOG_IS_ON(verboselevel), n)
-
-#define VLOG_IF_EVERY_N(verboselevel, condition, n) \
-  LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n)
-
-namespace base_logging {
-
-// LogMessage::LogStream is a std::ostream backed by this streambuf.
-// This class ignores overflow and leaves two bytes at the end of the
-// buffer to allow for a '\n' and '\0'.
-class GLOG_EXPORT LogStreamBuf : public std::streambuf {
- public:
-  // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\0'.
-  LogStreamBuf(char *buf, int len) {
-    setp(buf, buf + len - 2);
-  }
-
-  // This effectively ignores overflow.
-  int_type overflow(int_type ch) {
-    return ch;
-  }
-
-  // Legacy public ostrstream method.
-  size_t pcount() const { return static_cast<size_t>(pptr() - pbase()); }
-  char* pbase() const { return std::streambuf::pbase(); }
-};
-
-}  // namespace base_logging
-
-//
-// This class more or less represents a particular log message.  You
-// create an instance of LogMessage and then stream stuff to it.
-// When you finish streaming to it, ~LogMessage is called and the
-// full message gets streamed to the appropriate destination.
-//
-// You shouldn't actually use LogMessage's constructor to log things,
-// though.  You should use the LOG() macro (and variants thereof)
-// above.
-class GLOG_EXPORT LogMessage {
-public:
-  enum {
-    // Passing kNoLogPrefix for the line number disables the
-    // log-message prefix. Useful for using the LogMessage
-    // infrastructure as a printing utility. See also the --log_prefix
-    // flag for controlling the log-message prefix on an
-    // application-wide basis.
-    kNoLogPrefix = -1
-  };
-
-  // LogStream inherit from non-DLL-exported class (std::ostrstream)
-  // and VC++ produces a warning for this situation.
-  // However, MSDN says "C4275 can be ignored in Microsoft Visual C++
-  // 2005 if you are deriving from a type in the Standard C++ Library"
-  // http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
-  // Let's just ignore the warning.
-GLOG_MSVC_PUSH_DISABLE_WARNING(4275)
-  class GLOG_EXPORT LogStream : public std::ostream {
-GLOG_MSVC_POP_WARNING()
-  public:
-    LogStream(char *buf, int len, int64 ctr)
-        : std::ostream(NULL),
-          streambuf_(buf, len),
-          ctr_(ctr),
-          self_(this) {
-      rdbuf(&streambuf_);
-    }
-
-    int64 ctr() const { return ctr_; }
-    void set_ctr(int64 ctr) { ctr_ = ctr; }
-    LogStream* self() const { return self_; }
-
-    // Legacy std::streambuf methods.
-    size_t pcount() const { return streambuf_.pcount(); }
-    char* pbase() const { return streambuf_.pbase(); }
-    char* str() const { return pbase(); }
-
-  private:
-    LogStream(const LogStream&);
-    LogStream& operator=(const LogStream&);
-    base_logging::LogStreamBuf streambuf_;
-    int64 ctr_;  // Counter hack (for the LOG_EVERY_X() macro)
-    LogStream *self_;  // Consistency check hack
-  };
-
-public:
-  // icc 8 requires this typedef to avoid an internal compiler error.
-  typedef void (LogMessage::*SendMethod)();
-
-  LogMessage(const char* file, int line, LogSeverity severity, int64 ctr,
-             SendMethod send_method);
-
-  // Two special constructors that generate reduced amounts of code at
-  // LOG call sites for common cases.
-
-  // Used for LOG(INFO): Implied are:
-  // severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog.
-  //
-  // Using this constructor instead of the more complex constructor above
-  // saves 19 bytes per call site.
-  LogMessage(const char* file, int line);
-
-  // Used for LOG(severity) where severity != INFO.  Implied
-  // are: ctr = 0, send_method = &LogMessage::SendToLog
-  //
-  // Using this constructor instead of the more complex constructor above
-  // saves 17 bytes per call site.
-  LogMessage(const char* file, int line, LogSeverity severity);
-
-  // Constructor to log this message to a specified sink (if not NULL).
-  // Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if
-  // also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise.
-  LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink,
-             bool also_send_to_log);
-
-  // Constructor where we also give a vector<string> pointer
-  // for storing the messages (if the pointer is not NULL).
-  // Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog.
-  LogMessage(const char* file, int line, LogSeverity severity,
-             std::vector<std::string>* outvec);
-
-  // Constructor where we also give a string pointer for storing the
-  // message (if the pointer is not NULL).  Implied are: ctr = 0,
-  // send_method = &LogMessage::WriteToStringAndLog.
-  LogMessage(const char* file, int line, LogSeverity severity,
-             std::string* message);
-
-  // A special constructor used for check failures
-  LogMessage(const char* file, int line, const CheckOpString& result);
-
-  ~LogMessage();
-
-  // Flush a buffered message to the sink set in the constructor.  Always
-  // called by the destructor, it may also be called from elsewhere if
-  // needed.  Only the first call is actioned; any later ones are ignored.
-  void Flush();
-
-  // An arbitrary limit on the length of a single log message.  This
-  // is so that streaming can be done more efficiently.
-  static const size_t kMaxLogMessageLen;
-
-  // Theses should not be called directly outside of logging.*,
-  // only passed as SendMethod arguments to other LogMessage methods:
-  void SendToLog();  // Actually dispatch to the logs
-  void SendToSyslogAndLog();  // Actually dispatch to syslog and the logs
-
-  // Call abort() or similar to perform LOG(FATAL) crash.
-  [[noreturn]] static void Fail();
-
-  std::ostream& stream();
-
-  int preserved_errno() const;
-
-  // Must be called without the log_mutex held.  (L < log_mutex)
-  static int64 num_messages(int severity);
-
-  const LogMessageTime& getLogMessageTime() const;
-
-  struct LogMessageData;
-
-private:
-  // Fully internal SendMethod cases:
-  void SendToSinkAndLog();  // Send to sink if provided and dispatch to the logs
-  void SendToSink();  // Send to sink if provided, do nothing otherwise.
-
-  // Write to string if provided and dispatch to the logs.
-  void WriteToStringAndLog();
-
-  void SaveOrSendToLog();  // Save to stringvec if provided, else to logs
-
-  void Init(const char* file, int line, LogSeverity severity,
-            void (LogMessage::*send_method)());
-
-  // Used to fill in crash information during LOG(FATAL) failures.
-  void RecordCrashReason(glog_internal_namespace_::CrashReason* reason);
-
-  // Counts of messages sent at each priority:
-  static int64 num_messages_[NUM_SEVERITIES];  // under log_mutex
-
-  // We keep the data in a separate struct so that each instance of
-  // LogMessage uses less stack space.
-  LogMessageData* allocated_;
-  LogMessageData* data_;
-  LogMessageTime logmsgtime_;
-
-  friend class LogDestination;
-
-  LogMessage(const LogMessage&);
-  void operator=(const LogMessage&);
-};
-
-// This class happens to be thread-hostile because all instances share
-// a single data buffer, but since it can only be created just before
-// the process dies, we don't worry so much.
-class GLOG_EXPORT LogMessageFatal : public LogMessage {
- public:
-  LogMessageFatal(const char* file, int line);
-  LogMessageFatal(const char* file, int line, const CheckOpString& result);
-  [[noreturn]] ~LogMessageFatal();
-};
-
-// A non-macro interface to the log facility; (useful
-// when the logging level is not a compile-time constant).
-inline void LogAtLevel(int const severity, std::string const &msg) {
-  LogMessage(__FILE__, __LINE__, severity).stream() << msg;
-}
-
-// A macro alternative of LogAtLevel. New code may want to use this
-// version since there are two advantages: 1. this version outputs the
-// file name and the line number where this macro is put like other
-// LOG macros, 2. this macro can be used as C++ stream.
-#define LOG_AT_LEVEL(severity) google::LogMessage(__FILE__, __LINE__, severity).stream()
-
-// Helper for CHECK_NOTNULL().
-//
-// In C++11, all cases can be handled by a single function. Since the value
-// category of the argument is preserved (also for rvalue references),
-// member initializer lists like the one below will compile correctly:
-//
-//   Foo()
-//     : x_(CHECK_NOTNULL(MethodReturningUniquePtr())) {}
-template <typename T>
-T CheckNotNull(const char* file, int line, const char* names, T&& t) {
- if (t == nullptr) {
-   LogMessageFatal(file, line, new std::string(names));
- }
- return std::forward<T>(t);
-}
-
-// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This
-// only works if ostream is a LogStream. If the ostream is not a
-// LogStream you'll get an assert saying as much at runtime.
-GLOG_EXPORT std::ostream& operator<<(std::ostream &os,
-                                              const PRIVATE_Counter&);
-
-
-// Derived class for PLOG*() above.
-class GLOG_EXPORT ErrnoLogMessage : public LogMessage {
- public:
-  ErrnoLogMessage(const char* file, int line, LogSeverity severity, int64 ctr,
-                  void (LogMessage::*send_method)());
-
-  // Postpends ": strerror(errno) [errno]".
-  ~ErrnoLogMessage();
-
- private:
-  ErrnoLogMessage(const ErrnoLogMessage&);
-  void operator=(const ErrnoLogMessage&);
-};
-
-
-// This class is used to explicitly ignore values in the conditional
-// logging macros.  This avoids compiler warnings like "value computed
-// is not used" and "statement has no effect".
-
-class GLOG_EXPORT LogMessageVoidify {
- public:
-  LogMessageVoidify() { }
-  // This has to be an operator with a precedence lower than << but
-  // higher than ?:
-  void operator&(std::ostream&) { }
-};
-
-
-// Flushes all log files that contains messages that are at least of
-// the specified severity level.  Thread-safe.
-GLOG_EXPORT void FlushLogFiles(LogSeverity min_severity);
-
-// Flushes all log files that contains messages that are at least of
-// the specified severity level. Thread-hostile because it ignores
-// locking -- used for catastrophic failures.
-GLOG_EXPORT void FlushLogFilesUnsafe(LogSeverity min_severity);
-
-//
-// Set the destination to which a particular severity level of log
-// messages is sent.  If base_filename is "", it means "don't log this
-// severity".  Thread-safe.
-//
-GLOG_EXPORT void SetLogDestination(LogSeverity severity,
-                                            const char* base_filename);
-
-//
-// Set the basename of the symlink to the latest log file at a given
-// severity.  If symlink_basename is empty, do not make a symlink.  If
-// you don't call this function, the symlink basename is the
-// invocation name of the program.  Thread-safe.
-//
-GLOG_EXPORT void SetLogSymlink(LogSeverity severity,
-                                        const char* symlink_basename);
-
-//
-// Used to send logs to some other kind of destination
-// Users should subclass LogSink and override send to do whatever they want.
-// Implementations must be thread-safe because a shared instance will
-// be called from whichever thread ran the LOG(XXX) line.
-class GLOG_EXPORT LogSink {
- public:
-  virtual ~LogSink();
-
-  // Sink's logging logic (message_len is such as to exclude '\n' at the end).
-  // This method can't use LOG() or CHECK() as logging system mutex(s) are held
-  // during this call.
-  virtual void send(LogSeverity severity, const char* full_filename,
-                    const char* base_filename, int line,
-                    const LogMessageTime& logmsgtime, const char* message,
-                    size_t message_len);
-  // Provide an overload for compatibility purposes
-  GLOG_DEPRECATED
-  virtual void send(LogSeverity severity, const char* full_filename,
-                    const char* base_filename, int line, const std::tm* t,
-                    const char* message, size_t message_len);
-
-  // Redefine this to implement waiting for
-  // the sink's logging logic to complete.
-  // It will be called after each send() returns,
-  // but before that LogMessage exits or crashes.
-  // By default this function does nothing.
-  // Using this function one can implement complex logic for send()
-  // that itself involves logging; and do all this w/o causing deadlocks and
-  // inconsistent rearrangement of log messages.
-  // E.g. if a LogSink has thread-specific actions, the send() method
-  // can simply add the message to a queue and wake up another thread that
-  // handles real logging while itself making some LOG() calls;
-  // WaitTillSent() can be implemented to wait for that logic to complete.
-  // See our unittest for an example.
-  virtual void WaitTillSent();
-
-  // Returns the normal text output of the log message.
-  // Can be useful to implement send().
-  static std::string ToString(LogSeverity severity, const char* file, int line,
-                              const LogMessageTime &logmsgtime,
-                              const char* message, size_t message_len);
-};
-
-// Add or remove a LogSink as a consumer of logging data.  Thread-safe.
-GLOG_EXPORT void AddLogSink(LogSink *destination);
-GLOG_EXPORT void RemoveLogSink(LogSink *destination);
-
-//
-// Specify an "extension" added to the filename specified via
-// SetLogDestination.  This applies to all severity levels.  It's
-// often used to append the port we're listening on to the logfile
-// name.  Thread-safe.
-//
-GLOG_EXPORT void SetLogFilenameExtension(
-    const char* filename_extension);
-
-//
-// Make it so that all log messages of at least a particular severity
-// are logged to stderr (in addition to logging to the usual log
-// file(s)).  Thread-safe.
-//
-GLOG_EXPORT void SetStderrLogging(LogSeverity min_severity);
-
-//
-// Make it so that all log messages go only to stderr.  Thread-safe.
-//
-GLOG_EXPORT void LogToStderr();
-
-//
-// Make it so that all log messages of at least a particular severity are
-// logged via email to a list of addresses (in addition to logging to the
-// usual log file(s)).  The list of addresses is just a string containing
-// the email addresses to send to (separated by spaces, say).  Thread-safe.
-//
-GLOG_EXPORT void SetEmailLogging(LogSeverity min_severity,
-                                          const char* addresses);
-
-// A simple function that sends email. dest is a commma-separated
-// list of addressess.  Thread-safe.
-GLOG_EXPORT bool SendEmail(const char* dest, const char* subject,
-                           const char* body);
-
-GLOG_EXPORT const std::vector<std::string>& GetLoggingDirectories();
-
-// For tests only:  Clear the internal [cached] list of logging directories to
-// force a refresh the next time GetLoggingDirectories is called.
-// Thread-hostile.
-void TestOnly_ClearLoggingDirectoriesList();
-
-// Returns a set of existing temporary directories, which will be a
-// subset of the directories returned by GetLoggingDirectories().
-// Thread-safe.
-GLOG_EXPORT void GetExistingTempDirectories(
-    std::vector<std::string>* list);
-
-// Print any fatal message again -- useful to call from signal handler
-// so that the last thing in the output is the fatal message.
-// Thread-hostile, but a race is unlikely.
-GLOG_EXPORT void ReprintFatalMessage();
-
-// Truncate a log file that may be the append-only output of multiple
-// processes and hence can't simply be renamed/reopened (typically a
-// stdout/stderr).  If the file "path" is > "limit" bytes, copy the
-// last "keep" bytes to offset 0 and truncate the rest. Since we could
-// be racing with other writers, this approach has the potential to
-// lose very small amounts of data. For security, only follow symlinks
-// if the path is /proc/self/fd/*
-GLOG_EXPORT void TruncateLogFile(const char* path, uint64 limit, uint64 keep);
-
-// Truncate stdout and stderr if they are over the value specified by
-// --max_log_size; keep the final 1MB.  This function has the same
-// race condition as TruncateLogFile.
-GLOG_EXPORT void TruncateStdoutStderr();
-
-// Return the string representation of the provided LogSeverity level.
-// Thread-safe.
-GLOG_EXPORT const char* GetLogSeverityName(LogSeverity severity);
-
-// ---------------------------------------------------------------------
-// Implementation details that are not useful to most clients
-// ---------------------------------------------------------------------
-
-// A Logger is the interface used by logging modules to emit entries
-// to a log.  A typical implementation will dump formatted data to a
-// sequence of files.  We also provide interfaces that will forward
-// the data to another thread so that the invoker never blocks.
-// Implementations should be thread-safe since the logging system
-// will write to them from multiple threads.
-
-namespace base {
-
-class GLOG_EXPORT Logger {
- public:
-  virtual ~Logger();
-
-  // Writes "message[0,message_len-1]" corresponding to an event that
-  // occurred at "timestamp".  If "force_flush" is true, the log file
-  // is flushed immediately.
-  //
-  // The input message has already been formatted as deemed
-  // appropriate by the higher level logging facility.  For example,
-  // textual log messages already contain timestamps, and the
-  // file:linenumber header.
-  virtual void Write(bool force_flush,
-                     time_t timestamp,
-                     const char* message,
-                     size_t message_len) = 0;
-
-  // Flush any buffered messages
-  virtual void Flush() = 0;
-
-  // Get the current LOG file size.
-  // The returned value is approximate since some
-  // logged data may not have been flushed to disk yet.
-  virtual uint32 LogSize() = 0;
-};
-
-// Get the logger for the specified severity level.  The logger
-// remains the property of the logging module and should not be
-// deleted by the caller.  Thread-safe.
-extern GLOG_EXPORT Logger* GetLogger(LogSeverity level);
-
-// Set the logger for the specified severity level.  The logger
-// becomes the property of the logging module and should not
-// be deleted by the caller.  Thread-safe.
-extern GLOG_EXPORT void SetLogger(LogSeverity level, Logger* logger);
-
-}
-
-// glibc has traditionally implemented two incompatible versions of
-// strerror_r(). There is a poorly defined convention for picking the
-// version that we want, but it is not clear whether it even works with
-// all versions of glibc.
-// So, instead, we provide this wrapper that automatically detects the
-// version that is in use, and then implements POSIX semantics.
-// N.B. In addition to what POSIX says, we also guarantee that "buf" will
-// be set to an empty string, if this function failed. This means, in most
-// cases, you do not need to check the error code and you can directly
-// use the value of "buf". It will never have an undefined value.
-// DEPRECATED: Use StrError(int) instead.
-GLOG_EXPORT int posix_strerror_r(int err, char *buf, size_t len);
-
-// A thread-safe replacement for strerror(). Returns a string describing the
-// given POSIX error code.
-GLOG_EXPORT std::string StrError(int err);
-
-// A class for which we define operator<<, which does nothing.
-class GLOG_EXPORT NullStream : public LogMessage::LogStream {
- public:
-  // Initialize the LogStream so the messages can be written somewhere
-  // (they'll never be actually displayed). This will be needed if a
-  // NullStream& is implicitly converted to LogStream&, in which case
-  // the overloaded NullStream::operator<< will not be invoked.
-  NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) { }
-  NullStream(const char* /*file*/, int /*line*/,
-             const CheckOpString& /*result*/) :
-      LogMessage::LogStream(message_buffer_, 1, 0) { }
-  NullStream &stream() { return *this; }
- private:
-  // A very short buffer for messages (which we discard anyway). This
-  // will be needed if NullStream& converted to LogStream& (e.g. as a
-  // result of a conditional expression).
-  char message_buffer_[2];
-};
-
-// Do nothing. This operator is inline, allowing the message to be
-// compiled away. The message will not be compiled away if we do
-// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when
-// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly
-// converted to LogStream and the message will be computed and then
-// quietly discarded.
-template<class T>
-inline NullStream& operator<<(NullStream &str, const T &) { return str; }
-
-// Similar to NullStream, but aborts the program (without stack
-// trace), like LogMessageFatal.
-class GLOG_EXPORT NullStreamFatal : public NullStream {
- public:
-  NullStreamFatal() { }
-  NullStreamFatal(const char* file, int line, const CheckOpString& result) :
-      NullStream(file, line, result) { }
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4722)
-#endif // _MSC_VER
-  [[noreturn]] ~NullStreamFatal() throw() { _exit(EXIT_FAILURE); }
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif // _MSC_VER
-};
-
-// Install a signal handler that will dump signal information and a stack
-// trace when the program crashes on certain signals.  We'll install the
-// signal handler for the following signals.
-//
-// SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM.
-//
-// By default, the signal handler will write the failure dump to the
-// standard error.  You can customize the destination by installing your
-// own writer function by InstallFailureWriter() below.
-//
-// Note on threading:
-//
-// The function should be called before threads are created, if you want
-// to use the failure signal handler for all threads.  The stack trace
-// will be shown only for the thread that receives the signal.  In other
-// words, stack traces of other threads won't be shown.
-GLOG_EXPORT void InstallFailureSignalHandler();
-
-// Installs a function that is used for writing the failure dump.  "data"
-// is the pointer to the beginning of a message to be written, and "size"
-// is the size of the message.  You should not expect the data is
-// terminated with '\0'.
-GLOG_EXPORT void InstallFailureWriter(
-    void (*writer)(const char* data, size_t size));
-
-}
-
-#pragma pop_macro("DECLARE_VARIABLE")
-#pragma pop_macro("DECLARE_bool")
-#pragma pop_macro("DECLARE_string")
-#pragma pop_macro("DECLARE_int32")
-#pragma pop_macro("DECLARE_uint32")
-
-#endif // GLOG_LOGGING_H
diff --git a/runtime/onnxruntime/third_party/glog/src/glog/logging.h.in b/runtime/onnxruntime/third_party/glog/src/glog/logging.h.in
index e8e6c41..0a7ebd2 100644
--- a/runtime/onnxruntime/third_party/glog/src/glog/logging.h.in
+++ b/runtime/onnxruntime/third_party/glog/src/glog/logging.h.in
@@ -60,10 +60,10 @@
 #define GLOG_MSVC_POP_WARNING()
 #endif
 
-#include <glog/platform.h>
+#include "glog/platform.h"
 
 #if @ac_cv_have_glog_export@
-#include <glog/export.h>
+#include "glog/export.h"
 #endif
 
 // We care a lot about number of bits things take up.  Unfortunately,
@@ -290,11 +290,11 @@
 //         "program with --v=1 or more";
 //   VLOG_EVERY_N(1, 10)
 //      << "I'm printed every 10th occurrence, and when you run the program "
-//         "with --v=1 or more. Present occurence is " << google::COUNTER;
+//         "with --v=1 or more. Present occurrence is " << google::COUNTER;
 //   VLOG_IF_EVERY_N(1, (size > 1024), 10)
-//      << "I'm printed on every 10th occurence of case when size is more "
+//      << "I'm printed on every 10th occurrence of case when size is more "
 //         " than 1024, when you run the program with --v=1 or more. ";
-//         "Present occurence is " << google::COUNTER;
+//         "Present occurrence is " << google::COUNTER;
 //
 // The supported severity levels for macros that allow you to specify one
 // are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
@@ -470,6 +470,9 @@
 // Use UTC time for logging
 DECLARE_bool(log_utc_time);
 
+// Mailer used to send logging email
+DECLARE_string(logmailer);
+
 // Log messages below the GOOGLE_STRIP_LOG level will be compiled away for
 // security reasons. See LOG(severtiy) below.
 
@@ -596,8 +599,8 @@
 @ac_google_start_namespace@
 
 // They need the definitions of integer types.
-#include <glog/log_severity.h>
-#include <glog/vlog_is_on.h>
+#include "glog/log_severity.h"
+#include "glog/vlog_is_on.h"
 
 // Initialize google's logging library. You will see the program name
 // specified by argv0 in log outputs.
@@ -842,7 +845,7 @@
 #define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2))
 #elif DCHECK_IS_ON()
 // In debug mode, avoid constructing CheckOpStrings if possible,
-// to reduce the overhead of CHECK statments by 2x.
+// to reduce the overhead of CHECK statements by 2x.
 // Real DCHECK-heavy tests have seen 1.5x speedups.
 
 // The meaning of "string" might be different between now and
@@ -1042,13 +1045,13 @@
   constexpr std::chrono::nanoseconds LOG_TIME_PERIOD =                         \
       std::chrono::duration_cast<std::chrono::nanoseconds>(                    \
           std::chrono::duration<double>(seconds));                             \
-  static std::atomic<@ac_google_namespace@ ::int64> LOG_PREVIOUS_TIME_RAW;    \
+  static std::atomic<@ac_google_namespace@::int64> LOG_PREVIOUS_TIME_RAW;      \
   GLOG_IFDEF_THREAD_SANITIZER(                                                 \
       AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_TIME_PERIOD,            \
-                              sizeof(@ac_google_namespace @ ::int64), ""));    \
+                              sizeof(@ac_google_namespace@::int64), ""));      \
   GLOG_IFDEF_THREAD_SANITIZER(                                                 \
       AnnotateBenignRaceSized(__FILE__, __LINE__, &LOG_PREVIOUS_TIME_RAW,      \
-                              sizeof(@ac_google_namespace @ ::int64), ""));    \
+                              sizeof(@ac_google_namespace@::int64), ""));      \
   const auto LOG_CURRENT_TIME =                                                \
       std::chrono::duration_cast<std::chrono::nanoseconds>(                    \
           std::chrono::steady_clock::now().time_since_epoch());                \
@@ -1062,8 +1065,8 @@
             .count(),                                                          \
         std::memory_order_relaxed);                                            \
   if (LOG_TIME_DELTA > LOG_TIME_PERIOD)                                        \
-  @ac_google_namespace@ ::LogMessage(                                         \
-      __FILE__, __LINE__, @ac_google_namespace@ ::GLOG_##severity)            \
+  @ac_google_namespace@::LogMessage(                                           \
+      __FILE__, __LINE__, @ac_google_namespace@::GLOG_##severity)              \
       .stream()
 
 #define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \
@@ -1344,6 +1347,15 @@
   class GLOG_EXPORT LogStream : public std::ostream {
 GLOG_MSVC_POP_WARNING()
   public:
+#if defined __has_attribute
+#  if __has_attribute (used)
+    // In some cases, like when compiling glog as a static library with GCC and
+    // linking against a Clang-built executable, this constructor will be
+    // removed by the linker. We use this attribute to prevent the linker from
+    // discarding it.
+    __attribute__ ((used))
+#  endif
+#endif
     LogStream(char *buf, int len, int64 ctr)
         : std::ostream(NULL),
           streambuf_(buf, len),
@@ -1425,7 +1437,7 @@
   // is so that streaming can be done more efficiently.
   static const size_t kMaxLogMessageLen;
 
-  // Theses should not be called directly outside of logging.*,
+  // These should not be called directly outside of logging.*,
   // only passed as SendMethod arguments to other LogMessage methods:
   void SendToLog();  // Actually dispatch to the logs
   void SendToSyslogAndLog();  // Actually dispatch to syslog and the logs
@@ -1652,8 +1664,8 @@
 GLOG_EXPORT void SetEmailLogging(LogSeverity min_severity,
                                           const char* addresses);
 
-// A simple function that sends email. dest is a commma-separated
-// list of addressess.  Thread-safe.
+// A simple function that sends email. dest is a comma-separated
+// list of addresses.  Thread-safe.
 GLOG_EXPORT bool SendEmail(const char* dest, const char* subject,
                            const char* body);
 
@@ -1768,11 +1780,11 @@
   // (they'll never be actually displayed). This will be needed if a
   // NullStream& is implicitly converted to LogStream&, in which case
   // the overloaded NullStream::operator<< will not be invoked.
-  NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) { }
+  NullStream();
   NullStream(const char* /*file*/, int /*line*/,
-             const CheckOpString& /*result*/) :
-      LogMessage::LogStream(message_buffer_, 1, 0) { }
-  NullStream &stream() { return *this; }
+             const CheckOpString& /*result*/);
+  NullStream& stream();
+
  private:
   // A very short buffer for messages (which we discard anyway). This
   // will be needed if NullStream& converted to LogStream& (e.g. as a
@@ -1793,17 +1805,8 @@
 // trace), like LogMessageFatal.
 class GLOG_EXPORT NullStreamFatal : public NullStream {
  public:
-  NullStreamFatal() { }
-  NullStreamFatal(const char* file, int line, const CheckOpString& result) :
-      NullStream(file, line, result) { }
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4722)
-#endif // _MSC_VER
-  [[noreturn]] ~NullStreamFatal() throw() { _exit(EXIT_FAILURE); }
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif // _MSC_VER
+  using NullStream::NullStream;
+  [[noreturn]] ~NullStreamFatal();
 };
 
 // Install a signal handler that will dump signal information and a stack
diff --git a/runtime/onnxruntime/third_party/glog/src/glog/raw_logging.h b/runtime/onnxruntime/third_party/glog/src/glog/raw_logging.h
deleted file mode 100644
index eda5fb4..0000000
--- a/runtime/onnxruntime/third_party/glog/src/glog/raw_logging.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: Maxim Lifantsev
-//
-// Thread-safe logging routines that do not allocate any memory or
-// acquire any locks, and can therefore be used by low-level memory
-// allocation and synchronization code.
-
-#ifndef GLOG_RAW_LOGGING_H
-#define GLOG_RAW_LOGGING_H
-
-#include <ctime>
-
-namespace google {
-
-#include <glog/log_severity.h>
-#include <glog/logging.h>
-#include <glog/vlog_is_on.h>
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wvariadic-macros"
-#endif
-
-// This is similar to LOG(severity) << format... and VLOG(level) << format..,
-// but
-// * it is to be used ONLY by low-level modules that can't use normal LOG()
-// * it is desiged to be a low-level logger that does not allocate any
-//   memory and does not need any locks, hence:
-// * it logs straight and ONLY to STDERR w/o buffering
-// * it uses an explicit format and arguments list
-// * it will silently chop off really long message strings
-// Usage example:
-//   RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
-//   RAW_VLOG(3, "status is %i", status);
-// These will print an almost standard log lines like this to stderr only:
-//   E20200821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
-//   I20200821 211317 file.cc:142] RAW: status is 20
-#define RAW_LOG(severity, ...) \
-  do { \
-    switch (google::GLOG_ ## severity) {  \
-      case 0: \
-        RAW_LOG_INFO(__VA_ARGS__); \
-        break; \
-      case 1: \
-        RAW_LOG_WARNING(__VA_ARGS__); \
-        break; \
-      case 2: \
-        RAW_LOG_ERROR(__VA_ARGS__); \
-        break; \
-      case 3: \
-        RAW_LOG_FATAL(__VA_ARGS__); \
-        break; \
-      default: \
-        break; \
-    } \
-  } while (0)
-
-// The following STRIP_LOG testing is performed in the header file so that it's
-// possible to completely compile out the logging code and the log messages.
-#if !defined(STRIP_LOG) || STRIP_LOG == 0
-#define RAW_VLOG(verboselevel, ...) \
-  do { \
-    if (VLOG_IS_ON(verboselevel)) { \
-      RAW_LOG_INFO(__VA_ARGS__); \
-    } \
-  } while (0)
-#else
-#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__)
-#endif // STRIP_LOG == 0
-
-#if !defined(STRIP_LOG) || STRIP_LOG == 0
-#define RAW_LOG_INFO(...) google::RawLog__(google::GLOG_INFO, \
-                                   __FILE__, __LINE__, __VA_ARGS__)
-#else
-#define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__)
-#endif // STRIP_LOG == 0
-
-#if !defined(STRIP_LOG) || STRIP_LOG <= 1
-#define RAW_LOG_WARNING(...) google::RawLog__(google::GLOG_WARNING,   \
-                                      __FILE__, __LINE__, __VA_ARGS__)
-#else
-#define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__)
-#endif // STRIP_LOG <= 1
-
-#if !defined(STRIP_LOG) || STRIP_LOG <= 2
-#define RAW_LOG_ERROR(...) google::RawLog__(google::GLOG_ERROR,       \
-                                    __FILE__, __LINE__, __VA_ARGS__)
-#else
-#define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__)
-#endif // STRIP_LOG <= 2
-
-#if !defined(STRIP_LOG) || STRIP_LOG <= 3
-#define RAW_LOG_FATAL(...) google::RawLog__(google::GLOG_FATAL,       \
-                                    __FILE__, __LINE__, __VA_ARGS__)
-#else
-#define RAW_LOG_FATAL(...) \
-  do { \
-    google::RawLogStub__(0, __VA_ARGS__);        \
-    exit(EXIT_FAILURE); \
-  } while (0)
-#endif // STRIP_LOG <= 3
-
-// Similar to CHECK(condition) << message,
-// but for low-level modules: we use only RAW_LOG that does not allocate memory.
-// We do not want to provide args list here to encourage this usage:
-//   if (!cond)  RAW_LOG(FATAL, "foo ...", hard_to_compute_args);
-// so that the args are not computed when not needed.
-#define RAW_CHECK(condition, message)                                   \
-  do {                                                                  \
-    if (!(condition)) {                                                 \
-      RAW_LOG(FATAL, "Check %s failed: %s", #condition, message);       \
-    }                                                                   \
-  } while (0)
-
-// Debug versions of RAW_LOG and RAW_CHECK
-#ifndef NDEBUG
-
-#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__)
-#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message)
-
-#else  // NDEBUG
-
-#define RAW_DLOG(severity, ...)                                 \
-  while (false)                                                 \
-    RAW_LOG(severity, __VA_ARGS__)
-#define RAW_DCHECK(condition, message) \
-  while (false) \
-    RAW_CHECK(condition, message)
-
-#endif  // NDEBUG
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-// Stub log function used to work around for unused variable warnings when
-// building with STRIP_LOG > 0.
-static inline void RawLogStub__(int /* ignored */, ...) {
-}
-
-// Helper function to implement RAW_LOG and RAW_VLOG
-// Logs format... at "severity" level, reporting it
-// as called from file:line.
-// This does not allocate memory or acquire locks.
-GLOG_EXPORT void RawLog__(LogSeverity severity, const char* file, int line,
-                          const char* format, ...)
-    __attribute__((__format__(__printf__, 4, 5)));
-
-}
-
-#endif  // GLOG_RAW_LOGGING_H
diff --git a/runtime/onnxruntime/third_party/glog/src/glog/raw_logging.h.in b/runtime/onnxruntime/third_party/glog/src/glog/raw_logging.h.in
index 66fec91..0bf52b4 100644
--- a/runtime/onnxruntime/third_party/glog/src/glog/raw_logging.h.in
+++ b/runtime/onnxruntime/third_party/glog/src/glog/raw_logging.h.in
@@ -39,10 +39,9 @@
 #include <ctime>
 
 @ac_google_start_namespace@
-
-#include <glog/log_severity.h>
-#include <glog/logging.h>
-#include <glog/vlog_is_on.h>
+#include "glog/log_severity.h"
+#include "glog/logging.h"
+#include "glog/vlog_is_on.h"
 
 #if defined(__GNUC__)
 #pragma GCC diagnostic push
diff --git a/runtime/onnxruntime/third_party/glog/src/glog/stl_logging.h b/runtime/onnxruntime/third_party/glog/src/glog/stl_logging.h
deleted file mode 100644
index 96304e5..0000000
--- a/runtime/onnxruntime/third_party/glog/src/glog/stl_logging.h
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright (c) 2003, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Stream output operators for STL containers; to be used for logging *only*.
-// Inclusion of this file lets you do:
-//
-// list<string> x;
-// LOG(INFO) << "data: " << x;
-// vector<int> v1, v2;
-// CHECK_EQ(v1, v2);
-//
-// If you want to use this header file with hash maps or slist, you
-// need to define macros before including this file:
-//
-// - GLOG_STL_LOGGING_FOR_UNORDERED     - <unordered_map> and <unordered_set>
-// - GLOG_STL_LOGGING_FOR_TR1_UNORDERED - <tr1/unordered_(map|set)>
-// - GLOG_STL_LOGGING_FOR_EXT_HASH      - <ext/hash_(map|set)>
-// - GLOG_STL_LOGGING_FOR_EXT_SLIST     - <ext/slist>
-//
-
-#ifndef UTIL_GTL_STL_LOGGING_INL_H_
-#define UTIL_GTL_STL_LOGGING_INL_H_
-
-#include <deque>
-#include <list>
-#include <map>
-#include <ostream>
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-// Forward declare these two, and define them after all the container streams
-// operators so that we can recurse from pair -> container -> container -> pair
-// properly.
-template<class First, class Second>
-std::ostream& operator<<(std::ostream& out, const std::pair<First, Second>& p);
-
-namespace google {
-
-template<class Iter>
-void PrintSequence(std::ostream& out, Iter begin, Iter end);
-
-}
-#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \
-template<class T1, class T2> \
-inline std::ostream& operator<<(std::ostream& out, \
-                                const Sequence<T1, T2>& seq) { \
-  google::PrintSequence(out, seq.begin(), seq.end()); \
-  return out; \
-}
-
-    OUTPUT_TWO_ARG_CONTAINER(std::vector) OUTPUT_TWO_ARG_CONTAINER(std::deque)
-        OUTPUT_TWO_ARG_CONTAINER(std::list)
-
-#undef OUTPUT_TWO_ARG_CONTAINER
-
-#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \
-template<class T1, class T2, class T3> \
-inline std::ostream& operator<<(std::ostream& out, \
-                                const Sequence<T1, T2, T3>& seq) { \
-  google::PrintSequence(out, seq.begin(), seq.end()); \
-  return out; \
-}
-
-            OUTPUT_THREE_ARG_CONTAINER(std::set) OUTPUT_THREE_ARG_CONTAINER(
-                std::multiset)
-
-#undef OUTPUT_THREE_ARG_CONTAINER
-
-#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \
-template<class T1, class T2, class T3, class T4> \
-inline std::ostream& operator<<(std::ostream& out, \
-                                const Sequence<T1, T2, T3, T4>& seq) { \
-  google::PrintSequence(out, seq.begin(), seq.end()); \
-  return out; \
-}
-
-                OUTPUT_FOUR_ARG_CONTAINER(std::map) OUTPUT_FOUR_ARG_CONTAINER(
-                    std::multimap) OUTPUT_FOUR_ARG_CONTAINER(std::unordered_set)
-                    OUTPUT_FOUR_ARG_CONTAINER(std::unordered_multiset)
-
-#undef OUTPUT_FOUR_ARG_CONTAINER
-
-#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \
-template<class T1, class T2, class T3, class T4, class T5> \
-inline std::ostream& operator<<(std::ostream& out, \
-                                const Sequence<T1, T2, T3, T4, T5>& seq) { \
-  google::PrintSequence(out, seq.begin(), seq.end()); \
-  return out; \
-}
-
-#if defined(GLOG_STL_LOGGING_FOR_UNORDERED) && __cplusplus >= 201103L
-                        OUTPUT_FIVE_ARG_CONTAINER(std::unordered_map)
-                            OUTPUT_FIVE_ARG_CONTAINER(std::unordered_multimap)
-#endif
-
-#undef OUTPUT_FIVE_ARG_CONTAINER
-
-                                template <class First, class Second>
-                                inline std::ostream& operator<<(
-                                    std::ostream& out,
-                                    const std::pair<First, Second>& p) {
-  out << '(' << p.first << ", " << p.second << ')';
-  return out;
-}
-
-namespace google {
-
-template<class Iter>
-inline void PrintSequence(std::ostream& out, Iter begin, Iter end) {
-  // Output at most 100 elements -- appropriate if used for logging.
-  for (int i = 0; begin != end && i < 100; ++i, ++begin) {
-    if (i > 0) out << ' ';
-    out << *begin;
-  }
-  if (begin != end) {
-    out << " ...";
-  }
-}
-
-}
-
-// Note that this is technically undefined behavior! We are adding things into
-// the std namespace for a reason though -- we are providing new operations on
-// types which are themselves defined with this namespace. Without this, these
-// operator overloads cannot be found via ADL. If these definitions are not
-// found via ADL, they must be #included before they're used, which requires
-// this header to be included before apparently independent other headers.
-//
-// For example, base/logging.h defines various template functions to implement
-// CHECK_EQ(x, y) and stream x and y into the log in the event the check fails.
-// It does so via the function template MakeCheckOpValueString:
-//   template<class T>
-//   void MakeCheckOpValueString(strstream* ss, const T& v) {
-//     (*ss) << v;
-//   }
-// Because 'glog/logging.h' is included before 'glog/stl_logging.h',
-// subsequent CHECK_EQ(v1, v2) for vector<...> typed variable v1 and v2 can only
-// find these operator definitions via ADL.
-//
-// Even this solution has problems -- it may pull unintended operators into the
-// namespace as well, allowing them to also be found via ADL, and creating code
-// that only works with a particular order of includes. Long term, we need to
-// move all of the *definitions* into namespace std, bet we need to ensure no
-// one references them first. This lets us take that step. We cannot define them
-// in both because that would create ambiguous overloads when both are found.
-namespace std { using ::operator<<; }
-
-#endif  // UTIL_GTL_STL_LOGGING_INL_H_
diff --git a/runtime/onnxruntime/third_party/glog/src/glog/vlog_is_on.h b/runtime/onnxruntime/third_party/glog/src/glog/vlog_is_on.h
deleted file mode 100644
index 44c2048..0000000
--- a/runtime/onnxruntime/third_party/glog/src/glog/vlog_is_on.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2023, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: Ray Sidney and many others
-//
-// Defines the VLOG_IS_ON macro that controls the variable-verbosity
-// conditional logging.
-//
-// It's used by VLOG and VLOG_IF in logging.h
-// and by RAW_VLOG in raw_logging.h to trigger the logging.
-//
-// It can also be used directly e.g. like this:
-//   if (VLOG_IS_ON(2)) {
-//     // do some logging preparation and logging
-//     // that can't be accomplished e.g. via just VLOG(2) << ...;
-//   }
-//
-// The truth value that VLOG_IS_ON(level) returns is determined by
-// the three verbosity level flags:
-//   --v=<n>  Gives the default maximal active V-logging level;
-//            0 is the default.
-//            Normally positive values are used for V-logging levels.
-//   --vmodule=<str>  Gives the per-module maximal V-logging levels to override
-//                    the value given by --v.
-//                    E.g. "my_module=2,foo*=3" would change the logging level
-//                    for all code in source files "my_module.*" and "foo*.*"
-//                    ("-inl" suffixes are also disregarded for this matching).
-//
-// SetVLOGLevel helper function is provided to do limited dynamic control over
-// V-logging by overriding the per-module settings given via --vmodule flag.
-//
-// CAVEAT: --vmodule functionality is not available in non gcc compilers.
-//
-
-#ifndef BASE_VLOG_IS_ON_H_
-#define BASE_VLOG_IS_ON_H_
-
-#include <glog/log_severity.h>
-
-#include <cstddef>
-
-#if defined(__GNUC__)
-// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
-// (Normally) the first time every VLOG_IS_ON(n) site is hit,
-// we determine what variable will dynamically control logging at this site:
-// it's either FLAGS_v or an appropriate internal variable
-// matching the current source file that represents results of
-// parsing of --vmodule flag and/or SetVLOGLevel calls.
-#define VLOG_IS_ON(verboselevel)                                \
-  __extension__  \
-  ({ static google::SiteFlag vlocal__ = {NULL, NULL, 0, NULL};       \
-     google::int32 verbose_level__ = (verboselevel);                    \
-     (vlocal__.level == NULL ? google::InitVLOG3__(&vlocal__, &FLAGS_v, \
-                        __FILE__, verbose_level__) : *vlocal__.level >= verbose_level__); \
-  })
-#else
-// GNU extensions not available, so we do not support --vmodule.
-// Dynamic value of FLAGS_v always controls the logging level.
-#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel))
-#endif
-
-// Set VLOG(_IS_ON) level for module_pattern to log_level.
-// This lets us dynamically control what is normally set by the --vmodule flag.
-// Returns the level that previously applied to module_pattern.
-// NOTE: To change the log level for VLOG(_IS_ON) sites
-//	 that have already executed after/during InitGoogleLogging,
-//	 one needs to supply the exact --vmodule pattern that applied to them.
-//       (If no --vmodule pattern applied to them
-//       the value of FLAGS_v will continue to control them.)
-extern GLOG_EXPORT int SetVLOGLevel(const char* module_pattern, int log_level);
-
-// Various declarations needed for VLOG_IS_ON above: =========================
-
-struct SiteFlag {
-  google::int32* level;
-  const char* base_name;
-  std::size_t base_len;
-  SiteFlag* next;
-};
-
-// Helper routine which determines the logging info for a particalur VLOG site.
-//   site_flag     is the address of the site-local pointer to the controlling
-//                 verbosity level
-//   site_default  is the default to use for *site_flag
-//   fname         is the current source file name
-//   verbose_level is the argument to VLOG_IS_ON
-// We will return the return value for VLOG_IS_ON
-// and if possible set *site_flag appropriately.
-extern GLOG_EXPORT bool InitVLOG3__(
-    google::SiteFlag* site_flag,
-    google::int32* site_default, const char* fname,
-    google::int32 verbose_level);
-
-#endif  // BASE_VLOG_IS_ON_H_
diff --git a/runtime/onnxruntime/third_party/glog/src/glog/vlog_is_on.h.in b/runtime/onnxruntime/third_party/glog/src/glog/vlog_is_on.h.in
index ed37e0d..be76dff 100644
--- a/runtime/onnxruntime/third_party/glog/src/glog/vlog_is_on.h.in
+++ b/runtime/onnxruntime/third_party/glog/src/glog/vlog_is_on.h.in
@@ -61,9 +61,9 @@
 #ifndef BASE_VLOG_IS_ON_H_
 #define BASE_VLOG_IS_ON_H_
 
-#include <glog/log_severity.h>
-
 #include <cstddef>
+
+#include "glog/log_severity.h"
 
 #if defined(__GNUC__)
 // We emit an anonymous static int* variable at every VLOG_IS_ON(n) site.
@@ -75,6 +75,8 @@
 #define VLOG_IS_ON(verboselevel)                                \
   __extension__  \
   ({ static @ac_google_namespace@::SiteFlag vlocal__ = {NULL, NULL, 0, NULL};       \
+     GLOG_IFDEF_THREAD_SANITIZER( \
+             AnnotateBenignRaceSized(__FILE__, __LINE__, &vlocal__, sizeof(@ac_google_namespace@::SiteFlag), "")); \
      @ac_google_namespace@::int32 verbose_level__ = (verboselevel);                    \
      (vlocal__.level == NULL ? @ac_google_namespace@::InitVLOG3__(&vlocal__, &FLAGS_v, \
                         __FILE__, verbose_level__) : *vlocal__.level >= verbose_level__); \
@@ -104,7 +106,7 @@
   SiteFlag* next;
 };
 
-// Helper routine which determines the logging info for a particalur VLOG site.
+// Helper routine which determines the logging info for a particular VLOG site.
 //   site_flag     is the address of the site-local pointer to the controlling
 //                 verbosity level
 //   site_default  is the default to use for *site_flag
diff --git a/runtime/onnxruntime/third_party/glog/src/logging.cc b/runtime/onnxruntime/third_party/glog/src/logging.cc
index 53b485c..8d90e2b 100644
--- a/runtime/onnxruntime/third_party/glog/src/logging.cc
+++ b/runtime/onnxruntime/third_party/glog/src/logging.cc
@@ -33,8 +33,11 @@
 
 #include <algorithm>
 #include <cassert>
+#include <cstddef>
 #include <iomanip>
+#include <iterator>
 #include <string>
+
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>  // For _exit.
 #endif
@@ -56,18 +59,23 @@
 #ifdef HAVE_SYSLOG_H
 # include <syslog.h>
 #endif
+#ifdef HAVE__CHSIZE_S
+#include <io.h> // for truncate log file
+#endif
 #include <vector>
 #include <cerrno>                   // for errno
 #include <sstream>
+#include <regex>
+#include <cctype> // for std::isspace
 #ifdef GLOG_OS_WINDOWS
 #include "windows/dirent.h"
 #else
 #include <dirent.h> // for automatic removal of old logs
 #endif
-#include "base/commandlineflags.h"        // to get the program name
-#include <glog/logging.h>
-#include <glog/raw_logging.h>
+#include "base/commandlineflags.h"  // to get the program name
 #include "base/googleinit.h"
+#include "glog/logging.h"
+#include "glog/raw_logging.h"
 
 #ifdef HAVE_STACKTRACE
 # include "stacktrace.h"
@@ -1550,9 +1558,15 @@
 // allocations).
 static thread_local bool thread_data_available = true;
 
+#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
+// std::aligned_storage is deprecated in C++23
+alignas(LogMessage::LogMessageData) static thread_local std::byte
+    thread_msg_data[sizeof(LogMessage::LogMessageData)];
+#else   // !(defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L)
 static thread_local std::aligned_storage<
     sizeof(LogMessage::LogMessageData),
     alignof(LogMessage::LogMessageData)>::type thread_msg_data;
+#endif  // defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
 #endif  // defined(GLOG_THREAD_LOCAL_STORAGE)
 
 LogMessage::LogMessageData::LogMessageData()
@@ -1918,6 +1932,14 @@
 GLOG_EXPORT logging_fail_func_t g_logging_fail_func =
     reinterpret_cast<logging_fail_func_t>(&abort);
 
+NullStream::NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) {}
+NullStream::NullStream(const char* /*file*/, int /*line*/,
+                       const CheckOpString& /*result*/)
+    : LogMessage::LogStream(message_buffer_, 1, 0) {}
+NullStream& NullStream::stream() { return *this; }
+
+NullStreamFatal::~NullStreamFatal() { _exit(EXIT_FAILURE); }
+
 void InstallFailureFunction(logging_fail_func_t fail_func) {
   g_logging_fail_func = fail_func;
 }
@@ -2205,6 +2227,13 @@
   }
   return result;
 }
+
+// Trim whitespace from both ends of the provided string.
+static inline void trim(std::string &s) {
+  const auto toRemove = [](char ch) { return std::isspace(ch) == 0; };
+  s.erase(s.begin(), std::find_if(s.begin(), s.end(), toRemove));
+  s.erase(std::find_if(s.rbegin(), s.rend(), toRemove).base(), s.end());
+}
 #endif
 
 // use_logging controls whether the logging functions LOG/VLOG are used
@@ -2214,6 +2243,47 @@
                               const char*body, bool use_logging) {
 #ifndef GLOG_OS_EMSCRIPTEN
   if (dest && *dest) {
+    // Split the comma-separated list of email addresses, validate each one and
+    // build a sanitized new comma-separated string without whitespace.
+    std::istringstream ss(dest);
+    std::ostringstream sanitized_dests;
+    std::string s;
+    while (std::getline(ss, s, ',')) {
+      trim(s);
+      if (s.empty()) {
+        continue;
+      }
+      // We validate the provided email addresses using the same regular
+      // expression that HTML5 uses[1], except that we require the address to
+      // start with an alpha-numeric character. This is because we don't want to
+      // allow email addresses that start with a special character, such as a
+      // pipe or dash, which could be misunderstood as a command-line flag by
+      // certain versions of `mail` that are vulnerable to command injection.[2]
+      // [1] https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
+      // [2] e.g. https://nvd.nist.gov/vuln/detail/CVE-2004-2771
+      if (!std::regex_match(
+              s,
+              std::regex("^[a-zA-Z0-9]"
+                         "[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]*@[a-zA-Z0-9]"
+                         "(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]"
+                         "(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"))) {
+        if (use_logging) {
+          VLOG(1) << "Invalid destination email address:" << s;
+        } else {
+          fprintf(stderr, "Invalid destination email address: %s\n",
+                  s.c_str());
+        }
+        return false;
+      }
+      if (!sanitized_dests.str().empty()) {
+        sanitized_dests << ",";
+      }
+      sanitized_dests << s;
+    }
+    // Avoid dangling reference
+    const std::string& tmp = sanitized_dests.str();
+    dest = tmp.c_str();
+
     if ( use_logging ) {
       VLOG(1) << "Trying to send TITLE:" << subject
               << " BODY:" << body << " to " << dest;
@@ -2235,8 +2305,8 @@
 
     FILE* pipe = popen(cmd.c_str(), "w");
     if (pipe != nullptr) {
-        // Add the body if we have one
-        if (body) {
+      // Add the body if we have one
+      if (body) {
         fwrite(body, sizeof(char), strlen(body), pipe);
       }
       bool ok = pclose(pipe) != -1;
@@ -2328,8 +2398,13 @@
     logging_directories_list = new vector<string>;
 
     if ( !FLAGS_log_dir.empty() ) {
-      // A dir was specified, we should use it
-      logging_directories_list->push_back(FLAGS_log_dir);
+      // Ensure the specified path ends with a directory delimiter.
+      if (std::find(std::begin(possible_dir_delim), std::end(possible_dir_delim),
+            FLAGS_log_dir.back()) == std::end(possible_dir_delim)) {
+        logging_directories_list->push_back(FLAGS_log_dir + "/");
+      } else {
+        logging_directories_list->push_back(FLAGS_log_dir);
+      }
     } else {
       GetTempDirectories(logging_directories_list);
 #ifdef GLOG_OS_WINDOWS
@@ -2367,7 +2442,7 @@
 }
 
 void TruncateLogFile(const char *path, uint64 limit, uint64 keep) {
-#ifdef HAVE_UNISTD_H
+#if defined(HAVE_UNISTD_H) || defined(HAVE__CHSIZE_S)
   struct stat statbuf;
   const int kCopyBlockSize = 8 << 10;
   char copybuf[kCopyBlockSize];
@@ -2388,7 +2463,11 @@
       // all of base/...) with -D_FILE_OFFSET_BITS=64 but that's
       // rather scary.
       // Instead just truncate the file to something we can manage
+#ifdef HAVE__CHSIZE_S
+      if (_chsize_s(fd, 0) != 0) {
+#else
       if (truncate(path, 0) == -1) {
+#endif
         PLOG(ERROR) << "Unable to truncate " << path;
       } else {
         LOG(ERROR) << "Truncated " << path << " due to EFBIG error";
@@ -2433,7 +2512,11 @@
   // Truncate the remainder of the file. If someone else writes to the
   // end of the file after our last read() above, we lose their latest
   // data. Too bad ...
+#ifdef HAVE__CHSIZE_S
+  if (_chsize_s(fd, write_offset) != 0) {
+#else
   if (ftruncate(fd, write_offset) == -1) {
+#endif
     PLOG(ERROR) << "Unable to truncate " << path;
   }
 
diff --git a/runtime/onnxruntime/third_party/glog/src/mock-log.h b/runtime/onnxruntime/third_party/glog/src/mock-log.h
index 62999b2..a6c1147 100644
--- a/runtime/onnxruntime/third_party/glog/src/mock-log.h
+++ b/runtime/onnxruntime/third_party/glog/src/mock-log.h
@@ -36,13 +36,12 @@
 #define GLOG_SRC_MOCK_LOG_H_
 
 // For GOOGLE_NAMESPACE. This must go first so we get _XOPEN_SOURCE.
-#include "utilities.h"
+#include <gmock/gmock.h>
 
 #include <string>
 
-#include <gmock/gmock.h>
-
-#include <glog/logging.h>
+#include "glog/logging.h"
+#include "utilities.h"
 
 _START_GOOGLE_NAMESPACE_
 namespace glog_testing {
diff --git a/runtime/onnxruntime/third_party/glog/src/raw_logging.cc b/runtime/onnxruntime/third_party/glog/src/raw_logging.cc
index 9e6cf17..8debc18 100644
--- a/runtime/onnxruntime/third_party/glog/src/raw_logging.cc
+++ b/runtime/onnxruntime/third_party/glog/src/raw_logging.cc
@@ -39,12 +39,14 @@
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>               // for close() and write()
 #endif
-#include <fcntl.h>                 // for open()
+#include <fcntl.h>  // for open()
+
 #include <ctime>
-#include "config.h"
-#include <glog/logging.h>          // To pick up flag settings etc.
-#include <glog/raw_logging.h>
+
 #include "base/commandlineflags.h"
+#include "config.h"
+#include "glog/logging.h"  // To pick up flag settings etc.
+#include "glog/raw_logging.h"
 
 #ifdef HAVE_STACKTRACE
 # include "stacktrace.h"
@@ -60,7 +62,8 @@
 #endif
 
 #if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && \
-    (!(defined(GLOG_OS_MACOSX))) && !defined(GLOG_OS_EMSCRIPTEN)
+    (!(defined(GLOG_OS_MACOSX)) && !(defined(GLOG_OS_OPENBSD))) && \
+    !defined(GLOG_OS_EMSCRIPTEN)
 #define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
 #else
 // Not so safe, but what can you do?
diff --git a/runtime/onnxruntime/third_party/glog/src/signalhandler.cc b/runtime/onnxruntime/third_party/glog/src/signalhandler.cc
index 657e15c..f53e687 100644
--- a/runtime/onnxruntime/third_party/glog/src/signalhandler.cc
+++ b/runtime/onnxruntime/third_party/glog/src/signalhandler.cc
@@ -31,13 +31,13 @@
 //
 // Implementation of InstallFailureSignalHandler().
 
-#include "utilities.h"
-#include "stacktrace.h"
-#include "symbolize.h"
-#include <glog/logging.h>
-
 #include <csignal>
 #include <ctime>
+
+#include "glog/logging.h"
+#include "stacktrace.h"
+#include "symbolize.h"
+#include "utilities.h"
 #ifdef HAVE_UCONTEXT_H
 # include <ucontext.h>
 #endif
diff --git a/runtime/onnxruntime/third_party/glog/src/stacktrace.h b/runtime/onnxruntime/third_party/glog/src/stacktrace.h
index bf23e19..3180d30 100644
--- a/runtime/onnxruntime/third_party/glog/src/stacktrace.h
+++ b/runtime/onnxruntime/third_party/glog/src/stacktrace.h
@@ -34,7 +34,7 @@
 #define BASE_STACKTRACE_H_
 
 #include "config.h"
-#include <glog/logging.h>
+#include "glog/logging.h"
 
 _START_GOOGLE_NAMESPACE_
 
diff --git a/runtime/onnxruntime/third_party/glog/src/stacktrace_libunwind-inl.h b/runtime/onnxruntime/third_party/glog/src/stacktrace_libunwind-inl.h
index 0b20d23..e59c492 100644
--- a/runtime/onnxruntime/third_party/glog/src/stacktrace_libunwind-inl.h
+++ b/runtime/onnxruntime/third_party/glog/src/stacktrace_libunwind-inl.h
@@ -37,7 +37,7 @@
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
 }
-#include <glog/raw_logging.h>
+#include "glog/raw_logging.h"
 #include "stacktrace.h"
 
 _START_GOOGLE_NAMESPACE_
diff --git a/runtime/onnxruntime/third_party/glog/src/stacktrace_powerpc-inl.h b/runtime/onnxruntime/third_party/glog/src/stacktrace_powerpc-inl.h
index 30217db..af95adb 100644
--- a/runtime/onnxruntime/third_party/glog/src/stacktrace_powerpc-inl.h
+++ b/runtime/onnxruntime/third_party/glog/src/stacktrace_powerpc-inl.h
@@ -121,7 +121,7 @@
       // This check is in case the compiler doesn't define _CALL_SYSV.
       result[n++] = *(sp+1);
 #else
-#error Need to specify the PPC ABI for your archiecture.
+#error Need to specify the PPC ABI for your architecture.
 #endif
     }
     // Use strict unwinding rules.
diff --git a/runtime/onnxruntime/third_party/glog/src/stacktrace_unittest.cc b/runtime/onnxruntime/third_party/glog/src/stacktrace_unittest.cc
index 6d3c21a..b92961c 100644
--- a/runtime/onnxruntime/third_party/glog/src/stacktrace_unittest.cc
+++ b/runtime/onnxruntime/third_party/glog/src/stacktrace_unittest.cc
@@ -27,14 +27,15 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "utilities.h"
+#include "stacktrace.h"
 
 #include <cstdio>
 #include <cstdlib>
-#include "config.h"
+
 #include "base/commandlineflags.h"
-#include <glog/logging.h>
-#include "stacktrace.h"
+#include "config.h"
+#include "glog/logging.h"
+#include "utilities.h"
 
 #ifdef HAVE_EXECINFO_BACKTRACE_SYMBOLS
 # include <execinfo.h>
diff --git a/runtime/onnxruntime/third_party/glog/src/symbolize.cc b/runtime/onnxruntime/third_party/glog/src/symbolize.cc
index f95fccc..8e84361 100644
--- a/runtime/onnxruntime/third_party/glog/src/symbolize.cc
+++ b/runtime/onnxruntime/third_party/glog/src/symbolize.cc
@@ -119,7 +119,6 @@
 #include <elf.h>
 #endif
 #include <fcntl.h>
-#include <glog/raw_logging.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -133,6 +132,7 @@
 #include <cstring>
 
 #include "config.h"
+#include "glog/raw_logging.h"
 #include "symbolize.h"
 
 // Re-runs fn until it doesn't cause EINTR.
@@ -535,10 +535,8 @@
   // Iterate over maps and look for the map containing the pc.  Then
   // look into the symbol tables inside.
   char buf[1024];  // Big enough for line of sane /proc/self/maps
-  unsigned num_maps = 0;
   LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf), 0);
   while (true) {
-    num_maps++;
     const char *cursor;
     const char *eol;
     if (!reader.ReadLine(&cursor, &eol)) {  // EOF or malformed line.
diff --git a/runtime/onnxruntime/third_party/glog/src/symbolize.h b/runtime/onnxruntime/third_party/glog/src/symbolize.h
index 86c22e3..89a6a4f 100644
--- a/runtime/onnxruntime/third_party/glog/src/symbolize.h
+++ b/runtime/onnxruntime/third_party/glog/src/symbolize.h
@@ -54,9 +54,9 @@
 #ifndef BASE_SYMBOLIZE_H_
 #define BASE_SYMBOLIZE_H_
 
-#include "utilities.h"
 #include "config.h"
-#include <glog/logging.h>
+#include "glog/logging.h"
+#include "utilities.h"
 
 #ifdef HAVE_SYMBOLIZE
 
diff --git a/runtime/onnxruntime/third_party/glog/src/utilities.cc b/runtime/onnxruntime/third_party/glog/src/utilities.cc
index 8b0a1ea..f825470 100644
--- a/runtime/onnxruntime/third_party/glog/src/utilities.cc
+++ b/runtime/onnxruntime/third_party/glog/src/utilities.cc
@@ -292,6 +292,8 @@
   return getpid();  // Linux:  getpid returns thread ID when gettid is absent
 #elif defined GLOG_OS_WINDOWS && !defined GLOG_OS_CYGWIN
   return static_cast<pid_t>(GetCurrentThreadId());
+#elif defined GLOG_OS_OPENBSD
+  return getthrid();
 #elif defined(HAVE_PTHREAD)
   // If none of the techniques above worked, we use pthread_self().
   return (pid_t)(uintptr_t)pthread_self();
diff --git a/runtime/onnxruntime/third_party/glog/src/utilities.h b/runtime/onnxruntime/third_party/glog/src/utilities.h
index 45e555b..ae34d8d 100644
--- a/runtime/onnxruntime/third_party/glog/src/utilities.h
+++ b/runtime/onnxruntime/third_party/glog/src/utilities.h
@@ -29,7 +29,7 @@
 //
 // Author: Shinichiro Hamaji
 //
-// Define utilties for glog internal usage.
+// Define utilities for glog internal usage.
 
 #ifndef UTILITIES_H__
 #define UTILITIES_H__
@@ -52,11 +52,10 @@
 #define PRIXS __PRIS_PREFIX "X"
 #define PRIoS __PRIS_PREFIX "o"
 
-#include "base/mutex.h"  // This must go first so we get _XOPEN_SOURCE
-
 #include <string>
 
-#include <glog/logging.h>
+#include "base/mutex.h"  // This must go first so we get _XOPEN_SOURCE
+#include "glog/logging.h"
 
 #if defined(GLOG_OS_WINDOWS)
 # include "port.h"
@@ -174,7 +173,7 @@
                        :"=a"(ret)
                         // GCC may produces %sil or %dil for
                         // constraint "r", but some of apple's gas
-                        // dosn't know the 8 bit registers.
+                        // doesn't know the 8 bit registers.
                         // We use "q" to avoid these registers.
                        :"q"(newval), "q"(ptr), "a"(oldval)
                        :"memory", "cc");
diff --git a/runtime/onnxruntime/third_party/glog/src/vlog_is_on.cc b/runtime/onnxruntime/third_party/glog/src/vlog_is_on.cc
index ac60d02..f78fd07 100644
--- a/runtime/onnxruntime/third_party/glog/src/vlog_is_on.cc
+++ b/runtime/onnxruntime/third_party/glog/src/vlog_is_on.cc
@@ -32,17 +32,17 @@
 // Broken out from logging.cc by Soren Lassen
 // logging_unittest.cc covers the functionality herein
 
-#include "utilities.h"
-
-#include <cstring>
-#include <cstdlib>
 #include <cerrno>
 #include <cstdio>
+#include <cstdlib>
+#include <cstring>
 #include <string>
+
 #include "base/commandlineflags.h"
-#include <glog/logging.h>
-#include <glog/raw_logging.h>
 #include "base/googleinit.h"
+#include "glog/logging.h"
+#include "glog/raw_logging.h"
+#include "utilities.h"
 
 // glog doesn't have annotation
 #define ANNOTATE_BENIGN_RACE(address, description)
diff --git a/runtime/onnxruntime/third_party/glog/src/windows/dirent.h b/runtime/onnxruntime/third_party/glog/src/windows/dirent.h
new file mode 100644
index 0000000..097ad20
--- /dev/null
+++ b/runtime/onnxruntime/third_party/glog/src/windows/dirent.h
@@ -0,0 +1,1145 @@
+/*
+ * Dirent interface for Microsoft Visual Studio
+ *
+ * Copyright (C) 1998-2019 Toni Ronkko
+ * This file is part of dirent.  Dirent may be freely distributed
+ * under the MIT license.  For all details and documentation, see
+ * https://github.com/tronkko/dirent
+ */
+#ifndef DIRENT_H
+#define DIRENT_H
+
+/* Hide warnings about unreferenced local functions */
+#if defined(__clang__)
+#   pragma clang diagnostic ignored "-Wunused-function"
+#elif defined(_MSC_VER)
+#   pragma warning(disable:4505)
+#elif defined(__GNUC__)
+#   pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+/*
+ * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
+ * Windows Sockets 2.0.
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+#   define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include <cerrno>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cwchar>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* Indicates that d_type field is available in dirent structure */
+#define _DIRENT_HAVE_D_TYPE
+
+/* Indicates that d_namlen field is available in dirent structure */
+#define _DIRENT_HAVE_D_NAMLEN
+
+/* Entries missing from MSVC 6.0 */
+#if !defined(FILE_ATTRIBUTE_DEVICE)
+#   define FILE_ATTRIBUTE_DEVICE 0x40
+#endif
+
+/* File type and permission flags for stat(), general mask */
+#if !defined(S_IFMT)
+#   define S_IFMT _S_IFMT
+#endif
+
+/* Directory bit */
+#if !defined(S_IFDIR)
+#   define S_IFDIR _S_IFDIR
+#endif
+
+/* Character device bit */
+#if !defined(S_IFCHR)
+#   define S_IFCHR _S_IFCHR
+#endif
+
+/* Pipe bit */
+#if !defined(S_IFFIFO)
+#   define S_IFFIFO _S_IFFIFO
+#endif
+
+/* Regular file bit */
+#if !defined(S_IFREG)
+#   define S_IFREG _S_IFREG
+#endif
+
+/* Read permission */
+#if !defined(S_IREAD)
+#   define S_IREAD _S_IREAD
+#endif
+
+/* Write permission */
+#if !defined(S_IWRITE)
+#   define S_IWRITE _S_IWRITE
+#endif
+
+/* Execute permission */
+#if !defined(S_IEXEC)
+#   define S_IEXEC _S_IEXEC
+#endif
+
+/* Pipe */
+#if !defined(S_IFIFO)
+#   define S_IFIFO _S_IFIFO
+#endif
+
+/* Block device */
+#if !defined(S_IFBLK)
+#   define S_IFBLK 0
+#endif
+
+/* Link */
+#if !defined(S_IFLNK)
+#   define S_IFLNK 0
+#endif
+
+/* Socket */
+#if !defined(S_IFSOCK)
+#   define S_IFSOCK 0
+#endif
+
+/* Read user permission */
+#if !defined(S_IRUSR)
+#   define S_IRUSR S_IREAD
+#endif
+
+/* Write user permission */
+#if !defined(S_IWUSR)
+#   define S_IWUSR S_IWRITE
+#endif
+
+/* Execute user permission */
+#if !defined(S_IXUSR)
+#   define S_IXUSR 0
+#endif
+
+/* Read group permission */
+#if !defined(S_IRGRP)
+#   define S_IRGRP 0
+#endif
+
+/* Write group permission */
+#if !defined(S_IWGRP)
+#   define S_IWGRP 0
+#endif
+
+/* Execute group permission */
+#if !defined(S_IXGRP)
+#   define S_IXGRP 0
+#endif
+
+/* Read others permission */
+#if !defined(S_IROTH)
+#   define S_IROTH 0
+#endif
+
+/* Write others permission */
+#if !defined(S_IWOTH)
+#   define S_IWOTH 0
+#endif
+
+/* Execute others permission */
+#if !defined(S_IXOTH)
+#   define S_IXOTH 0
+#endif
+
+/* Maximum length of file name */
+#if !defined(PATH_MAX)
+#   define PATH_MAX MAX_PATH
+#endif
+#if !defined(FILENAME_MAX)
+#   define FILENAME_MAX MAX_PATH
+#endif
+#if !defined(NAME_MAX)
+#   define NAME_MAX FILENAME_MAX
+#endif
+
+/* File type flags for d_type */
+#define DT_UNKNOWN 0
+#define DT_REG S_IFREG
+#define DT_DIR S_IFDIR
+#define DT_FIFO S_IFIFO
+#define DT_SOCK S_IFSOCK
+#define DT_CHR S_IFCHR
+#define DT_BLK S_IFBLK
+#define DT_LNK S_IFLNK
+
+/* Macros for converting between st_mode and d_type */
+#define IFTODT(mode) ((mode) & S_IFMT)
+#define DTTOIF(type) (type)
+
+/*
+ * File type macros.  Note that block devices, sockets and links cannot be
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
+ * only defined for compatibility.  These macros should always return false
+ * on Windows.
+ */
+#if !defined(S_ISFIFO)
+#   define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISDIR)
+#   define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG)
+#   define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISLNK)
+#   define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK)
+#   define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISCHR)
+#   define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISBLK)
+#   define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
+#endif
+
+/* Return the exact length of the file name without zero terminator */
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
+
+/* Return the maximum size of a file name */
+#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Wide-character version */
+struct _wdirent {
+    /* Always zero */
+    long d_ino;
+
+    /* File position within stream */
+    long d_off;
+
+    /* Structure size */
+    unsigned short d_reclen;
+
+    /* Length of name without \0 */
+    size_t d_namlen;
+
+    /* File type */
+    int d_type;
+
+    /* File name */
+    wchar_t d_name[PATH_MAX+1];
+};
+
+struct _WDIR {
+    /* Current directory entry */
+    _wdirent ent;
+
+    /* Private file data */
+    WIN32_FIND_DATAW data;
+
+    /* True if data is valid */
+    int cached;
+
+    /* Win32 search handle */
+    HANDLE handle;
+
+    /* Initial directory name */
+    wchar_t *patt;
+};
+
+/* Multi-byte character version */
+struct dirent {
+    /* Always zero */
+    long d_ino;
+
+    /* File position within stream */
+    long d_off;
+
+    /* Structure size */
+    unsigned short d_reclen;
+
+    /* Length of name without \0 */
+    size_t d_namlen;
+
+    /* File type */
+    int d_type;
+
+    /* File name */
+    char d_name[PATH_MAX+1];
+};
+
+struct DIR {
+    struct dirent ent;
+    struct _WDIR *wdirp;
+};
+
+/* Dirent functions */
+static DIR *opendir (const char *dirname);
+static _WDIR *_wopendir (const wchar_t *dirname);
+
+static struct dirent *readdir (DIR *dirp);
+static struct _wdirent *_wreaddir (_WDIR *dirp);
+
+static int readdir_r(
+    DIR *dirp, struct dirent *entry, struct dirent **result);
+static int _wreaddir_r(
+    _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
+
+static int closedir (DIR *dirp);
+static int _wclosedir (_WDIR *dirp);
+
+static void rewinddir (DIR* dirp);
+static void _wrewinddir (_WDIR* dirp);
+
+static int scandir (const char *dirname, struct dirent ***namelist,
+    int (*filter)(const struct dirent*),
+    int (*compare)(const struct dirent**, const struct dirent**));
+
+static int alphasort (const struct dirent **a, const struct dirent **b);
+
+static int versionsort (const struct dirent **a, const struct dirent **b);
+
+
+/* For compatibility with Symbian */
+#define wdirent _wdirent
+#define WDIR _WDIR
+#define wopendir _wopendir
+#define wreaddir _wreaddir
+#define wclosedir _wclosedir
+#define wrewinddir _wrewinddir
+
+
+/* Internal utility functions */
+static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
+static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
+
+static int dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count);
+
+static int dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes,
+    const wchar_t *wcstr,
+    size_t count);
+
+static void dirent_set_errno (int error);
+
+
+/*
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+static _WDIR*
+_wopendir(
+    const wchar_t *dirname)
+{
+    _WDIR *dirp;
+    DWORD n;
+    wchar_t *p;
+
+    /* Must have directory name */
+    if (dirname == nullptr || dirname[0] == '\0') {
+      dirent_set_errno(ENOENT);
+      return nullptr;
+    }
+
+    /* Allocate new _WDIR structure */
+    dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
+    if (!dirp) {
+      return nullptr;
+    }
+
+    /* Reset _WDIR structure */
+    dirp->handle = INVALID_HANDLE_VALUE;
+    dirp->patt = nullptr;
+    dirp->cached = 0;
+
+    /*
+     * Compute the length of full path plus zero terminator
+     *
+     * Note that on WinRT there's no way to convert relative paths
+     * into absolute paths, so just assume it is an absolute path.
+     */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+    /* Desktop */
+    n = GetFullPathNameW(dirname, 0, nullptr, nullptr);
+#else
+    /* WinRT */
+    n = wcslen (dirname);
+#endif
+
+    /* Allocate room for absolute directory name and search pattern */
+    dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
+    if (dirp->patt == nullptr) {
+      goto exit_closedir;
+    }
+
+    /*
+     * Convert relative directory name to an absolute one.  This
+     * allows rewinddir() to function correctly even when current
+     * working directory is changed between opendir() and rewinddir().
+     *
+     * Note that on WinRT there's no way to convert relative paths
+     * into absolute paths, so just assume it is an absolute path.
+     */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+    /* Desktop */
+    n = GetFullPathNameW(dirname, n, dirp->patt, nullptr);
+    if (n <= 0) {
+        goto exit_closedir;
+    }
+#else
+    /* WinRT */
+    wcsncpy_s (dirp->patt, n+1, dirname, n);
+#endif
+
+    /* Append search pattern \* to the directory name */
+    p = dirp->patt + n;
+    switch (p[-1]) {
+    case '\\':
+    case '/':
+    case ':':
+        /* Directory ends in path separator, e.g. c:\temp\ */
+        /*NOP*/;
+        break;
+
+    default:
+        /* Directory name doesn't end in path separator */
+        *p++ = '\\';
+    }
+    *p++ = '*';
+    *p = '\0';
+
+    /* Open directory stream and retrieve the first entry */
+    if (!dirent_first (dirp)) {
+        goto exit_closedir;
+    }
+
+    /* Success */
+    return dirp;
+
+    /* Failure */
+exit_closedir:
+    _wclosedir (dirp);
+    return nullptr;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * Returns pointer to static directory entry which may be overwritten by
+ * subsequent calls to _wreaddir().
+ */
+static struct _wdirent*
+_wreaddir(
+    _WDIR *dirp)
+{
+    struct _wdirent *entry;
+
+    /*
+     * Read directory entry to buffer.  We can safely ignore the return value
+     * as entry will be set to nullptr in case of error.
+     */
+    (void) _wreaddir_r (dirp, &dirp->ent, &entry);
+
+    /* Return pointer to statically allocated directory entry */
+    return entry;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * Returns zero on success.  If end of directory stream is reached, then sets
+ * result to nullptr and returns zero.
+ */
+static int
+_wreaddir_r(
+    _WDIR *dirp,
+    struct _wdirent *entry,
+    struct _wdirent **result)
+{
+    WIN32_FIND_DATAW *datap;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp);
+    if (datap) {
+        size_t n;
+        DWORD attr;
+
+        /*
+         * Copy file name as wide-character string.  If the file name is too
+         * long to fit in to the destination buffer, then truncate file name
+         * to PATH_MAX characters and zero-terminate the buffer.
+         */
+        n = 0;
+        while (n < PATH_MAX  &&  datap->cFileName[n] != 0) {
+            entry->d_name[n] = datap->cFileName[n];
+            n++;
+        }
+        entry->d_name[n] = 0;
+
+        /* Length of file name excluding zero terminator */
+        entry->d_namlen = n;
+
+        /* File type */
+        attr = datap->dwFileAttributes;
+        if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+            entry->d_type = DT_CHR;
+        } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+            entry->d_type = DT_DIR;
+        } else {
+            entry->d_type = DT_REG;
+        }
+
+        /* Reset dummy fields */
+        entry->d_ino = 0;
+        entry->d_off = 0;
+        entry->d_reclen = sizeof (struct _wdirent);
+
+        /* Set result address */
+        *result = entry;
+
+    } else {
+        /* Return nullptr to indicate end of directory */
+        *result = nullptr;
+    }
+
+    return /*OK*/0;
+}
+
+/*
+ * Close directory stream opened by opendir() function.  This invalidates the
+ * DIR structure as well as any directory entry read previously by
+ * _wreaddir().
+ */
+static int
+_wclosedir(
+    _WDIR *dirp)
+{
+    int ok;
+    if (dirp) {
+
+        /* Release search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+        }
+
+        /* Release search pattern */
+        free (dirp->patt);
+
+        /* Release directory structure */
+        free (dirp);
+        ok = /*success*/0;
+
+    } else {
+
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+
+    }
+    return ok;
+}
+
+/*
+ * Rewind directory stream such that _wreaddir() returns the very first
+ * file name again.
+ */
+static void
+_wrewinddir(
+    _WDIR* dirp)
+{
+    if (dirp) {
+        /* Release existing search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+        }
+
+        /* Open new search handle */
+        dirent_first (dirp);
+    }
+}
+
+/* Get first directory entry (internal) */
+static WIN32_FIND_DATAW*
+dirent_first(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *datap;
+    DWORD error;
+
+    /* Open directory and retrieve the first entry */
+    dirp->handle = FindFirstFileExW(dirp->patt, FindExInfoStandard, &dirp->data,
+                                    FindExSearchNameMatch, nullptr, 0);
+    if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* a directory entry is now waiting in memory */
+        datap = &dirp->data;
+        dirp->cached = 1;
+
+    } else {
+
+        /* Failed to open directory: no directory entry in memory */
+        dirp->cached = 0;
+        datap = nullptr;
+
+        /* Set error code */
+        error = GetLastError ();
+        switch (error) {
+        case ERROR_ACCESS_DENIED:
+            /* No read access to directory */
+            dirent_set_errno (EACCES);
+            break;
+
+        case ERROR_DIRECTORY:
+            /* Directory name is invalid */
+            dirent_set_errno (ENOTDIR);
+            break;
+
+        case ERROR_PATH_NOT_FOUND:
+        default:
+            /* Cannot find the file */
+            dirent_set_errno (ENOENT);
+        }
+
+    }
+    return datap;
+}
+
+/*
+ * Get next directory entry (internal).
+ *
+ * Returns
+ */
+static WIN32_FIND_DATAW*
+dirent_next(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *p;
+
+    /* Get next directory entry */
+    if (dirp->cached != 0) {
+
+        /* A valid directory entry already in memory */
+        p = &dirp->data;
+        dirp->cached = 0;
+
+    } else if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* Get the next directory entry from stream */
+        if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
+            /* Got a file */
+            p = &dirp->data;
+        } else {
+            /* The very last entry has been processed or an error occurred */
+            FindClose (dirp->handle);
+            dirp->handle = INVALID_HANDLE_VALUE;
+            p = nullptr;
+        }
+
+    } else {
+
+        /* End of directory stream reached */
+        p = nullptr;
+    }
+
+    return p;
+}
+
+/*
+ * Open directory stream using plain old C-string.
+ */
+static DIR*
+opendir(
+    const char *dirname)
+{
+    struct DIR *dirp;
+
+    /* Must have directory name */
+    if (dirname == nullptr || dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return nullptr;
+    }
+
+    /* Allocate memory for DIR structure */
+    dirp = (DIR*) malloc (sizeof (struct DIR));
+    if (!dirp) {
+        return nullptr;
+    }
+    {
+        int error;
+        wchar_t wname[PATH_MAX + 1];
+        size_t n;
+
+        /* Convert directory name to wide-character string */
+        error = dirent_mbstowcs_s(
+            &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
+        if (error) {
+            /*
+             * Cannot convert file name to wide-character string.  This
+             * occurs if the string contains invalid multi-byte sequences or
+             * the output buffer is too small to contain the resulting
+             * string.
+             */
+            goto exit_free;
+        }
+
+
+        /* Open directory stream using wide-character name */
+        dirp->wdirp = _wopendir (wname);
+        if (!dirp->wdirp) {
+            goto exit_free;
+        }
+
+    }
+
+    /* Success */
+    return dirp;
+
+    /* Failure */
+exit_free:
+    free (dirp);
+    return nullptr;
+}
+
+/*
+ * Read next directory entry.
+ */
+static struct dirent*
+readdir(
+    DIR *dirp)
+{
+    struct dirent *entry;
+
+    /*
+     * Read directory entry to buffer.  We can safely ignore the return value
+     * as entry will be set to nullptr in case of error.
+     */
+    (void) readdir_r (dirp, &dirp->ent, &entry);
+
+    /* Return pointer to statically allocated directory entry */
+    return entry;
+}
+
+/*
+ * Read next directory entry into called-allocated buffer.
+ *
+ * Returns zero on success.  If the end of directory stream is reached, then
+ * sets result to nullptr and returns zero.
+ */
+static int
+readdir_r(
+    DIR *dirp,
+    struct dirent *entry,
+    struct dirent **result)
+{
+    WIN32_FIND_DATAW *datap;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp->wdirp);
+    if (datap) {
+        size_t n;
+        int error;
+
+        /* Attempt to convert file name to multi-byte string */
+        error = dirent_wcstombs_s(
+            &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
+
+        /*
+         * If the file name cannot be represented by a multi-byte string,
+         * then attempt to use old 8+3 file name.  This allows traditional
+         * Unix-code to access some file names despite of unicode
+         * characters, although file names may seem unfamiliar to the user.
+         *
+         * Be ware that the code below cannot come up with a short file
+         * name unless the file system provides one.  At least
+         * VirtualBox shared folders fail to do this.
+         */
+        if (error  &&  datap->cAlternateFileName[0] != '\0') {
+            error = dirent_wcstombs_s(
+                &n, entry->d_name, PATH_MAX + 1,
+                datap->cAlternateFileName, PATH_MAX + 1);
+        }
+
+        if (!error) {
+            DWORD attr;
+
+            /* Length of file name excluding zero terminator */
+            entry->d_namlen = n - 1;
+
+            /* File attributes */
+            attr = datap->dwFileAttributes;
+            if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+                entry->d_type = DT_CHR;
+            } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+                entry->d_type = DT_DIR;
+            } else {
+                entry->d_type = DT_REG;
+            }
+
+            /* Reset dummy fields */
+            entry->d_ino = 0;
+            entry->d_off = 0;
+            entry->d_reclen = sizeof (struct dirent);
+
+        } else {
+            /*
+             * Cannot convert file name to multi-byte string so construct
+             * an erroneous directory entry and return that.  Note that
+             * we cannot return nullptr as that would stop the processing
+             * of directory entries completely.
+             */
+            entry->d_name[0] = '?';
+            entry->d_name[1] = '\0';
+            entry->d_namlen = 1;
+            entry->d_type = DT_UNKNOWN;
+            entry->d_ino = 0;
+            entry->d_off = -1;
+            entry->d_reclen = 0;
+
+        }
+
+        /* Return pointer to directory entry */
+        *result = entry;
+
+    } else {
+
+        /* No more directory entries */
+        *result = nullptr;
+    }
+
+    return /*OK*/0;
+}
+
+/*
+ * Close directory stream.
+ */
+static int
+closedir(
+    DIR *dirp)
+{
+    int ok;
+    if (dirp) {
+
+        /* Close wide-character directory stream */
+        ok = _wclosedir (dirp->wdirp);
+        dirp->wdirp = nullptr;
+
+        /* Release multi-byte character version */
+        free (dirp);
+
+    } else {
+
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+
+    }
+    return ok;
+}
+
+/*
+ * Rewind directory stream to beginning.
+ */
+static void
+rewinddir(
+    DIR* dirp)
+{
+    /* Rewind wide-character string directory stream */
+    _wrewinddir (dirp->wdirp);
+}
+
+/*
+ * Scan directory for entries.
+ */
+static int
+scandir(
+    const char *dirname,
+    struct dirent ***namelist,
+    int (*filter)(const struct dirent*),
+    int (*compare)(const struct dirent**, const struct dirent**))
+{
+    struct dirent **files = nullptr;
+    size_t size = 0;
+    size_t allocated = 0;
+    const size_t init_size = 1;
+    DIR *dir = nullptr;
+    struct dirent *entry;
+    struct dirent *tmp = nullptr;
+    size_t i;
+    int result = 0;
+
+    /* Open directory stream */
+    dir = opendir (dirname);
+    if (dir) {
+
+        /* Read directory entries to memory */
+        while (1) {
+
+            /* Enlarge pointer table to make room for another pointer */
+            if (size >= allocated) {
+                void *p;
+                size_t num_entries;
+
+                /* Compute number of entries in the enlarged pointer table */
+                if (size < init_size) {
+                    /* Allocate initial pointer table */
+                    num_entries = init_size;
+                } else {
+                    /* Double the size */
+                    num_entries = size * 2;
+                }
+
+                /* Allocate first pointer table or enlarge existing table */
+                p = realloc (files, sizeof (void*) * num_entries);
+                if (p != nullptr) {
+                    /* Got the memory */
+                    files = (dirent**) p;
+                    allocated = num_entries;
+                } else {
+                    /* Out of memory */
+                    result = -1;
+                    break;
+                }
+            }
+
+            /* Allocate room for temporary directory entry */
+            if (tmp == nullptr) {
+                tmp = (struct dirent*) malloc (sizeof (struct dirent));
+                if (tmp == nullptr) {
+                    /* Cannot allocate temporary directory entry */
+                    result = -1;
+                    break;
+                }
+            }
+
+            /* Read directory entry to temporary area */
+            if (readdir_r (dir, tmp, &entry) == /*OK*/0) {
+
+                /* Did we get an entry? */
+                if (entry != nullptr) {
+                    int pass;
+
+                    /* Determine whether to include the entry in result */
+                    if (filter) {
+                        /* Let the filter function decide */
+                        pass = filter (tmp);
+                    } else {
+                        /* No filter function, include everything */
+                        pass = 1;
+                    }
+
+                    if (pass) {
+                        /* Store the temporary entry to pointer table */
+                        files[size++] = tmp;
+                        tmp = nullptr;
+
+                        /* Keep up with the number of files */
+                        result++;
+                    }
+
+                } else {
+                    /*
+                     * End of directory stream reached => sort entries and
+                     * exit.
+                     */
+                    qsort (files, size, sizeof (void*),
+                        (int (*) (const void*, const void*)) compare);
+                    break;
+                }
+
+            } else {
+                /* Error reading directory entry */
+                result = /*Error*/ -1;
+                break;
+            }
+
+        }
+
+    } else {
+        /* Cannot open directory */
+        result = /*Error*/ -1;
+    }
+
+    /* Release temporary directory entry */
+    free (tmp);
+
+    /* Release allocated memory on error */
+    if (result < 0) {
+        for (i = 0; i < size; i++) {
+            free (files[i]);
+        }
+        free (files);
+        files = nullptr;
+    }
+
+    /* Close directory stream */
+    if (dir) {
+        closedir (dir);
+    }
+
+    /* Pass pointer table to caller */
+    if (namelist) {
+        *namelist = files;
+    }
+    return result;
+}
+
+/* Alphabetical sorting */
+static int
+alphasort(
+    const struct dirent **a, const struct dirent **b)
+{
+    return strcoll ((*a)->d_name, (*b)->d_name);
+}
+
+/* Sort versions */
+static int
+versionsort(
+    const struct dirent **a, const struct dirent **b)
+{
+    /* FIXME: implement strverscmp and use that */
+    return alphasort (a, b);
+}
+
+/* Convert multi-byte string to wide character string */
+static int
+dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to wide-character string (or count characters) */
+    n = mbstowcs (wcstr, mbstr, sizeInWords);
+    if (!wcstr  ||  n < count) {
+
+        /* Zero-terminate output buffer */
+        if (wcstr  &&  sizeInWords) {
+            if (n >= sizeInWords) {
+                n = sizeInWords - 1;
+            }
+            wcstr[n] = 0;
+        }
+
+        /* Length of resulting multi-byte string WITH zero terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Could not convert string */
+        error = 1;
+
+    }
+
+#endif
+    return error;
+}
+
+/* Convert wide-character string to multi-byte string */
+static int
+dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes, /* max size of mbstr */
+    const wchar_t *wcstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to multi-byte string (or count the number of bytes needed) */
+    n = wcstombs (mbstr, wcstr, sizeInBytes);
+    if (!mbstr  ||  n < count) {
+
+        /* Zero-terminate output buffer */
+        if (mbstr  &&  sizeInBytes) {
+            if (n >= sizeInBytes) {
+                n = sizeInBytes - 1;
+            }
+            mbstr[n] = '\0';
+        }
+
+        /* Length of resulting multi-bytes string WITH zero-terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Cannot convert string */
+        error = 1;
+
+    }
+
+#endif
+    return error;
+}
+
+/* Set errno variable */
+static void
+dirent_set_errno(
+    int error)
+{
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 and later */
+    _set_errno (error);
+
+#else
+
+    /* Non-Microsoft compiler or older Microsoft compiler */
+    errno = error;
+
+#endif
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*DIRENT_H*/
diff --git a/runtime/onnxruntime/third_party/glog/src/windows/port.cc b/runtime/onnxruntime/third_party/glog/src/windows/port.cc
new file mode 100644
index 0000000..f80a54a
--- /dev/null
+++ b/runtime/onnxruntime/third_party/glog/src/windows/port.cc
@@ -0,0 +1,75 @@
+/* Copyright (c) 2008, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ * Copied from google-perftools and modified by Shinichiro Hamaji
+ */
+
+#ifndef _WIN32
+# error You should only be including windows/port.cc in a windows environment!
+#endif
+
+#include "port.h"
+
+#include <cstdarg>  // for va_list, va_start, va_end
+#include <ctime>
+
+#include "config.h"
+
+// These call the windows _vsnprintf, but always NUL-terminate.
+int safe_vsnprintf(char* str, std::size_t size, const char* format,
+                   va_list ap) {
+  if (size == 0)        // not even room for a \0?
+    return -1;          // not what C99 says to do, but what windows does
+  str[size-1] = '\0';
+  return _vsnprintf(str, size-1, format, ap);
+}
+
+#ifndef HAVE_LOCALTIME_R
+struct tm* localtime_r(const std::time_t* timep, std::tm* result) {
+  localtime_s(result, timep);
+  return result;
+}
+#endif // not HAVE_LOCALTIME_R
+#ifndef HAVE_GMTIME_R
+struct tm* gmtime_r(const std::time_t* timep, std::tm* result) {
+  gmtime_s(result, timep);
+  return result;
+}
+#endif // not HAVE_GMTIME_R
+#ifndef HAVE_SNPRINTF
+int snprintf(char *str, size_t size, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  const int r = vsnprintf(str, size, format, ap);
+  va_end(ap);
+  return r;
+}
+#endif
diff --git a/runtime/onnxruntime/third_party/glog/src/windows/port.h b/runtime/onnxruntime/third_party/glog/src/windows/port.h
new file mode 100644
index 0000000..eecc46f
--- /dev/null
+++ b/runtime/onnxruntime/third_party/glog/src/windows/port.h
@@ -0,0 +1,181 @@
+/* Copyright (c) 2023, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * Author: Craig Silverstein
+ * Copied from google-perftools and modified by Shinichiro Hamaji
+ *
+ * These are some portability typedefs and defines to make it a bit
+ * easier to compile this code under VC++.
+ *
+ * Several of these are taken from glib:
+ *    http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
+ */
+
+#ifndef CTEMPLATE_WINDOWS_PORT_H_
+#define CTEMPLATE_WINDOWS_PORT_H_
+
+#include "config.h"
+
+#ifdef _WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN  /* We always want minimal includes */
+#endif
+
+#include <windows.h>
+#include <winsock.h>         /* for gethostname */
+#include <io.h>              /* because we so often use open/close/etc */
+#include <direct.h>          /* for _getcwd() */
+#include <process.h>         /* for _getpid() */
+#include <cstdarg>          /* template_dictionary.cc uses va_copy */
+#include <cstdio>           /* read in vsnprintf decl. before redifining it */
+#include <cstring>          /* for _strnicmp(), strerror_s() */
+#include <ctime>            /* for localtime_s() */
+/* Note: the C++ #includes are all together at the bottom.  This file is
+ * used by both C and C++ code, so we put all the C++ together.
+ */
+
+#include "glog/logging.h"
+
+#ifdef _MSC_VER
+
+/* 4244: otherwise we get problems when substracting two size_t's to an int
+ * 4251: it's complaining about a private struct I've chosen not to dllexport
+ * 4355: we use this in a constructor, but we do it safely
+ * 4715: for some reason VC++ stopped realizing you can't return after abort()
+ * 4800: we know we're casting ints/char*'s to bools, and we're ok with that
+ * 4996: Yes, we're ok using "unsafe" functions like fopen() and strerror()
+ * 4312: Converting uint32_t to a pointer when testing %p
+ * 4267: also subtracting two size_t to int
+ * 4722: Destructor never returns due to abort()
+ */
+#pragma warning(disable:4244 4251 4355 4715 4800 4996 4267 4312 4722)
+
+/* file I/O */
+#define PATH_MAX 1024
+#define access  _access
+#define getcwd  _getcwd
+#define open    _open
+#define read    _read
+#define write(fd, p, n) _write(fd, p, n)
+#define lseek   _lseek
+#define close   _close
+#define popen   _popen
+#define pclose  _pclose
+#define R_OK    04           /* read-only (for access()) */
+#define S_ISDIR(m)  (((m) & _S_IFMT) == _S_IFDIR)
+
+#define O_WRONLY _O_WRONLY
+#define O_CREAT _O_CREAT
+#define O_EXCL _O_EXCL
+
+#ifndef __MINGW32__
+enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
+#endif
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+
+/* Not quite as lightweight as a hard-link, but more than good enough for us. */
+#define link(oldpath, newpath)  CopyFileA(oldpath, newpath, false)
+
+#define strcasecmp   _stricmp
+#define strncasecmp  _strnicmp
+
+/* In windows-land, hash<> is called hash_compare<> (from xhash.h) */
+/* VC11 provides std::hash */
+#if defined(_MSC_VER) && (_MSC_VER < 1700)
+#define hash  hash_compare
+#endif
+
+/* Sleep is in ms, on windows */
+#define sleep(secs)  Sleep((secs) * 1000)
+
+/* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
+ * because they don't always NUL-terminate. :-(  We also can't use the
+ * name vsnprintf, since windows defines that (but not snprintf (!)).
+ */
+#ifndef HAVE_SNPRINTF
+extern int GLOG_EXPORT snprintf(char* str, size_t size, const char* format,
+                                ...);
+#endif
+extern int GLOG_EXPORT safe_vsnprintf(char* str, size_t size,
+                                      const char* format, va_list ap);
+#define vsnprintf(str, size, format, ap)  safe_vsnprintf(str, size, format, ap)
+#ifndef va_copy
+#define va_copy(dst, src)  (dst) = (src)
+#endif
+
+/* Windows doesn't support specifying the number of buckets as a
+ * hash_map constructor arg, so we leave this blank.
+ */
+#define CTEMPLATE_SMALL_HASHTABLE
+
+#define DEFAULT_TEMPLATE_ROOTDIR  ".."
+
+// ----------------------------------- SYSTEM/PROCESS
+typedef int pid_t;
+#define getpid  _getpid
+
+#endif  // _MSC_VER
+
+// ----------------------------------- THREADS
+#if defined(HAVE_PTHREAD)
+# include <pthread.h>
+#else // no PTHREAD
+typedef DWORD pthread_t;
+typedef DWORD pthread_key_t;
+typedef LONG pthread_once_t;
+enum { PTHREAD_ONCE_INIT = 0 };   // important that this be 0! for SpinLock
+#define pthread_self  GetCurrentThreadId
+#define pthread_equal(pthread_t_1, pthread_t_2)  ((pthread_t_1)==(pthread_t_2))
+#endif // HAVE_PTHREAD
+
+#ifndef HAVE_LOCALTIME_R
+extern GLOG_EXPORT std::tm* localtime_r(const std::time_t* timep,
+                                        std::tm* result);
+#endif // not HAVE_LOCALTIME_R
+
+#ifndef HAVE_GMTIME_R
+extern GLOG_EXPORT std::tm* gmtime_r(const std::time_t* timep, std::tm* result);
+#endif // not HAVE_GMTIME_R
+
+inline char* strerror_r(int errnum, char* buf, std::size_t buflen) {
+  strerror_s(buf, buflen, errnum);
+  return buf;
+}
+
+#ifndef __cplusplus
+/* I don't see how to get inlining for C code in MSVC.  Ah well. */
+#define inline
+#endif
+
+#endif  /* _WIN32 */
+
+#endif  /* CTEMPLATE_WINDOWS_PORT_H_ */
diff --git a/runtime/onnxruntime/third_party/jieba/include/limonp/Logging.hpp b/runtime/onnxruntime/third_party/jieba/include/limonp/Logging.hpp
index 3fe3ada..88c6669 100644
--- a/runtime/onnxruntime/third_party/jieba/include/limonp/Logging.hpp
+++ b/runtime/onnxruntime/third_party/jieba/include/limonp/Logging.hpp
@@ -50,7 +50,7 @@
 
     #if defined(_WIN32) || defined(_WIN64)
     errno_t e = localtime_s(&tmNow, &timeNow);
-    assert(e = 0);
+    assert(e == 0);
     #else
     struct tm * tm_tmp = localtime_r(&timeNow, &tmNow);
     assert(tm_tmp != nullptr);
diff --git a/runtime/onnxruntime/third_party/kaldi/CMakeLists.txt b/runtime/onnxruntime/third_party/kaldi/CMakeLists.txt
index 1ff94d8..f253cb4 100644
--- a/runtime/onnxruntime/third_party/kaldi/CMakeLists.txt
+++ b/runtime/onnxruntime/third_party/kaldi/CMakeLists.txt
@@ -2,7 +2,7 @@
 
 project(kaldi)
 
-add_library(kaldi-util
+add_library(kaldi-util STATIC
   base/kaldi-error.cc
   base/kaldi-math.cc
   util/kaldi-io.cc
@@ -12,13 +12,23 @@
 )
 #target_link_libraries(kaldi-util PUBLIC utils)
 
-add_library(kaldi-decoder
+add_library(kaldi-decoder STATIC
   lat/determinize-lattice-pruned.cc
   lat/lattice-functions.cc
   decoder/lattice-faster-decoder.cc
   decoder/lattice-faster-online-decoder.cc
 )
+
+if (WIN32)
+target_link_libraries(kaldi-decoder PUBLIC kaldi-util)
+else()
 target_link_libraries(kaldi-decoder PUBLIC kaldi-util dl)
+endif (WIN32)
+
+
+if (WIN32)
+  target_compile_definitions (kaldi-decoder PUBLIC GLOG_NO_ABBREVIATED_SEVERITIES)
+endif (WIN32)
 
 include_directories(${CMAKE_SOURCE_DIR}/build/third_party/glog)
 include_directories(${CMAKE_SOURCE_DIR}/third_party/glog/src)
@@ -30,7 +40,13 @@
     lm/arpa-lm-compiler.cc
     lmbin/arpa2fst.cc
   )
-  target_link_libraries(arpa2fst PUBLIC kaldi-util fst dl)
+
+if (WIN32)
+target_link_libraries(arpa2fst PUBLIC kaldi-util fst)
+else()
+target_link_libraries(arpa2fst PUBLIC kaldi-util fst dl)
+endif (WIN32)
+
 
   # FST tools binary
   set(FST_BINS
@@ -46,6 +62,10 @@
       fstbin/${name}.cc
       fstext/kaldi-fst-io.cc
     )
+if (WIN32)
+    target_link_libraries(${name} PUBLIC kaldi-util fst)
+else()
     target_link_libraries(${name} PUBLIC kaldi-util fst dl)
+endif (WIN32)
   endforeach()
 endif()
diff --git a/runtime/onnxruntime/third_party/openfst/src/include/fst/log.h b/runtime/onnxruntime/third_party/openfst/src/include/fst/log.h
index bf041c5..9f87519 100644
--- a/runtime/onnxruntime/third_party/openfst/src/include/fst/log.h
+++ b/runtime/onnxruntime/third_party/openfst/src/include/fst/log.h
@@ -27,7 +27,9 @@
 
 using std::string;
 
+#ifndef _WIN32
 DECLARE_int32(v);
+#endif
 
 class LogMessage {
  public:
diff --git a/runtime/onnxruntime/third_party/openfst/src/lib/CMakeLists.txt b/runtime/onnxruntime/third_party/openfst/src/lib/CMakeLists.txt
index 9960ce9..fca75ae 100644
--- a/runtime/onnxruntime/third_party/openfst/src/lib/CMakeLists.txt
+++ b/runtime/onnxruntime/third_party/openfst/src/lib/CMakeLists.txt
@@ -1,7 +1,7 @@
 FILE(GLOB HEADER_FILES ../include/fst/*.h)
 
 
-add_library(fst
+add_library(fst STATIC
   compat.cc
   flags.cc
   fst-types.cc
diff --git a/runtime/onnxruntime/third_party/yaml-cpp/include/yaml-cpp/exceptions.h b/runtime/onnxruntime/third_party/yaml-cpp/include/yaml-cpp/exceptions.h
index 9c96859..72bff04 100644
--- a/runtime/onnxruntime/third_party/yaml-cpp/include/yaml-cpp/exceptions.h
+++ b/runtime/onnxruntime/third_party/yaml-cpp/include/yaml-cpp/exceptions.h
@@ -16,7 +16,7 @@
 // This is here for compatibility with older versions of Visual Studio
 // which don't support noexcept
 #ifdef _MSC_VER
-    #define YAML_CPP_NOEXCEPT _NOEXCEPT
+    #define YAML_CPP_NOEXCEPT noexcept
 #else
     #define YAML_CPP_NOEXCEPT noexcept
 #endif
diff --git a/runtime/onnxruntime/third_party/yaml-cpp/src/exceptions.cpp b/runtime/onnxruntime/third_party/yaml-cpp/src/exceptions.cpp
index 9b6d891..79ea77d 100644
--- a/runtime/onnxruntime/third_party/yaml-cpp/src/exceptions.cpp
+++ b/runtime/onnxruntime/third_party/yaml-cpp/src/exceptions.cpp
@@ -3,7 +3,7 @@
 // This is here for compatibility with older versions of Visual Studio
 // which don't support noexcept
 #ifdef _MSC_VER
-    #define YAML_CPP_NOEXCEPT _NOEXCEPT
+    #define YAML_CPP_NOEXCEPT noexcept
 #else
     #define YAML_CPP_NOEXCEPT noexcept
 #endif
diff --git a/runtime/websocket/CMakeLists.txt b/runtime/websocket/CMakeLists.txt
index 5f14bf4..b234265 100644
--- a/runtime/websocket/CMakeLists.txt
+++ b/runtime/websocket/CMakeLists.txt
@@ -9,7 +9,14 @@
 option(ENABLE_WEBSOCKET "Whether to build websocket server" ON)
 option(ENABLE_PORTAUDIO "Whether to build portaudio" ON)
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -fPIC")
+if(WIN32)
+else()
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -fPIC")
+endif()
+
+
+
+
 option(ENABLE_GLOG "Whether to build glog" ON)
 option(ENABLE_FST "Whether to build openfst" ON) # ITN need openfst compiled
 option(BUILD_SHARED_LIBS "Build shared libraries" ON)
diff --git a/runtime/websocket/bin/CMakeLists.txt b/runtime/websocket/bin/CMakeLists.txt
index b46e2ca..35408d0 100644
--- a/runtime/websocket/bin/CMakeLists.txt
+++ b/runtime/websocket/bin/CMakeLists.txt
@@ -1,10 +1,27 @@
 
-add_executable(funasr-wss-server "funasr-wss-server.cpp" "websocket-server.cpp")
-add_executable(funasr-wss-server-2pass "funasr-wss-server-2pass.cpp" "websocket-server-2pass.cpp")
-add_executable(funasr-wss-client "funasr-wss-client.cpp")
-add_executable(funasr-wss-client-2pass "funasr-wss-client-2pass.cpp" "microphone.cpp")
 
-target_link_libraries(funasr-wss-client PUBLIC funasr ssl crypto)
-target_link_libraries(funasr-wss-client-2pass PUBLIC funasr ssl crypto portaudio)
-target_link_libraries(funasr-wss-server PUBLIC funasr ssl crypto)
-target_link_libraries(funasr-wss-server-2pass PUBLIC funasr ssl crypto)
+if(WIN32)
+  include_directories(${ONNXRUNTIME_DIR}/include)
+  include_directories(${FFMPEG_DIR}/include)
+  include_directories(${OPENSSL_ROOT_DIR}//include)
+  link_directories(${OPENSSL_ROOT_DIR}/lib)
+  add_definitions(-D_WEBSOCKETPP_CPP11_RANDOM_DEVICE_)
+  add_definitions(-D_WEBSOCKETPP_CPP11_TYPE_TRAITS_)
+  add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/bigobj>")
+  add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
+  SET(RELATION_SOURCE "../../onnxruntime/src/audio.cpp" "../../onnxruntime/src/resample.cpp" "../../onnxruntime/src/util.cpp" "../../onnxruntime/src/alignedmem.cpp" "../../onnxruntime/src/encode_converter.cpp")
+endif()
+
+
+
+
+
+add_executable(funasr-wss-server "funasr-wss-server.cpp" "websocket-server.cpp" ${RELATION_SOURCE})
+add_executable(funasr-wss-server-2pass "funasr-wss-server-2pass.cpp" "websocket-server-2pass.cpp" ${RELATION_SOURCE})
+add_executable(funasr-wss-client "funasr-wss-client.cpp" ${RELATION_SOURCE})
+add_executable(funasr-wss-client-2pass "funasr-wss-client-2pass.cpp" "microphone.cpp" ${RELATION_SOURCE})
+
+target_link_libraries(funasr-wss-client PUBLIC funasr ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY})
+target_link_libraries(funasr-wss-client-2pass PUBLIC funasr ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY} portaudio)
+target_link_libraries(funasr-wss-server PUBLIC funasr ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY})
+target_link_libraries(funasr-wss-server-2pass PUBLIC funasr ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY})
diff --git a/runtime/websocket/bin/funasr-wss-server-2pass.cpp b/runtime/websocket/bin/funasr-wss-server-2pass.cpp
index 83bcaeb..2ad20a4 100644
--- a/runtime/websocket/bin/funasr-wss-server-2pass.cpp
+++ b/runtime/websocket/bin/funasr-wss-server-2pass.cpp
@@ -11,8 +11,13 @@
 //                    <string>] [--punc-quant <string>] [--punc-dir <string>]
 //                    [--vad-quant <string>] [--vad-dir <string>] [--quantize
 //                    <string>] --model-dir <string> [--] [--version] [-h]
-#include <unistd.h>
+
 #include "websocket-server-2pass.h"
+#ifdef _WIN32
+#include "win_func.h"
+#else
+#include <unistd.h>
+#endif
 #include <fstream>
 #include "util.h"
 
diff --git a/runtime/websocket/bin/funasr-wss-server.cpp b/runtime/websocket/bin/funasr-wss-server.cpp
index 66a9a58..da7fdd4 100644
--- a/runtime/websocket/bin/funasr-wss-server.cpp
+++ b/runtime/websocket/bin/funasr-wss-server.cpp
@@ -11,7 +11,11 @@
 //                    [--vad-quant <string>] [--vad-dir <string>] [--quantize
 //                    <string>] --model-dir <string> [--] [--version] [-h]
 #include "websocket-server.h"
+#ifdef _WIN32
+#include "win_func.h"
+#else
 #include <unistd.h>
+#endif
 #include <fstream>
 #include "util.h"
 
diff --git a/runtime/websocket/readme_zh.md b/runtime/websocket/readme_zh.md
index a940079..91a63d9 100644
--- a/runtime/websocket/readme_zh.md
+++ b/runtime/websocket/readme_zh.md
@@ -34,4 +34,42 @@
 mkdir build && cd build
 cmake  -DCMAKE_BUILD_TYPE=release .. -DONNXRUNTIME_DIR=/path/to/onnxruntime-linux-x64-1.14.0 -DFFMPEG_DIR=/path/to/ffmpeg-N-111383-g20b8688092-linux64-gpl-shared
 make -j 4
-```
\ No newline at end of file
+```
+
+
+## Windows 骞冲彴缂栬瘧
+### 涓嬭浇 onnxruntime
+https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl-\shared.zip
+
+涓嬭浇骞惰В鍘嬪埌 d:\ffmpeg-master-latest-win64-gpl-shared
+
+### 涓嬭浇 ffmpeg
+https://github.com/microsoft/onnxruntime/releases/download/v1.16.1/onnxruntime-win-x64-1.16.1.zip
+
+涓嬭浇骞惰В鍘嬪埌 d:\onnxruntime-win-x64-1.16.1
+
+### 缂栬瘧 openssl
+https://www.openssl.org/source/openssl-1.1.1w.tar.gz 
+
+涓嬭浇瑙e帇鍒� d:/src/openssl-1.1.1w
+
+鎵撳紑 x64 Native Tools Command Prompt 鎵ц浠ヤ笅缂栬瘧姝ラ
+```
+d:
+cd d:/src/openssl-1.1.1w
+perl Configure VC-WIN64A --prefix=d:/openssl-1.1.1w
+nmake
+namke install
+
+```
+
+### 缂栬瘧 runtime
+```
+git clone https://github.com/alibaba-damo-academy/FunASR.git 
+cd FunASR/runtime/websocket
+mkdir build
+cd build
+cmake ../ -D OPENSSL_ROOT_DIR=d:/openssl-1.1.1w -D FFMPEG_DIR=d:/ffmpeg-master-latest-win64-gpl-shared -D ONNXRUNTIME_DIR=d:/onnxruntime-win-x64-1.16.1
+```
+Visual Studio 鎵撳紑 FunASRWebscoket.sln 瀹屾垚缂栬瘧
+

--
Gitblit v1.9.1