diff --git a/.gitignore b/.gitignore
index a775725..2bde2c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,5 +8,6 @@ output
 *.sdf
 sdk/obj
 **/ipch
+build
 *.obj
-*.o
\ No newline at end of file
+*.o
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..99c6905
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,78 @@
+cmake_minimum_required(VERSION 3.18)
+project(rplidar_sdk)
+
+if (NOT UNIX)
+    message(FATAL_ERROR "Only support Unix, sorry.")
+endif()
+
+file(GLOB SRC_FILES
+sdk/src/*.cpp
+sdk/src/dataunpacker/*.cpp
+sdk/src/dataunpacker/unpacker/*.cpp
+sdk/src/hal/*.cpp)
+
+if(LINUX)
+file(GLOB EXTRA_SRC_FILES
+        sdk/src/arch/linux/*.cpp)
+else() # macOS
+    file(GLOB EXTRA_SRC_FILES
+        sdk/src/arch/macOS/*.cpp)
+endif()
+
+list (APPEND SRC_FILES ${EXTRA_SRC_FILES})
+
+add_library(rplidar_sdk STATIC 
+    ${SRC_FILES}
+)
+add_library(rplidar_sdk::rplidar_sdk ALIAS rplidar_sdk)
+
+target_include_directories(rplidar_sdk
+    PUBLIC
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/sdk/include>
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/sdk/src>
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/sdk/src/dataunpacker>
+        $<INSTALL_INTERFACE:include>
+        # $<INSTALL_INTERFACE:sdk/src>
+)
+
+file(GLOB PUBLIC_HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/sdk/include/*.h")
+install(FILES ${PUBLIC_HEADER_FILES}
+    DESTINATION include
+)
+
+install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/sdk/src/hal/types.h"
+    DESTINATION include/hal
+)
+
+install(TARGETS rplidar_sdk
+    EXPORT ${PROJECT_NAME}-targets
+)
+
+####################################################
+# Exports
+####################################################
+
+# This section is a boiler plate to ensure the targets are exported for use in other cmake projects via find_package
+# See https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html for more info on what's going on here
+
+include(CMakePackageConfigHelpers)
+
+# Create a *Config.cmake file using the *.cmake.in file
+configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in
+                              ${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake
+                              INSTALL_DESTINATION lib/cmake/${PROJECT_NAME}
+)
+
+# Install the *Config.cmake file we've just created
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake
+        DESTINATION lib/cmake/${PROJECT_NAME}/
+)
+
+# Install the targets exported by the earlier install commands
+# for use by the *Config.cmake generate above
+# This file is pulled in via the commands in the *Config.cmake.in template
+install(EXPORT ${PROJECT_NAME}-targets
+        FILE ${PROJECT_NAME}-targets.cmake
+        NAMESPACE ${PROJECT_NAME}::
+        DESTINATION lib/cmake/${PROJECT_NAME}
+)
\ No newline at end of file
diff --git a/app/custom_baudrate/main.cpp b/app/custom_baudrate/main.cpp
index f7789cf..65dea50 100644
--- a/app/custom_baudrate/main.cpp
+++ b/app/custom_baudrate/main.cpp
@@ -32,10 +32,8 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <signal.h>
 #include <string.h>
 
-#include "sl_lidar.h" 
 #include "sl_lidar_driver.h"
 #ifndef _countof
 #define _countof(_Array) (int)(sizeof(_Array) / sizeof(_Array[0]))
diff --git a/cmake/rplidar_sdkConfig.cmake.in b/cmake/rplidar_sdkConfig.cmake.in
new file mode 100644
index 0000000..a221835
--- /dev/null
+++ b/cmake/rplidar_sdkConfig.cmake.in
@@ -0,0 +1,5 @@
+@PACKAGE_INIT@
+
+include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake)
+
+check_required_components(@PROJECT_NAME@)
\ No newline at end of file
diff --git a/sdk/src/hal/event.h b/sdk/src/hal/event.h
index ada15a5..b558924 100644
--- a/sdk/src/hal/event.h
+++ b/sdk/src/hal/event.h
@@ -59,7 +59,7 @@ class Event
 #else
         pthread_mutex_init(&_cond_locker, NULL);
         pthread_condattr_init(&_cond_attr);
-#ifdef _MACOS
+#ifdef __APPLE__
         // sadly, there is no monotonic clock support for pthread cond variable on MACOS
         // if time slew is a big issue, try to reimplement it using kqueue/kevent
 #else
diff --git a/sdk/src/hal/locker.h b/sdk/src/hal/locker.h
index 2a18e6b..184f598 100644
--- a/sdk/src/hal/locker.h
+++ b/sdk/src/hal/locker.h
@@ -71,7 +71,7 @@ class Locker
         }
 
 #else
-#ifdef _MACOS
+#ifdef __APPLE__
         if (timeout !=0 ) {
             if (pthread_mutex_lock(&_lock) == 0) return LOCK_OK;
         }
@@ -84,7 +84,7 @@ class Locker
         {
             if (pthread_mutex_trylock(&_lock) == 0) return LOCK_OK;
         }
-#ifndef _MACOS
+#ifndef __APPLE__
         else
         {
             timespec wait_time;
diff --git a/sdk/src/hal/thread.cpp b/sdk/src/hal/thread.cpp
index bc68dd5..c6b3bf1 100644
--- a/sdk/src/hal/thread.cpp
+++ b/sdk/src/hal/thread.cpp
@@ -37,7 +37,7 @@
 
 #if defined(_WIN32)
 #include "arch/win32/winthread.hpp"
-#elif defined(_MACOS)
+#elif defined(__APPLE__)
 #include "arch/macOS/thread.hpp"
 #elif defined(__GNUC__)
 #include "arch/linux/thread.hpp"
diff --git a/sdk/src/sdkcommon.h b/sdk/src/sdkcommon.h
index f928b42..6ecf80c 100644
--- a/sdk/src/sdkcommon.h
+++ b/sdk/src/sdkcommon.h
@@ -35,7 +35,7 @@
 #if defined(_WIN32)
 
 #include "arch/win32/arch_win32.h"
-#elif defined(_MACOS)
+#elif defined(__APPLE__)
 #include "arch/macOS/arch_macOS.h"
 #elif defined(__GNUC__)
 #include "arch/linux/arch_linux.h"