diff --git a/CMakeLists.txt b/CMakeLists.txt index 2081d5fc..95586a10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,8 +109,10 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") add_compile_options(-O3) endif() elseif(MSVC) - add_compile_options(/W4 /WX) -endif() + add_compile_options(/W3) + add_compile_definitions(NOMINMAX) + add_compile_definitions(WIN32_LEAN_AND_MEAN) + endif() # Memory sanitizer options for debugging option(ENABLE_ASAN "Enable AddressSanitizer for memory error detection" OFF) @@ -224,7 +226,10 @@ if(MCP_USE_LLHTTP) ) message(STATUS "Downloading llhttp... This may take a moment depending on your connection speed.") - FetchContent_MakeAvailable(llhttp) + FetchContent_GetProperties(llhttp) + if(NOT llhttp_POPULATED) + FetchContent_Populate(llhttp) + endif() message(STATUS "llhttp download complete.") # Build llhttp as a simple static library @@ -232,15 +237,15 @@ if(MCP_USE_LLHTTP) file(GLOB LLHTTP_SOURCES ${llhttp_SOURCE_DIR}/src/*.c) if(NOT TARGET llhttp) - add_library(llhttp STATIC ${LLHTTP_SOURCES}) - target_include_directories(llhttp PUBLIC ${llhttp_SOURCE_DIR}/include) + add_library(llhttp STATIC ${LLHTTP_SOURCES}) + target_include_directories(llhttp PUBLIC ${llhttp_SOURCE_DIR}/include) - # Enable position-independent code for shared library linking - set_target_properties(llhttp PROPERTIES POSITION_INDEPENDENT_CODE ON) + # Enable position-independent code for shared library linking + set_target_properties(llhttp PROPERTIES POSITION_INDEPENDENT_CODE ON) - # Disable warnings for third-party code - if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_compile_options(llhttp PRIVATE -w) + # Disable warnings for third-party code + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(llhttp PRIVATE -w) endif() endif() @@ -529,8 +534,12 @@ set(MCP_SDK_SOURCES ${MCP_CORE_SOURCES} ${MCP_CLIENT_SERVER_SOURCES} ${MCP_EVENT if(BUILD_STATIC_LIBS) add_library(gopher-mcp-static STATIC ${MCP_SDK_SOURCES} ${MCP_HTTP_SOURCES}) + if(WIN32) + set_target_properties(gopher-mcp-static PROPERTIES OUTPUT_NAME gopher-mcp-static) + else() + set_target_properties(gopher-mcp-static PROPERTIES OUTPUT_NAME gopher-mcp) + endif() set_target_properties(gopher-mcp-static PROPERTIES - OUTPUT_NAME gopher-mcp POSITION_INDEPENDENT_CODE ON VERSION ${GOPHER_MCP_VERSION} SOVERSION ${GOPHER_MCP_VERSION_MAJOR} @@ -705,8 +714,12 @@ endif() # Create Gopher MCP Echo Advanced libraries if(BUILD_STATIC_LIBS) add_library(gopher-mcp-echo-advanced-static STATIC ${MCP_ECHO_ADVANCED_SOURCES}) + if(WIN32) + set_target_properties(gopher-mcp-echo-advanced-static PROPERTIES OUTPUT_NAME gopher-mcp-echo-advanced-static) + else() + set_target_properties(gopher-mcp-echo-advanced-static PROPERTIES OUTPUT_NAME gopher-mcp-echo-advanced) + endif() set_target_properties(gopher-mcp-echo-advanced-static PROPERTIES - OUTPUT_NAME gopher-mcp-echo-advanced POSITION_INDEPENDENT_CODE ON ) endif() @@ -717,6 +730,7 @@ if(BUILD_SHARED_LIBS) VERSION ${GOPHER_MCP_VERSION} SOVERSION ${GOPHER_MCP_VERSION_MAJOR} POSITION_INDEPENDENT_CODE ON + WINDOWS_EXPORT_ALL_SYMBOLS ON ) else() add_library(gopher-mcp-echo-advanced ALIAS gopher-mcp-echo-advanced-static) @@ -782,8 +796,12 @@ endforeach() # Create Gopher MCP Event libraries if(BUILD_STATIC_LIBS) add_library(gopher-mcp-event-static STATIC ${MCP_EVENT_SOURCES}) + if(WIN32) + set_target_properties(gopher-mcp-event-static PROPERTIES OUTPUT_NAME gopher-mcp-event-static) + else() + set_target_properties(gopher-mcp-event-static PROPERTIES OUTPUT_NAME gopher-mcp-event) + endif() set_target_properties(gopher-mcp-event-static PROPERTIES - OUTPUT_NAME gopher-mcp-event POSITION_INDEPENDENT_CODE ON ) endif() @@ -794,6 +812,7 @@ if(BUILD_SHARED_LIBS) VERSION ${GOPHER_MCP_VERSION} SOVERSION ${GOPHER_MCP_VERSION_MAJOR} POSITION_INDEPENDENT_CODE ON + WINDOWS_EXPORT_ALL_SYMBOLS ON ) else() add_library(gopher-mcp-event ALIAS gopher-mcp-event-static) @@ -861,6 +880,9 @@ foreach(lib_target ${EVENT_REAL_TARGETS}) target_link_directories(${lib_target} PUBLIC ${LIBEVENT_LIBRARY_DIRS}) endif() target_link_libraries(${lib_target} PUBLIC ${LIBEVENT_LIBRARIES}) + if(WIN32) + target_link_libraries(${lib_target} PUBLIC ws2_32) + endif() endif() # Add Windows-specific socket libraries for event library diff --git a/examples/mcp/mcp_example_server.cc b/examples/mcp/mcp_example_server.cc index 7e82a2c3..5aa1c3d3 100644 --- a/examples/mcp/mcp_example_server.cc +++ b/examples/mcp/mcp_example_server.cc @@ -181,6 +181,8 @@ void setupLogging(bool verbose) { #ifdef _WIN32 // Windows Console Control Handler BOOL WINAPI ConsoleCtrlHandler(DWORD ctrlType) { + static std::atomic signal_count(0); + switch (ctrlType) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: @@ -196,7 +198,6 @@ BOOL WINAPI ConsoleCtrlHandler(DWORD ctrlType) { g_shutdown_cv.notify_all(); // For safety, if we receive multiple signals, force exit - static std::atomic signal_count(0); signal_count++; if (signal_count > 1) { std::cerr << "\n[INFO] Force shutdown after multiple signals..." diff --git a/include/mcp/buffer.h b/include/mcp/buffer.h index 50951293..57f88797 100644 --- a/include/mcp/buffer.h +++ b/include/mcp/buffer.h @@ -13,6 +13,12 @@ #include "mcp/core/compat.h" +// msvc does not define ssize_t by default +#if defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + namespace mcp { // Forward declarations diff --git a/include/mcp/event/libevent_dispatcher.h b/include/mcp/event/libevent_dispatcher.h index d0a56ce5..a9baa481 100644 --- a/include/mcp/event/libevent_dispatcher.h +++ b/include/mcp/event/libevent_dispatcher.h @@ -16,7 +16,7 @@ namespace mcp { namespace event { // Rename to avoid conflict with struct event -using libevent_event = struct event; +using libevent_event = struct ::event; // Use libevent's socket type for callback signature compatibility. // On Windows, libevent uses intptr_t (SOCKET), on POSIX it uses int. diff --git a/include/mcp/filter/request_logger_filter.h b/include/mcp/filter/request_logger_filter.h index bbc7b123..dd9a99fd 100644 --- a/include/mcp/filter/request_logger_filter.h +++ b/include/mcp/filter/request_logger_filter.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "mcp/core/compat.h" #include "mcp/json/json_serialization.h" diff --git a/include/mcp/logging/log_message.h b/include/mcp/logging/log_message.h index 2a8e0640..31dac2ee 100644 --- a/include/mcp/logging/log_message.h +++ b/include/mcp/logging/log_message.h @@ -5,10 +5,10 @@ #include #include -// Platform-specific process ID header -#ifdef _WIN32 +#if defined(_WIN32) #include -#define getpid _getpid +using pid_t = int; +inline pid_t getpid() { return _getpid(); } #else #include #endif diff --git a/include/mcp/network/address.h b/include/mcp/network/address.h index be18397b..0b4b8aba 100644 --- a/include/mcp/network/address.h +++ b/include/mcp/network/address.h @@ -17,6 +17,10 @@ #define _SOCKLEN_T_DEFINED typedef int socklen_t; #endif +#ifndef _MODE_T_DEFINED +#define _MODE_T_DEFINED +typedef int mode_t; +#endif // mode_t and other POSIX types are defined in mcp/core/compat.h #else #include diff --git a/src/c_api/CMakeLists.txt b/src/c_api/CMakeLists.txt index a40885c9..c9f263ac 100644 --- a/src/c_api/CMakeLists.txt +++ b/src/c_api/CMakeLists.txt @@ -184,11 +184,14 @@ option(BUILD_C_API_STATIC "Build static C API library" ON) if(BUILD_C_API_STATIC) add_library(gopher_mcp_c_static STATIC ${MCP_C_API_SOURCES}) - - set_target_properties(gopher_mcp_c_static PROPERTIES - OUTPUT_NAME gopher_mcp_c - POSITION_INDEPENDENT_CODE ON - ) + if(WIN32) + set_target_properties(gopher_mcp_c_static PROPERTIES OUTPUT_NAME gopher_mcp_c_static-static) + else() + set_target_properties(gopher_mcp_c_static PROPERTIES OUTPUT_NAME gopher_mcp_c_static) + endif() + set_target_properties(gopher_mcp_c_static PROPERTIES + POSITION_INDEPENDENT_CODE ON + ) target_include_directories(gopher_mcp_c_static PUBLIC diff --git a/src/config/file_config_source.cc b/src/config/file_config_source.cc index 941e290d..08adf121 100644 --- a/src/config/file_config_source.cc +++ b/src/config/file_config_source.cc @@ -49,6 +49,7 @@ // Platform-specific includes #ifdef _WIN32 #include +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif namespace mcp { diff --git a/src/echo/echo_stdio_transport_advanced.cc b/src/echo/echo_stdio_transport_advanced.cc index 173fedb3..e46608c1 100644 --- a/src/echo/echo_stdio_transport_advanced.cc +++ b/src/echo/echo_stdio_transport_advanced.cc @@ -12,6 +12,7 @@ #ifdef _WIN32 #include #include +typedef SSIZE_T ssize_t; #define read(fd, buf, len) _read(fd, buf, static_cast(len)) #define write(fd, buf, len) _write(fd, buf, static_cast(len)) #ifndef STDIN_FILENO diff --git a/src/logging/CMakeLists.txt b/src/logging/CMakeLists.txt index d485c740..bf1762ea 100644 --- a/src/logging/CMakeLists.txt +++ b/src/logging/CMakeLists.txt @@ -13,10 +13,14 @@ set(MCP_LOGGING_SOURCES # Create static library add_library(gopher-mcp-logging-static STATIC ${MCP_LOGGING_SOURCES}) -set_target_properties(gopher-mcp-logging-static PROPERTIES - OUTPUT_NAME gopher-mcp-logging - POSITION_INDEPENDENT_CODE ON -) + if(WIN32) + set_target_properties(gopher-mcp-logging-static PROPERTIES OUTPUT_NAME gopher-mcp-logging-static) + else() + set_target_properties(gopher-mcp-logging-static PROPERTIES OUTPUT_NAME gopher-mcp-logging) + endif() + set_target_properties(gopher-mcp-logging-static PROPERTIES + POSITION_INDEPENDENT_CODE ON + ) target_include_directories(gopher-mcp-logging-static PUBLIC $ @@ -47,7 +51,7 @@ target_compile_definitions(gopher-mcp-logging-static PUBLIC # Create shared library if(BUILD_SHARED_LIBS) add_library(gopher-mcp-logging SHARED ${MCP_LOGGING_SOURCES}) - + target_include_directories(gopher-mcp-logging PUBLIC $ $ @@ -63,6 +67,10 @@ if(BUILD_SHARED_LIBS) target_compile_definitions(gopher-mcp-logging PUBLIC $<$:MCP_DEBUG_LOGGING> ) + + set_target_properties(gopher-mcp-logging PROPERTIES + WINDOWS_EXPORT_ALL_SYMBOLS ON + ) else() add_library(gopher-mcp-logging ALIAS gopher-mcp-logging-static) endif() diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 00000000..c54e99cc --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,6 @@ +{ + "dependencies": [ + "libevent", + "openssl" + ] +}