dependencies: add msgpack

DHTNet currently doesn't compile on some platforms (including Debian 12,
Ubuntu 23.10 and openSUSE Leap 15.5) because the version of msgpack
available via their package manager doesn't support (un)packing data of
type std::chrono::time_point.

Change-Id: I3166edf3992325bb7ce88030b5cc09f31cba4ead
diff --git a/.gitmodules b/.gitmodules
index 887b3b1..1586f9b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,6 @@
 [submodule "dependencies/restinio"]
 	path = dependencies/restinio
 	url = https://github.com/aberaud/restinio
+[submodule "dependencies/msgpack"]
+	path = dependencies/msgpack
+	url = https://github.com/msgpack/msgpack-c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e71ca35..deda8b7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,12 +40,30 @@
 endif()
 
 if (NOT MSVC)
+    # Check if there's a recent enough version of msgpack installed on the system
+    find_package(msgpack 5.0.0 QUIET CONFIG NAMES msgpack msgpackc-cxx)
+    if (msgpack_FOUND)
+        set(MSGPACK_TARGET "msgpackc-cxx")
+    else()
+        find_package(msgpack 5.0.0 QUIET CONFIG NAMES msgpack-cxx)
+        if (msgpack_FOUND)
+            set(MSGPACK_TARGET "msgpack-cxx")
+        endif()
+    endif()
+    # If no suitable version of msgpack was found, build the one
+    # included as a submodule in the dependencies folder
+    if (NOT msgpack_FOUND)
+        set(DEPENDENCIES_BUILD_ARGS "--build-msgpack")
+    else()
+        set(DEPENDENCIES_BUILD_ARGS "")
+    endif()
+
     set(DEPENDENCIES_PATH ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/install/${TARGET})
     message("dependencies path: ${DEPENDENCIES_PATH}")
     if (BUILD_DEPENDENCIES)
         find_package(Python3 COMPONENTS Interpreter)
         execute_process(
-            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/build.py
+            COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/build.py ${DEPENDENCIES_BUILD_ARGS}
             WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dependencies
             RESULT_VARIABLE BUILD_RESULT
         )
@@ -62,17 +80,6 @@
         list(APPEND PKG_CONFIG_EXECUTABLE "--static")
     endif()
 
-    check_include_file_cxx(msgpack.hpp HAVE_MSGPACKCXX)
-    if (NOT HAVE_MSGPACKCXX)
-        find_package(msgpack QUIET CONFIG NAMES msgpack msgpackc-cxx)
-        if (NOT msgpack_FOUND)
-            find_package(msgpack REQUIRED CONFIG NAMES msgpack-cxx)
-            set(MSGPACK_TARGET "msgpack-cxx")
-        else()
-            set(MSGPACK_TARGET "msgpackc-cxx")
-        endif()
-    endif()
-
     if (BUILD_TOOLS)
         find_package(yaml-cpp REQUIRED)
     endif()
@@ -241,7 +248,7 @@
         ${WIN32_DEP_DIR}/../msvc/lib/libfmt.lib
         ${WIN32_DEP_DIR}/../msvc/lib/libmsgpackc-cxx.lib)
 endif()
-if (NOT HAVE_MSGPACKCXX)
+if (msgpack_FOUND)
     target_link_libraries(dhtnet PUBLIC ${MSGPACK_TARGET})
 endif()
 if (APPLE)
diff --git a/dependencies/build.py b/dependencies/build.py
index e3c3499..6321e2f 100755
--- a/dependencies/build.py
+++ b/dependencies/build.py
@@ -17,6 +17,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 
+import argparse
 import subprocess
 import os
 
@@ -24,6 +25,7 @@
 opendht_dir = "opendht"
 pjproject_dir = "pjproject"
 restinio_dir = "restinio"
+msgpack_dir = "msgpack"
 install_dir = os.path.abspath("install")
 
 def build_and_install_restinio():
@@ -120,7 +122,33 @@
         print("Error building PJSIP libraries: %s", e)
         return False
 
+def build_and_install_msgpack():
+    print("\nBuilding and installing msgpack...", flush=True)
+    try:
+        msgpack_build_dir = os.path.join(msgpack_dir, "build")
+        cmake_command = [
+            "cmake", "..",
+            "-DCMAKE_INSTALL_PREFIX=" + install_dir,
+            "-DCMAKE_BUILD_TYPE=Release",
+            "-DMSGPACK_CXX17=ON",
+            "-DMSGPACK_USE_BOOST=OFF",
+            "-DMSGPACK_BUILD_EXAMPLES=OFF",
+        ]
+        os.makedirs(msgpack_build_dir, exist_ok=True)
+        subprocess.run(cmake_command, cwd=msgpack_build_dir, check=True)
+        subprocess.run(["make", "install"], cwd=msgpack_build_dir, check=True)
+        print("msgpack installed successfully.")
+        return True
+    except (subprocess.CalledProcessError, OSError) as e:
+        print("Error building or installing msgpack:", e)
+        return False
+
 def main():
+    # Parse arguments
+    parser = argparse.ArgumentParser(description="DHTNet dependencies build script")
+    parser.add_argument('--build-msgpack', default=False, action='store_true')
+    args = parser.parse_args()
+
     # Create install directory if it doesn't exist
     if not os.path.exists(install_dir):
         os.makedirs(install_dir)
@@ -129,6 +157,12 @@
         print("Error building or installing restinio.")
         return
 
+    # Build and install msgpack if necessary
+    if args.build_msgpack:
+        if not build_and_install_msgpack():
+            print("Error building or installing msgpack.")
+            return
+
     # Build and install OpenDHT
     if not build_and_install_opendht():
         print("Error building or installing OpenDHT.")
diff --git a/dependencies/msgpack b/dependencies/msgpack
new file mode 160000
index 0000000..44c0f70
--- /dev/null
+++ b/dependencies/msgpack
@@ -0,0 +1 @@
+Subproject commit 44c0f705c9a60217d7e07de844fb13ce4c1c1e6e