From 249f2b59a0a893b7c9eef0442b9bd47d5cd32976 Mon Sep 17 00:00:00 2001
From: Xavier Deguillard <xavierd@fb.com>
Date: Wed, 23 Sep 2020 12:54:29 -0700
Subject: [PATCH] build: make it compile with @mode/win (#7406)

Summary:
While rocksdb can compile on both macOS and Linux with Buck, it couldn't be
compiled on Windows. The only way to compile it on Windows was with the CMake
build.

To keep the multi-platform complexity low, I've simply included all the Windows
bits in the TARGETS file, and added large #if blocks when not on Windows, the
same was done on the posix specific files.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/7406

Test Plan:
On my devserver:
  buck test //rocksdb/...
On Windows:
  buck build mode/win //rocksdb/src:rocksdb_lib

Reviewed By: pdillinger

Differential Revision: D23874358

Pulled By: xavierd

fbshipit-source-id: 8768b5d16d7e8f44b5ca1e2483881ca4b24bffbe
---
 TARGETS                      | 30 ++++++++++++++++++++++++------
 buckifier/targets_builder.py | 20 ++++++++++----------
 buckifier/targets_cfg.py     | 32 ++++++++++++++++++++++----------
 env/env_posix.cc             |  5 +++++
 env/fs_posix.cc              |  5 +++++
 port/port_posix.cc           |  4 ++++
 port/stack_trace.cc          |  5 +++--
 port/win/env_default.cc      |  4 ++++
 port/win/env_win.cc          |  4 ++++
 port/win/env_win.h           |  2 +-
 port/win/io_win.cc           | 16 ++++++++++------
 port/win/io_win.h            |  2 +-
 port/win/port_win.cc         |  6 +++---
 port/win/win_jemalloc.cc     |  4 ++++
 port/win/win_logger.cc       | 18 +++++++++---------
 port/win/win_thread.cc       |  4 ++++
 port/win/xpress_win.cc       |  4 ++++
 src.mk                       |  6 ++++++
 18 files changed, 123 insertions(+), 48 deletions(-)

diff --git a/TARGETS b/TARGETS
index ac811dc1b83..f598af99a4a 100644
--- a/TARGETS
+++ b/TARGETS
@@ -25,13 +25,16 @@ ROCKSDB_EXTERNAL_DEPS = [
     ("gflags", None, "gflags"),
     ("lz4", None, "lz4"),
     ("zstd", None),
-    ("tbb", None),
 ]
 
 ROCKSDB_OS_DEPS = [
     (
         "linux",
-        ["third-party//numa:numa", "third-party//liburing:uring"],
+        ["third-party//numa:numa", "third-party//liburing:uring", "third-party//tbb:tbb"],
+    ),
+    (
+        "macos",
+        ["third-party//tbb:tbb"],
     ),
 ]
 
@@ -49,17 +52,27 @@ ROCKSDB_OS_PREPROCESSOR_FLAGS = [
             "-DHAVE_SSE42",
             "-DLIBURING",
             "-DNUMA",
+            "-DROCKSDB_PLATFORM_POSIX",
+            "-DROCKSDB_LIB_IO_POSIX",
+            "-DTBB",
         ],
     ),
     (
         "macos",
-        ["-DOS_MACOSX"],
+        [
+            "-DOS_MACOSX",
+            "-DROCKSDB_PLATFORM_POSIX",
+            "-DROCKSDB_LIB_IO_POSIX",
+            "-DTBB",
+        ],
+    ),
+    (
+        "windows",
+        [ "-DOS_WIN", "-DWIN32", "-D_MBCS", "-DWIN64", "-DNOMINMAX" ]
     ),
 ]
 
 ROCKSDB_PREPROCESSOR_FLAGS = [
-    "-DROCKSDB_PLATFORM_POSIX",
-    "-DROCKSDB_LIB_IO_POSIX",
     "-DROCKSDB_SUPPORT_THREAD_LOCAL",
 
     # Flags to enable libs we include
@@ -70,7 +83,6 @@ ROCKSDB_PREPROCESSOR_FLAGS = [
     "-DZSTD",
     "-DZSTD_STATIC_LINKING_ONLY",
     "-DGFLAGS=gflags",
-    "-DTBB",
 
     # Added missing flags from output of build_detect_platform
     "-DROCKSDB_BACKTRACE",
@@ -246,6 +258,12 @@ cpp_library(
         "options/options_parser.cc",
         "port/port_posix.cc",
         "port/stack_trace.cc",
+        "port/win/env_default.cc",
+        "port/win/env_win.cc",
+        "port/win/io_win.cc",
+        "port/win/port_win.cc",
+        "port/win/win_logger.cc",
+        "port/win/win_thread.cc",
         "table/adaptive/adaptive_table_factory.cc",
         "table/block_based/binary_search_index_reader.cc",
         "table/block_based/block.cc",
diff --git a/buckifier/targets_builder.py b/buckifier/targets_builder.py
index 73c289a8ab2..0b67e0b3762 100644
--- a/buckifier/targets_builder.py
+++ b/buckifier/targets_builder.py
@@ -27,9 +27,9 @@ def pretty_list(lst, indent=8):
 class TARGETSBuilder(object):
     def __init__(self, path):
         self.path = path
-        self.targets_file = open(path, 'w')
+        self.targets_file = open(path, 'wb')
         header = targets_cfg.rocksdb_target_header_template
-        self.targets_file.write(header)
+        self.targets_file.write(header.encode("utf-8"))
         self.total_lib = 0
         self.total_bin = 0
         self.total_test = 0
@@ -52,7 +52,7 @@ def add_library(self, name, srcs, deps=None, headers=None,
             headers_attr_prefix=headers_attr_prefix,
             headers=headers,
             deps=pretty_list(deps),
-            extra_external_deps=extra_external_deps))
+            extra_external_deps=extra_external_deps).encode("utf-8"))
         self.total_lib = self.total_lib + 1
 
     def add_rocksdb_library(self, name, srcs, headers=None):
@@ -66,18 +66,18 @@ def add_rocksdb_library(self, name, srcs, headers=None):
             name=name,
             srcs=pretty_list(srcs),
             headers_attr_prefix=headers_attr_prefix,
-            headers=headers))
+            headers=headers).encode("utf-8"))
         self.total_lib = self.total_lib + 1
 
     def add_binary(self, name, srcs, deps=None):
-        self.targets_file.write(targets_cfg.binary_template % (
-            name,
-            pretty_list(srcs),
-            pretty_list(deps)))
+        self.targets_file.write(targets_cfg.binary_template.format(
+            name=name,
+            srcs=pretty_list(srcs),
+            deps=pretty_list(deps)).encode("utf-8"))
         self.total_bin = self.total_bin + 1
 
     def add_c_test(self):
-        self.targets_file.write("""
+        self.targets_file.write(b"""
 if not is_opt_mode:
     cpp_binary(
         name = "c_test_bin",
@@ -119,5 +119,5 @@ def register_test(self,
         self.total_test = self.total_test + 1
 
     def flush_tests(self):
-        self.targets_file.write(targets_cfg.unittests_template % self.tests_cfg)
+        self.targets_file.write(targets_cfg.unittests_template.format(tests=self.tests_cfg).encode("utf-8"))
         self.tests_cfg = ""
diff --git a/buckifier/targets_cfg.py b/buckifier/targets_cfg.py
index 1115ebdbfb0..110842312b8 100644
--- a/buckifier/targets_cfg.py
+++ b/buckifier/targets_cfg.py
@@ -32,13 +32,16 @@
     ("gflags", None, "gflags"),
     ("lz4", None, "lz4"),
     ("zstd", None),
-    ("tbb", None),
 ]
 
 ROCKSDB_OS_DEPS = [
     (
         "linux",
-        ["third-party//numa:numa", "third-party//liburing:uring"],
+        ["third-party//numa:numa", "third-party//liburing:uring", "third-party//tbb:tbb"],
+    ),
+    (
+        "macos",
+        ["third-party//tbb:tbb"],
     ),
 ]
 
@@ -56,17 +59,27 @@
             "-DHAVE_SSE42",
             "-DLIBURING",
             "-DNUMA",
+            "-DROCKSDB_PLATFORM_POSIX",
+            "-DROCKSDB_LIB_IO_POSIX",
+            "-DTBB",
         ],
     ),
     (
         "macos",
-        ["-DOS_MACOSX"],
+        [
+            "-DOS_MACOSX",
+            "-DROCKSDB_PLATFORM_POSIX",
+            "-DROCKSDB_LIB_IO_POSIX",
+            "-DTBB",
+        ],
+    ),
+    (
+        "windows",
+        [ "-DOS_WIN", "-DWIN32", "-D_MBCS", "-DWIN64", "-DNOMINMAX" ]
     ),
 ]
 
 ROCKSDB_PREPROCESSOR_FLAGS = [
-    "-DROCKSDB_PLATFORM_POSIX",
-    "-DROCKSDB_LIB_IO_POSIX",
     "-DROCKSDB_SUPPORT_THREAD_LOCAL",
 
     # Flags to enable libs we include
@@ -77,7 +90,6 @@
     "-DZSTD",
     "-DZSTD_STATIC_LINKING_ONLY",
     "-DGFLAGS=gflags",
-    "-DTBB",
 
     # Added missing flags from output of build_detect_platform
     "-DROCKSDB_BACKTRACE",
@@ -154,12 +166,12 @@
 
 binary_template = """
 cpp_binary(
-    name = "%s",
-    srcs = [%s],
+    name = "{name}",
+    srcs = [{srcs}],
     arch_preprocessor_flags = ROCKSDB_ARCH_PREPROCESSOR_FLAGS,
     compiler_flags = ROCKSDB_COMPILER_FLAGS,
     preprocessor_flags = ROCKSDB_PREPROCESSOR_FLAGS,
-    deps = [%s],
+    deps = [{deps}],
     external_deps = ROCKSDB_EXTERNAL_DEPS,
 )
 """
@@ -176,7 +188,7 @@
 unittests_template = """
 # [test_name, test_src, test_type, extra_deps, extra_compiler_flags]
 ROCKS_TESTS = [
-%s]
+{tests}]
 
 # Generate a test rule for each entry in ROCKS_TESTS
 # Do not build the tests in opt mode, since SyncPoint and other test code
diff --git a/env/env_posix.cc b/env/env_posix.cc
index 46f1b42fdff..fd7cbec22d3 100644
--- a/env/env_posix.cc
+++ b/env/env_posix.cc
@@ -6,6 +6,9 @@
 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors
+
+#if !defined(OS_WIN)
+
 #include <dirent.h>
 #ifndef ROCKSDB_NO_DYNAMIC_EXTENSION
 #include <dlfcn.h>
@@ -517,3 +520,5 @@ std::unique_ptr<Env> NewCompositeEnv(std::shared_ptr<FileSystem> fs) {
 }
 
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/env/fs_posix.cc b/env/fs_posix.cc
index b4311c859cb..5fa3d8224f0 100644
--- a/env/fs_posix.cc
+++ b/env/fs_posix.cc
@@ -6,6 +6,9 @@
 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors
+
+#if !defined(OS_WIN)
+
 #include <dirent.h>
 #ifndef ROCKSDB_NO_DYNAMIC_EXTENSION
 #include <dlfcn.h>
@@ -1060,3 +1063,5 @@ static FactoryFunc<FileSystem> posix_filesystem_reg =
 #endif
 
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/port/port_posix.cc b/port/port_posix.cc
index 4154b4fa9df..8610c6e0d5d 100644
--- a/port/port_posix.cc
+++ b/port/port_posix.cc
@@ -7,6 +7,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors.
 
+#if !defined(OS_WIN)
+
 #include "port/port_posix.h"
 
 #include <assert.h>
@@ -262,3 +264,5 @@ void SetCpuPriority(ThreadId id, CpuPriority priority) {
 
 }  // namespace port
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/port/stack_trace.cc b/port/stack_trace.cc
index 310ba77d2e3..dee8bd9cea6 100644
--- a/port/stack_trace.cc
+++ b/port/stack_trace.cc
@@ -5,8 +5,9 @@
 //
 #include "port/stack_trace.h"
 
-#if defined(ROCKSDB_LITE) || !(defined(ROCKSDB_BACKTRACE) || defined(OS_MACOSX)) || \
-    defined(CYGWIN) || defined(OS_FREEBSD) || defined(OS_SOLARIS)
+#if defined(ROCKSDB_LITE) ||                                                  \
+    !(defined(ROCKSDB_BACKTRACE) || defined(OS_MACOSX)) || defined(CYGWIN) || \
+    defined(OS_FREEBSD) || defined(OS_SOLARIS) || defined(OS_WIN)
 
 // noop
 
diff --git a/port/win/env_default.cc b/port/win/env_default.cc
index 663779ddeca..36f95fbe342 100644
--- a/port/win/env_default.cc
+++ b/port/win/env_default.cc
@@ -7,6 +7,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors.
 
+#if defined(OS_WIN)
+
 #include <mutex>
 
 #include <rocksdb/env.h>
@@ -39,3 +41,5 @@ Env* Env::Default() {
 }
 
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/port/win/env_win.cc b/port/win/env_win.cc
index 9c6a0208ff3..f7d8f9ce3ce 100644
--- a/port/win/env_win.cc
+++ b/port/win/env_win.cc
@@ -7,6 +7,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors.
 
+#if defined(OS_WIN)
+
 #include "port/win/env_win.h"
 #include "port/win/win_thread.h"
 #include <algorithm>
@@ -1549,3 +1551,5 @@ std::string Env::GenerateUniqueId() {
 }
 
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/port/win/env_win.h b/port/win/env_win.h
index fc7402f7f9f..24e3a56fe36 100644
--- a/port/win/env_win.h
+++ b/port/win/env_win.h
@@ -311,7 +311,7 @@ class WinEnv : public Env {
 
   void StartThread(void(*function)(void* arg), void* arg) override;
 
-  void WaitForJoin();
+  void WaitForJoin() override;
 
   unsigned int GetThreadPoolQueueLen(Env::Priority pri) const override;
 
diff --git a/port/win/io_win.cc b/port/win/io_win.cc
index e6c6890ef80..f8d1c3dbb83 100644
--- a/port/win/io_win.cc
+++ b/port/win/io_win.cc
@@ -7,6 +7,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors.
 
+#if defined(OS_WIN)
+
 #include "port/win/io_win.h"
 
 #include "monitoring/iostats_context_imp.h"
@@ -642,8 +644,8 @@ Status WinSequentialFile::Skip(uint64_t n) {
   BOOL ret = SetFilePointerEx(hFile_, li, NULL, FILE_CURRENT);
   if (ret == FALSE) {
     auto lastError = GetLastError();
-    return IOErrorFromWindowsError("Skip SetFilePointerEx():" + filename_, 
-      lastError);
+    return IOErrorFromWindowsError("Skip SetFilePointerEx():" + filename_,
+                                   lastError);
   }
   return Status::OK();
 }
@@ -767,8 +769,8 @@ Status WinWritableImpl::AppendImpl(const Slice& data) {
   Status s;
 
   if (data.size() > std::numeric_limits<DWORD>::max()) {
-    return Status::InvalidArgument("data is too long for a single write" + 
-      file_data_->GetName());
+    return Status::InvalidArgument("data is too long for a single write" +
+                                   file_data_->GetName());
   }
 
   size_t bytes_written = 0; // out param
@@ -805,8 +807,8 @@ Status WinWritableImpl::AppendImpl(const Slice& data) {
       // is sector aligned
       next_write_offset_ += bytes_written;
     } else {
-      s = Status::IOError("Failed to write all bytes: " + 
-        file_data_->GetName());
+      s = Status::IOError("Failed to write all bytes: " +
+                          file_data_->GetName());
     }
   }
 
@@ -1067,3 +1069,5 @@ WinFileLock::~WinFileLock() {
 
 }
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/port/win/io_win.h b/port/win/io_win.h
index 4fc2ba499bc..d7aa7b48397 100644
--- a/port/win/io_win.h
+++ b/port/win/io_win.h
@@ -409,7 +409,7 @@ class WinRandomRWFile : private WinFileData,
 
   virtual Status Sync() override;
 
-  virtual Status Fsync() { return Sync(); }
+  virtual Status Fsync() override { return Sync(); }
 
   virtual Status Close() override;
 };
diff --git a/port/win/port_win.cc b/port/win/port_win.cc
index 2d99a7a9b91..16599911d8f 100644
--- a/port/win/port_win.cc
+++ b/port/win/port_win.cc
@@ -7,9 +7,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors.
 
-#if !defined(OS_WIN) && !defined(WIN32) && !defined(_WIN32)
-#error Windows Specific Code
-#endif
+#if defined(OS_WIN)
 
 #include "port/win/port_win.h"
 
@@ -272,3 +270,5 @@ void SetCpuPriority(ThreadId id, CpuPriority priority) {
 
 }  // namespace port
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/port/win/win_jemalloc.cc b/port/win/win_jemalloc.cc
index a29232f8a2e..f054469ccce 100644
--- a/port/win/win_jemalloc.cc
+++ b/port/win/win_jemalloc.cc
@@ -7,6 +7,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors.
 
+#if defined(OS_WIN)
+
 #ifndef ROCKSDB_JEMALLOC
 # error This file can only be part of jemalloc aware build
 #endif
@@ -73,3 +75,5 @@ void operator delete[](void* p) {
     je_free(p);
   }
 }
+
+#endif
diff --git a/port/win/win_logger.cc b/port/win/win_logger.cc
index d429a3f4a5e..a9b10c04b8c 100644
--- a/port/win/win_logger.cc
+++ b/port/win/win_logger.cc
@@ -10,6 +10,8 @@
 // Logger implementation that can be shared by all environments
 // where enough posix functionality is available.
 
+#if defined(OS_WIN)
+
 #include "port/win/win_logger.h"
 #include "port/win/io_win.h"
 
@@ -47,13 +49,11 @@ void WinLogger::DebugWriter(const char* str, int len) {
   BOOL ret = WriteFile(file_, str, len, &bytesWritten, NULL);
   if (ret == FALSE) {
     std::string errSz = GetWindowsErrSz(GetLastError());
-    fprintf(stderr, errSz.c_str());
+    fprintf(stderr, "%s", errSz.c_str());
   }
 }
 
-WinLogger::~WinLogger() { 
-  CloseInternal();
-}
+WinLogger::~WinLogger() { CloseInternal(); }
 
 Status WinLogger::CloseImpl() {
   return CloseInternal();
@@ -65,15 +65,13 @@ Status WinLogger::CloseInternal() {
     BOOL ret = FlushFileBuffers(file_);
     if (ret == 0) {
       auto lastError = GetLastError();
-      s = IOErrorFromWindowsError("Failed to flush LOG on Close() ", 
-        lastError);
+      s = IOErrorFromWindowsError("Failed to flush LOG on Close() ", lastError);
     }
     ret = CloseHandle(file_);
     // On error the return value is zero
     if (ret == 0 && s.ok()) {
       auto lastError = GetLastError();
-      s = IOErrorFromWindowsError("Failed to flush LOG on Close() ", 
-        lastError);
+      s = IOErrorFromWindowsError("Failed to flush LOG on Close() ", lastError);
     }
     file_ = INVALID_HANDLE_VALUE;
     closed_ = true;
@@ -163,7 +161,7 @@ void WinLogger::Logv(const char* format, va_list ap) {
       &bytesWritten, NULL);
     if (ret == FALSE) {
       std::string errSz = GetWindowsErrSz(GetLastError());
-      fprintf(stderr, errSz.c_str());
+      fprintf(stderr, "%s", errSz.c_str());
     }
 
     flush_pending_ = true;
@@ -190,3 +188,5 @@ size_t WinLogger::GetLogFileSize() const { return log_size_; }
 }
 
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/port/win/win_thread.cc b/port/win/win_thread.cc
index 74c667b5447..2bc05e8da32 100644
--- a/port/win/win_thread.cc
+++ b/port/win/win_thread.cc
@@ -7,6 +7,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors.
 
+#if defined(OS_WIN)
+
 #include "port/win/win_thread.h"
 
 #include <assert.h>
@@ -177,3 +179,5 @@ unsigned int __stdcall  WindowsThread::Data::ThreadProc(void* arg) {
 }
 } // namespace port
 }  // namespace ROCKSDB_NAMESPACE
+
+#endif
diff --git a/port/win/xpress_win.cc b/port/win/xpress_win.cc
index bcc106534d7..c016d62b2c2 100644
--- a/port/win/xpress_win.cc
+++ b/port/win/xpress_win.cc
@@ -7,6 +7,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file. See the AUTHORS file for names of contributors.
 
+#if defined(OS_WIN)
+
 #include "port/win/xpress_win.h"
 #include <windows.h>
 
@@ -224,3 +226,5 @@ char* Decompress(const char* input_data, size_t input_length,
 }  // namespace ROCKSDB_NAMESPACE
 
 #endif
+
+#endif
diff --git a/src.mk b/src.mk
index 69dd757482d..0563d7bb6d5 100644
--- a/src.mk
+++ b/src.mk
@@ -129,6 +129,12 @@ LIB_SOURCES =                                                   \
   options/options_helper.cc                                     \
   options/options_parser.cc                                     \
   port/port_posix.cc                                            \
+  port/win/env_default.cc                                       \
+  port/win/env_win.cc                                           \
+  port/win/io_win.cc                                            \
+  port/win/port_win.cc                                          \
+  port/win/win_logger.cc                                        \
+  port/win/win_thread.cc                                        \
   port/stack_trace.cc                                           \
   table/adaptive/adaptive_table_factory.cc                      \
   table/block_based/binary_search_index_reader.cc               \