From 9ba9bd80f2ee233bbd61fd6bb243b3dfc2ec7d9c Mon Sep 17 00:00:00 2001
From: Kyrian Obikwelu <koshnawaza@gmail.com>
Date: Wed, 24 Apr 2024 00:30:05 +0100
Subject: [PATCH] Update makefiles and library files for macOS compatibility

---
 CMakeLists.txt      |  2 +-
 README.md           | 81 ++++++++++++++++++++++++++++++++++++++++-----
 cmake/Packing.cmake |  2 ++
 src/CMakeLists.txt  | 19 +++++++++++
 src/common.h        | 22 +++++++-----
 5 files changed, 109 insertions(+), 17 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c56e80..28a77b5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,7 +19,7 @@ add_subdirectory(./src)
 add_subdirectory(./include)
 add_subdirectory(./tests)
 
-if(UNIX)
+if(UNIX AND NOT APPLE)
     add_subdirectory(./debian)
 endif()
 
diff --git a/README.md b/README.md
index 86bb928..8af07d4 100644
--- a/README.md
+++ b/README.md
@@ -11,17 +11,19 @@ Rindow Math Matrix is the fundamental package for scientific matrix operation
 You can call a high-speed calculation library written in C language to speed up matrix calculation processing.
 Rindow Matlib includes many matrix operations functions used in machine learning.
 
