From a17efcb039c1128fdb11fd147687f15f2ae12494 Mon Sep 17 00:00:00 2001
From: Pavel Maryanov <acid@jack.kiev.ua>
Date: Tue, 10 Oct 2017 14:05:28 +0100
Subject: [PATCH] make this build on SunOS/Solaris

---
 CMakeLists.txt                              |  6 ++++++
 README.md                                   | 11 +++++++++++
 external/miniupnpc/CMakeLists.txt           |  3 +++
 external/unbound/CMakeLists.txt             |  5 +++++
 external/unbound/configure_checks.cmake     |  5 +++++
 src/common/int-util.h                       |  4 ++++
 src/common/util.cpp                         |  2 +-
 src/crypto/initializer.h                    |  5 +++++
 tests/performance_tests/performance_utils.h |  4 ++--
 9 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 637e9c4e6..328e17646 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -331,6 +331,10 @@ if (UNIX AND NOT APPLE)
 endif()
 
 # Handle OpenSSL, used for sha256sum on binary updates and light wallet ssl http
+if (CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthreads")
+endif ()
+
 if (APPLE AND NOT IOS)
   if (NOT OpenSSL_DIR)
       EXECUTE_PROCESS(COMMAND brew --prefix openssl
@@ -675,6 +679,8 @@ elseif(FREEBSD)
 elseif(DRAGONFLY)
   find_library(COMPAT compat)
   set(EXTRA_LIBRARIES execinfo ${COMPAT})
+elseif(CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)")
+  set(EXTRA_LIBRARIES socket nsl resolv)
 elseif(NOT MSVC)
   find_library(RT rt)
   set(EXTRA_LIBRARIES ${RT})
diff --git a/README.md b/README.md
index 4036743e1..2dec65465 100644
--- a/README.md
+++ b/README.md
@@ -430,6 +430,17 @@ doas make install
 
 Build monero: `env DEVELOPER_LOCAL_TOOLS=1 BOOST_ROOT=/usr/local make release-static`
 
+### On Solaris:
+
+The default Solaris linker can't be used, you have to install GNU ld, then run cmake manually with the path to your copy of GNU ld:
+
+        mkdir -p build/release
+        cd build/release
+        cmake -DCMAKE_LINKER=/path/to/ld -D CMAKE_BUILD_TYPE=Release ../..
+        cd ../..
+
+Then you can run make as usual.
+
 ### On Linux for Android (using docker):
 
         # Build image (select android64.Dockerfile for aarch64)
diff --git a/external/miniupnpc/CMakeLists.txt b/external/miniupnpc/CMakeLists.txt
index 4c01b6d06..bc9685699 100644
--- a/external/miniupnpc/CMakeLists.txt
+++ b/external/miniupnpc/CMakeLists.txt
@@ -36,6 +36,9 @@ if (NOT WIN32)
     # add_definitions (-D_POSIX_C_SOURCE=200112L)
     add_definitions (-D_XOPEN_SOURCE=600)
   endif (NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" AND NOT CMAKE_SYSTEM_NAME STREQUAL "DragonFly")
+  if (CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)")
+    add_definitions (-D__EXTENSIONS__ -std=c99)
+  endif ()
 else (NOT WIN32)
   add_definitions (-D_WIN32_WINNT=0x0501) # XP or higher for getnameinfo and friends
 endif (NOT WIN32)
diff --git a/external/unbound/CMakeLists.txt b/external/unbound/CMakeLists.txt
index 8ac4bbd84..a2e475232 100644
--- a/external/unbound/CMakeLists.txt
+++ b/external/unbound/CMakeLists.txt
@@ -44,7 +44,12 @@ endif ()
 
 set(RETSIGTYPE void)
 
+if(CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)")
+add_definitions(-D_XOPEN_SOURCE=600)
+else()
 add_definitions(-D_GNU_SOURCE)
+endif()
+add_definitions(-std=c99)
 
 option(USE_ECDSA "Use ECDSA algorithms" ON)
 option(USE_SHA2 "Enable SHA2 support" ON)
diff --git a/external/unbound/configure_checks.cmake b/external/unbound/configure_checks.cmake
index 258f28138..2acf556d1 100644
--- a/external/unbound/configure_checks.cmake
+++ b/external/unbound/configure_checks.cmake
@@ -49,6 +49,11 @@ if (WIN32)
     iphlpapi
     ws2_32)
 endif ()
+if (CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)")
+  set(CMAKE_REQUIRED_LIBRARIES
+    socket
+    nsl)
+endif ()
 
 check_function_exists(_beginthreadex HAVE__BEGINTHREADEX)
 check_function_exists(arc4random HAVE_ARC4RANDOM)
diff --git a/src/common/int-util.h b/src/common/int-util.h
index 34288805a..7cec571ad 100644
--- a/src/common/int-util.h
+++ b/src/common/int-util.h
@@ -40,6 +40,10 @@
 #include <byteswap.h>
 #endif
 
+#if defined(__sun) && defined(__SVR4)
+#include <endian.h>
+#endif
+
 #if defined(_MSC_VER)
 #include <stdlib.h>
 
diff --git a/src/common/util.cpp b/src/common/util.cpp
index 1e180d325..a13ac6e50 100644
--- a/src/common/util.cpp
+++ b/src/common/util.cpp
@@ -405,7 +405,7 @@ namespace tools
 #else
 std::string get_nix_version_display_string()
 {
-  utsname un;
+  struct utsname un;
 
   if(uname(&un) < 0)
     return std::string("*nix: failed to get os version");
diff --git a/src/crypto/initializer.h b/src/crypto/initializer.h
index 619038ae6..eb1d1c069 100644
--- a/src/crypto/initializer.h
+++ b/src/crypto/initializer.h
@@ -31,8 +31,13 @@
 #pragma once
 
 #if defined(__GNUC__)
+#if defined(__sun) && defined(__SVR4)
+#define INITIALIZER(name) __attribute__((constructor)) static void name(void)
+#define FINALIZER(name) __attribute__((destructor)) static void name(void)
+#else
 #define INITIALIZER(name) __attribute__((constructor(101))) static void name(void)
 #define FINALIZER(name) __attribute__((destructor(101))) static void name(void)
+#endif
 #define REGISTER_FINALIZER(name) ((void) 0)
 
 #elif defined(_MSC_VER)
diff --git a/tests/performance_tests/performance_utils.h b/tests/performance_tests/performance_utils.h
index 061772cbd..6bf45ff83 100644
--- a/tests/performance_tests/performance_utils.h
+++ b/tests/performance_tests/performance_utils.h
@@ -40,7 +40,7 @@
 
 void set_process_affinity(int core)
 {
-#if defined (__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+#if defined (__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun)
     return;
 #elif defined(BOOST_WINDOWS)
   DWORD_PTR mask = 1;
@@ -62,7 +62,7 @@ void set_process_affinity(int core)
 
 void set_thread_high_priority()
 {
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun)
     return;
 #elif defined(BOOST_WINDOWS)
   ::SetPriorityClass(::GetCurrentProcess(), HIGH_PRIORITY_CLASS);