Add WASI compatibility (#2144)
* Detect non-Emscripten WASI builds
* Guard clocks & system APIs
google#1774
Co-authored-by: Roman Lebedev <lebedev.ri@gmail.com>
diff --git a/src/benchmark.cc b/src/benchmark.cc
index acf4d3b..e866d29 100644
--- a/src/benchmark.cc
+++ b/src/benchmark.cc
@@ -22,7 +22,8 @@
#include "internal_macros.h"
#ifndef BENCHMARK_OS_WINDOWS
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
+#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) && \
+ !defined(BENCHMARK_OS_WASI)
#include <sys/resource.h>
#endif
#include <sys/time.h>
diff --git a/src/benchmark_register.cc b/src/benchmark_register.cc
index 730d275..560a762 100644
--- a/src/benchmark_register.cc
+++ b/src/benchmark_register.cc
@@ -15,7 +15,8 @@
#include "benchmark_register.h"
#ifndef BENCHMARK_OS_WINDOWS
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
+#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) && \
+ !defined(BENCHMARK_OS_WASI)
#include <sys/resource.h>
#endif
#include <sys/time.h>
diff --git a/src/benchmark_runner.cc b/src/benchmark_runner.cc
index 7efbad4..f6d37e0 100644
--- a/src/benchmark_runner.cc
+++ b/src/benchmark_runner.cc
@@ -23,7 +23,8 @@
#include "internal_macros.h"
#ifndef BENCHMARK_OS_WINDOWS
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
+#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) && \
+ !defined(BENCHMARK_OS_WASI)
#include <sys/resource.h>
#endif
#include <sys/time.h>
diff --git a/src/cycleclock.h b/src/cycleclock.h
index 2633f22..23d67d7 100644
--- a/src/cycleclock.h
+++ b/src/cycleclock.h
@@ -235,7 +235,7 @@
struct timeval tv;
gettimeofday(&tv, nullptr);
return static_cast<int64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
-#elif defined(__hppa__) || defined(__linux__)
+#elif defined(__hppa__) || defined(__linux__) || defined(BENCHMARK_OS_WASI)
// Fallback for all other architectures with a recent Linux kernel, e.g.:
// HP PA-RISC provides a user-readable clock counter (cr16), but
// it's not syncronized across CPUs and only 32-bit wide when programs
diff --git a/src/internal_macros.h b/src/internal_macros.h
index 22e3e21..a0bd0e1 100644
--- a/src/internal_macros.h
+++ b/src/internal_macros.h
@@ -77,6 +77,8 @@
#define BENCHMARK_OS_NACL 1
#elif defined(__EMSCRIPTEN__)
#define BENCHMARK_OS_EMSCRIPTEN 1
+#elif defined(__wasi__)
+ #define BENCHMARK_OS_WASI 1
#elif defined(__rtems__)
#define BENCHMARK_OS_RTEMS 1
#elif defined(__Fuchsia__)
diff --git a/src/sysinfo.cc b/src/sysinfo.cc
index 39da0fe..ca32daa 100644
--- a/src/sysinfo.cc
+++ b/src/sysinfo.cc
@@ -27,7 +27,8 @@
#include <codecvt>
#else
#include <fcntl.h>
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
+#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) && \
+ !defined(BENCHMARK_OS_WASI)
#include <sys/resource.h>
#endif
#include <sys/time.h>
@@ -444,7 +445,8 @@
return GetCacheSizesWindows();
#elif defined(BENCHMARK_OS_QNX)
return GetCacheSizesQNX();
-#elif defined(BENCHMARK_OS_QURT) || defined(__EMSCRIPTEN__)
+#elif defined(BENCHMARK_OS_QURT) || defined(BENCHMARK_OS_EMSCRIPTEN) || \
+ defined(BENCHMARK_OS_WASI)
return std::vector<CPUInfo::CacheInfo>();
#else
return GetCacheSizesFromKVFS();
@@ -477,6 +479,8 @@
str += std::to_string(arch_version_struct.arch_version);
}
return str;
+#elif defined(BENCHMARK_OS_WASI)
+ return std::string("wasi");
#else
#ifndef HOST_NAME_MAX
#ifdef BENCHMARK_HAS_SYSCTL // BSD/Mac doesn't have HOST_NAME_MAX defined
diff --git a/src/timers.cc b/src/timers.cc
index f8d9560..53cf487 100644
--- a/src/timers.cc
+++ b/src/timers.cc
@@ -23,7 +23,8 @@
#include <windows.h>
#else
#include <fcntl.h>
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
+#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) && \
+ !defined(BENCHMARK_OS_WASI)
#include <sys/resource.h>
#endif
#include <sys/time.h>
@@ -84,7 +85,8 @@
static_cast<double>(user.QuadPart)) *
1e-7;
}
-#elif !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
+#elif !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT) && \
+ !defined(BENCHMARK_OS_WASI)
double MakeTime(struct rusage const& ru) {
return (static_cast<double>(ru.ru_utime.tv_sec) +
static_cast<double>(ru.ru_utime.tv_usec) * 1e-6 +
@@ -140,6 +142,14 @@
// same as total time, but this is ok because there aren't long-latency
// synchronous system calls in Emscripten.
return emscripten_get_now() * 1e-3;
+#elif defined(BENCHMARK_OS_WASI)
+ // WASI lacks CLOCK_PROCESS_CPUTIME_ID and getrusage; use monotonic clock.
+ struct timespec ts {};
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+ return static_cast<double>(ts.tv_sec) +
+ (static_cast<double>(ts.tv_nsec) * 1e-9);
+ }
+ DiagnoseAndExit("clock_gettime(CLOCK_MONOTONIC, ...) failed");
#elif defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
// FIXME We want to use clock_gettime, but its not available in MacOS 10.11.
// See https://github.com/google/benchmark/pull/292
@@ -195,6 +205,9 @@
#elif defined(BENCHMARK_OS_ZOS)
// z/OS doesn't support CLOCK_THREAD_CPUTIME_ID.
return ProcessCPUUsage();
+#elif defined(BENCHMARK_OS_WASI)
+ // WASI doesn't support per-thread CPU timing; fall back to process time.
+ return ProcessCPUUsage();
#elif defined(BENCHMARK_OS_SOLARIS)
struct rusage ru;
if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru);