diff --git a/CMakeLists.txt b/CMakeLists.txt index 24e74f6..ad3a7a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,36 @@ project(webots_controller LANGUAGES C CXX) option(WEBOTS_CONTROLLER_NO_PLUGINS "Disable runtime plugin loading (dlopen/LoadLibrary paths)." ON) +if(MSVC) + find_package(dirent CONFIG REQUIRED) + + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cmake") + file( + DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v0.40.8/CPM.cmake + "${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake" + EXPECTED_HASH + SHA256=78ba32abdf798bc616bab7c73aac32a17bbd7b06ad9e26a6add69de8f3ae4791) + include("${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake") + + CPMAddPackage( + NAME libunistd + GITHUB_REPOSITORY robinrowe/libunistd + GIT_TAG v1.4 + DOWNLOAD_ONLY YES) + + add_library(webots_controller_msvc_unix_headers INTERFACE) + target_include_directories( + webots_controller_msvc_unix_headers + SYSTEM + INTERFACE "$" + "${libunistd_SOURCE_DIR}/unistd") + target_link_libraries(webots_controller_msvc_unix_headers + INTERFACE dirent::dirent) + target_compile_definitions(webots_controller_msvc_unix_headers + INTERFACE _CRT_DECLARE_NONSTDC_NAMES=0) + target_compile_options(webots_controller_msvc_unix_headers + INTERFACE /FIunistd.h) +endif() + add_subdirectory(src/controller) diff --git a/conanfile.py b/conanfile.py index 30d2b1c..7ebd7b9 100644 --- a/conanfile.py +++ b/conanfile.py @@ -20,7 +20,7 @@ class WebotsControllerConan(ConanFile): "no_plugins": True, } - exports_sources = "CMakeLists.txt", "src/*", "include/*", "LICENSE", "README.md" + exports_sources = "CMakeLists.txt", "src/*", "include/*", "patches/*.patch", "LICENSE", "README.md" def config_options(self): if self.settings.os == "Windows": @@ -36,7 +36,8 @@ class WebotsControllerConan(ConanFile): def requirements(self): # self.requires("stb/cci.20240531") - pass + if self.settings.os == "Windows" and self.settings.compiler != "gcc": + self.requires("dirent/1.24") def layout(self): cmake_layout(self) diff --git a/lefthook.yml b/lefthook.yml index 97edf86..64bee8f 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -7,6 +7,8 @@ pre-commit: # clang-format: # run: uvx run-clang-format -i ./src ./include ./tests # stage_fixed: true + gitleaks: + run: gitleaks protect --staged --redact --no-banner # post-checkout: # commands: # inkr-skill-sync: diff --git a/patches/msvc-controller-c.patch b/patches/msvc-controller-c.patch new file mode 100644 index 0000000..7169405 --- /dev/null +++ b/patches/msvc-controller-c.patch @@ -0,0 +1,28 @@ +diff --git a/motion.c b/motion.c +index 02c5e62..3de3b2f 100644 +--- a/motion.c ++++ b/motion.c +@@ -45,7 +45,7 @@ typedef struct WbMotionStructPrivate { + extern void wb_motor_set_position_no_mutex(WbDeviceTag, double); + + static const int UNDEFINED_TIME = -1; +-static const int MAX_LINE = 4096; ++#define MAX_LINE 4096 + static const double UNDEFINED_POSITION = -9999999.9; + static WbMotionRef head = NULL; + static const char *HEADER = "#WEBOTS_MOTION"; +diff --git a/robot.c b/robot.c +index 6bb2b81..4d4cb6b 100644 +--- a/robot.c ++++ b/robot.c +@@ -65,6 +65,10 @@ + #include "supervisor_private.h" + #include "tcp_client.h" + ++#ifdef _WIN32 ++#undef wb_robot_init ++#endif ++ + #ifdef _WIN32 + #include // GetCommandLine + #else diff --git a/src/controller/c/CMakeLists.txt b/src/controller/c/CMakeLists.txt index 23b647e..7fc9a93 100644 --- a/src/controller/c/CMakeLists.txt +++ b/src/controller/c/CMakeLists.txt @@ -81,6 +81,30 @@ else() list(APPEND WEBOTS_CONTROLLER_C_SOURCES ${WEBOTS_CONTROLLER_C_PLUGIN_SOURCES}) endif() +if(MSVC) + find_package(Git REQUIRED) + set(WEBOTS_CONTROLLER_MSVC_SOURCE_DIR + "${CMAKE_CURRENT_BINARY_DIR}/msvc-patched-source") + file(REMOVE_RECURSE "${WEBOTS_CONTROLLER_MSVC_SOURCE_DIR}") + file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/" + DESTINATION "${WEBOTS_CONTROLLER_MSVC_SOURCE_DIR}") + file(RELATIVE_PATH WEBOTS_CONTROLLER_MSVC_SOURCE_RELATIVE_DIR + "${CMAKE_SOURCE_DIR}" "${WEBOTS_CONTROLLER_MSVC_SOURCE_DIR}") + execute_process( + COMMAND + "${GIT_EXECUTABLE}" apply + "--directory=${WEBOTS_CONTROLLER_MSVC_SOURCE_RELATIVE_DIR}" + "${CMAKE_SOURCE_DIR}/patches/msvc-controller-c.patch" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + RESULT_VARIABLE WEBOTS_CONTROLLER_MSVC_PATCH_RESULT) + if(NOT WEBOTS_CONTROLLER_MSVC_PATCH_RESULT EQUAL 0) + message(FATAL_ERROR "Failed to apply MSVC controller C source patch") + endif() + + list(TRANSFORM WEBOTS_CONTROLLER_C_SOURCES + PREPEND "${WEBOTS_CONTROLLER_MSVC_SOURCE_DIR}/") +endif() + # add_library without STATIC/SHARED follows BUILD_SHARED_LIBS automatically in # cmake. add_library(webots_controller ${WEBOTS_CONTROLLER_C_SOURCES}) @@ -112,12 +136,23 @@ if(WIN32) target_link_libraries(webots_controller PRIVATE ws2_32) endif() +if(MSVC) + target_sources(webots_controller + PRIVATE "${libunistd_SOURCE_DIR}/unistd/clock_gettime.cpp") + target_link_libraries(webots_controller + PRIVATE webots_controller_msvc_unix_headers) + target_compile_definitions(webots_controller PRIVATE _USE_MATH_DEFINES + O_TEXT=_O_TEXT) + target_compile_options(webots_controller PRIVATE /utf-8) +endif() + target_include_directories( webots_controller PUBLIC $ $ $ $ - PRIVATE ${WEBOTS_STB_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + PRIVATE ${WEBOTS_STB_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + ${WEBOTS_CONTROLLER_MSVC_SOURCE_DIR}) target_compile_definitions(webots_controller PRIVATE LIBCONTROLLER_VERSION="R2025a")