-Please see the documents about rindow mathematics on [Rindow Mathematics](https://rindow.github.io/mathematics/openblas/mathlibrary.html) web pages.
+Please see the documents about rindow mathematics
+on [Rindow Mathematics](https://rindow.github.io/mathematics/openblas/mathlibrary.html) web pages.
 
 Requirements
 ============
-- Windows 10 or later, Linux(Ubuntu 20.04 or later)
 
+- Windows 10 or later, Linux(Ubuntu 20.04 or later)
 
 How to setup pre-build binaries
 ===============================
 
 ### How to setup for Windows
+
 Download the pre-build binary file.
 
 - https://github.com/rindow/rindow-matlib/releases
@@ -33,11 +35,12 @@ C> PATH %PATH%;C:\path\to\bin
 ```
 
 ### How to setup for Ubuntu
+
 Download the pre-build binary file.
 
 - https://github.com/rindow/rindow-matlib/releases
 
-Please install using the apt command. 
+Please install using the apt command.
 
 ```shell
 $ sudo apt install ./rindow-matlib_X.X.X_amd64.deb
@@ -58,11 +61,37 @@ There are 2 choices for the alternative librindowmatlib.so (providing /usr/lib/l
 Press <enter> to keep the current choice[*], or type selection number: 2
 ```
 
+### How to setup for MacOS
+
+Download the pre-build binary file.
+
+- https://github.com/rindow/rindow-matlib/releases
+
+Extract the tar.gz file to the tmp directory and navigate to the directory.
+
+```shell
+$ tar -xzf rindow-matlib-X.X.X-Darwin.tar.gz -C /tmp
+$ cd /tmp/rindow-matlib-X.X.X-Darwin
+```
+
+Next, copy the include and lib directories to /usr/local.
+
+```shell
+$ sudo cp -r usr/include /usr/local/
+$ sudo cp -r usr/lib /usr/local/
+```
+
+Depending on whether you are using OpenMP or not, you need to set the symbolic link.
+
+```shell
+$ sudo ln -s /usr/local/lib/rindowmatlib-openmp/librindowmatlib.dylib /usr/local/lib/librindowmatlib.dylib
+```
+
 How to build from source code on Windows
 ========================================
 You can also build and use from source code.
 
-### download source code
+### Download source code
 
 Download source code from release and unzip
 
@@ -81,6 +110,7 @@ C> ctest -C Release
 C> cpack -C Release
 C> cd ..\packages
 ```
+
 Unzip the package file from packages directory.
 
 ```shell
@@ -91,7 +121,7 @@ How to build from source code on Ubuntu
 =======================================
 You can also build and use from source code.
 
-### download source code
+### Download source code
 
 Download source code from release and extract
 
@@ -108,7 +138,8 @@ $ cmake --build build --config Release
 $ (cd build; ctest -C Release)
 $ (cd build; cpack -C Release)
 ```
-Install with apt commnand.
+
+Install with apt command.
 
 ```shell
 $ sudo apt install ./packages/rindow-matlib_X.X.X_amd64.deb
@@ -129,10 +160,34 @@ There are 2 choices for the alternative librindowmatlib.so (providing /usr/lib/l
 Press <enter> to keep the current choice[*], or type selection number: 2
 ```
 
+How to build from source code on MacOS
+=======================================
+
+You can also build and use from source code.
+
+### Download source code
+
+Download source code from release and extract
+
+- https://github.com/rindow/rindow-matlib/releases
+
+### Build and Install on MacOS
+
+Build with cmake.
+
+```shell
+$ cd \path\to\here
+$ cmake -S . -B build
+$ cmake --build build --config Release
+$ (cd build; ctest -C Release)
+$ (cd build; cpack -C Release)
+```
+
 How to use
 ==========
 
 ### sample program
+
 ```cpp
 #include <iostream>
 #include <string>
@@ -199,10 +254,20 @@ int main(int ac, char **av)
 }
 ```
 
-### build the sample program on Windows.
+### Build the sample program on Windows.
 
+```shell
 C> cl /EHsc -I.\path\to\include sample.cpp \path\to\lib\rindowmatlib.lib
+```
 
-### build the sample program on Ubuntu.
+### Build the sample program on Ubuntu.
 
+```shell
+$ g++ sample.cpp -lrindowmatlib -lm
+```
+
+### Build the sample program on MacOS.
+
+```shell
 $ g++ sample.cpp -lrindowmatlib -lm
+```
\ No newline at end of file
diff --git a/cmake/Packing.cmake b/cmake/Packing.cmake
index b635fe1..108dcfb 100644
--- a/cmake/Packing.cmake
+++ b/cmake/Packing.cmake
@@ -50,6 +50,8 @@ if(MSVC)
   set(CPACK_GENERATOR "ZIP")
   set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
   set(CPACK_PACKAGING_INSTALL_PREFIX ".")
+elseif(APPLE)
+    set(CPACK_GENERATOR "TGZ")
 elseif(UNIX)
   set(CPACK_GENERATOR "DEB")
 endif()
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bcc13be..75fd591 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -21,6 +21,25 @@ add_library(rindowmatlib SHARED ${srcfiles})
 target_compile_options(rindowmatlib PRIVATE -DRINDOW_COMPILING_DLL)
 if (MSVC)
     target_compile_options(rindowmatlib PRIVATE /openmp:experimental)
+    
+elseif(APPLE)
+    if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+        set(OpenMP_C "${CMAKE_C_COMPILER}" CACHE STRING "" FORCE)
+        set(OpenMP_C_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument" CACHE STRING "" FORCE)
+        set(OpenMP_C_LIB_NAMES "libomp" "libgomp" "libiomp5" CACHE STRING "" FORCE)
+        set(OpenMP_libomp_LIBRARY ${OpenMP_C_LIB_NAMES} CACHE STRING "" FORCE)
+        set(OpenMP_libgomp_LIBRARY ${OpenMP_C_LIB_NAMES} CACHE STRING "" FORCE)
+        set(OpenMP_libiomp5_LIBRARY ${OpenMP_C_LIB_NAMES} CACHE STRING "" FORCE)
+    endif()
+    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+      set(OpenMP_CXX "${CMAKE_CXX_COMPILER}" CACHE STRING "" FORCE)
+      set(OpenMP_CXX_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument" CACHE STRING "" FORCE)
+      set(OpenMP_CXX_LIB_NAMES "libomp" "libgomp" "libiomp5" CACHE STRING "" FORCE)
+      set(OpenMP_libomp_LIBRARY ${OpenMP_CXX_LIB_NAMES} CACHE STRING "" FORCE)
+      set(OpenMP_libgomp_LIBRARY ${OpenMP_CXX_LIB_NAMES} CACHE STRING "" FORCE)
+      set(OpenMP_libiomp5_LIBRARY ${OpenMP_CXX_LIB_NAMES} CACHE STRING "" FORCE)
+    endif()
+    
 elseif(UNIX)
     find_package(OpenMP REQUIRED)
     if(OpenMP_FOUND)
diff --git a/src/common.h b/src/common.h
index b8bcf8f..c6104b6 100644
--- a/src/common.h
+++ b/src/common.h
@@ -6,9 +6,12 @@
 #include <stdint.h>
 
 #ifdef _MSC_VER
-#include <windows.h>
+#include <windows.h> // For Windows
+#elif defined(__APPLE__)
+#include <sys/sysctl.h> // For macOS
+#include <mach/mach.h> // For macOS
 #else
-#include <sys/sysinfo.h>
+#include <sys/sysinfo.h> // For Linux and other Unix-like systems
 #endif
 #ifdef _OPENMP
 #include <omp.h>
@@ -16,12 +19,15 @@
 
 #include <stdlib.h>
 #ifndef _OPENMP
-    #ifdef _MSC_VER
-      #include <sysinfoapi.h>
-    #else
-      #include <sys/sysinfo.h>
-      #include <pthread.h>
-    #endif
+  #ifdef _MSC_VER
+    #include <sysinfoapi.h>  // Include Windows-specific header for system information
+  #elif defined(__APPLE__)
+    #include <sys/sysctl.h>  // Include sysctl.h for system information
+    #include <pthread.h>     // Include pthread.h for POSIX threads
+  #else
+    #include <sys/sysinfo.h>  // Include sysinfo.h for system information (Linux)
+    #include <pthread.h>      // Include pthread.h for POSIX threads
+  #endif
     #include <memory.h>
 #endif