From 9421dabe02fd9c1c376c2517e41d36d4cc8191a2 Mon Sep 17 00:00:00 2001 From: Maor Hamami Date: Mon, 23 Mar 2026 19:20:10 +0200 Subject: [PATCH 1/2] [windows] Fix building dynamic plugins --- GetArchitecture.cmake | 12 ++++- ZeekPlugin.cmake | 14 +++++- ZeekPluginDynamic.cmake | 83 ++++++++++++++++++++++++++++++++--- zeek-plugin-create-package.sh | 2 +- 4 files changed, 100 insertions(+), 11 deletions(-) diff --git a/GetArchitecture.cmake b/GetArchitecture.cmake index a33b8c6..215a07c 100644 --- a/GetArchitecture.cmake +++ b/GetArchitecture.cmake @@ -2,6 +2,16 @@ # We run uname ourselves here as CMAKE by default uses -p rather than # -m. -execute_process(COMMAND uname -m OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE) +if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + # On Windows, uname may not be available; use CMake's built-in variable. + # Normalize AMD64 to x86_64 for consistency with uname -m used by + # external plugin builds running under Git Bash. + set(arch "${CMAKE_HOST_SYSTEM_PROCESSOR}") + if (arch STREQUAL "AMD64") + set(arch "x86_64") + endif () +else () + execute_process(COMMAND uname -m OUTPUT_VARIABLE arch OUTPUT_STRIP_TRAILING_WHITESPACE) +endif () set(HOST_ARCHITECTURE "${CMAKE_SYSTEM_NAME}-${arch}") string(TOLOWER ${HOST_ARCHITECTURE} HOST_ARCHITECTURE) diff --git a/ZeekPlugin.cmake b/ZeekPlugin.cmake index ec121d3..43d44ff 100644 --- a/ZeekPlugin.cmake +++ b/ZeekPlugin.cmake @@ -12,6 +12,15 @@ function (zeek_plugin_bootstrapping) set(_zeek_build_dir "$ENV{ZEEK_BUILD_DIR}") endif () find_package(Zeek REQUIRED CONFIG NO_DEFAULT_PATH PATHS "${_zeek_build_dir}") + + # Match the plugin build type to Zeek's. This ensures plugins link + # against the same CRT and are ABI-compatible with the Zeek binary. + if (ZEEK_CMAKE_BUILD_TYPE) + message(STATUS "Setting plugin CMAKE_BUILD_TYPE to ${ZEEK_CMAKE_BUILD_TYPE}") + set(CMAKE_BUILD_TYPE "${ZEEK_CMAKE_BUILD_TYPE}" + CACHE STRING "Configures the CMAKE_BUILD_TYPE for the plugin." FORCE) + endif () + return() endif () # When building plugins against an installed Zeek, this file must be installed @@ -59,8 +68,9 @@ function (zeek_plugin_bootstrapping) set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE PATH "Configures whether to write a compile database." FORCE) - # When CMAKE_BUILD_TYPE is not set, use the one from Zeek. - if (NOT CMAKE_BUILD_TYPE) + # Match the plugin build type to Zeek's. This ensures plugins link against + # the same CRT and are ABI-compatible with the Zeek binary. + if (ZEEK_CMAKE_BUILD_TYPE) message(STATUS "Setting plugin CMAKE_BUILD_TYPE to ${ZEEK_CMAKE_BUILD_TYPE}") set(CMAKE_BUILD_TYPE "${ZEEK_CMAKE_BUILD_TYPE}" CACHE STRING "Configures the CMAKE_BUILD_TYPE for the plugin." FORCE) diff --git a/ZeekPluginDynamic.cmake b/ZeekPluginDynamic.cmake index 24b0940..53e18d4 100644 --- a/ZeekPluginDynamic.cmake +++ b/ZeekPluginDynamic.cmake @@ -1,6 +1,19 @@ include(GetArchitecture) include(RequireCXXStd) +# On Windows, shell scripts (.sh) need to be invoked through bash. +if (WIN32 AND NOT ZEEK_PLUGIN_SHELL_PREFIX) + find_program(_bash_exe bash) + if (_bash_exe) + set(ZEEK_PLUGIN_SHELL_PREFIX "${_bash_exe}" CACHE INTERNAL "Shell prefix for .sh scripts") + else () + set(ZEEK_PLUGIN_SHELL_PREFIX "" CACHE INTERNAL "Shell prefix for .sh scripts") + endif () +endif () +if (NOT DEFINED ZEEK_PLUGIN_SHELL_PREFIX) + set(ZEEK_PLUGIN_SHELL_PREFIX "" CACHE INTERNAL "Shell prefix for .sh scripts") +endif () + # Sets `target` to contain the CMake target name for a dynamic plugin. macro (zeek_get_dynamic_plugin_target target ns name) set(${target} "${ns}_${name}") @@ -34,6 +47,32 @@ function (zeek_add_dynamic_plugin ns name) set_target_properties(${target_name} PROPERTIES CXX_EXTENSIONS OFF) endif () + # On MSVC with static CRT, each DLL has its own stdout buffer. + # Generate a DllMain that disables stdout buffering so plugin + # printf output appears in correct order when stdout is redirected. + if (MSVC) + set(_dllmain_src "${CMAKE_CURRENT_BINARY_DIR}/zeek_plugin_dllmain.cc") + if (NOT EXISTS "${_dllmain_src}") + file( + WRITE "${_dllmain_src}" + "#include \n" + "// With static CRT (/MT), each DLL has its own stdout.\n" + "// Set it to unbuffered so output is correctly ordered,\n" + "// and close it at shutdown to prevent the DLL CRT's\n" + "// atexit handler from corrupting the shared fd.\n" + "namespace { struct ZeekPluginStdoutInit {\n" + " ZeekPluginStdoutInit() {\n" + " setvbuf(stdout, nullptr, _IONBF, 0);\n" + " }\n" + " ~ZeekPluginStdoutInit() {\n" + " fclose(stdout);\n" + " fclose(stderr);\n" + " }\n" + "} zeek_plugin_stdout_init; }\n") + endif () + target_sources(${target_name} PRIVATE "${_dllmain_src}") + endif () + # Place library file into the 'lib' directory, drop default-generated file # prefix and override the default file name to include the architecture. set_target_properties( @@ -99,6 +138,20 @@ function (zeek_add_dynamic_plugin ns name) # Add extra dependencies when compiling with MSVC. if (MSVC) target_link_libraries(${target_name} PRIVATE ws2_32) + # Force the plugin DLL to import CRT allocation functions from + # zeek.exe. With /MT, each module has its own heap; importing + # operator new/delete ensures all allocations use the same heap, + # preventing cross-module heap mismatches when objects are created + # in plugin code and freed by zeek or vice versa. + target_link_options( + ${target_name} + PRIVATE + "/INCLUDE:??2@YAPEAX_K@Z" + "/INCLUDE:??_U@YAPEAX_K@Z" + "/INCLUDE:??3@YAXPEAX@Z" + "/INCLUDE:??3@YAXPEAX_K@Z" + "/INCLUDE:??_V@YAXPEAX@Z" + "/INCLUDE:??_V@YAXPEAX_K@Z") endif () # Pass compiler flags, paths and dependencies to the target. @@ -179,7 +232,8 @@ function (zeek_add_dynamic_plugin ns name) add_custom_command( OUTPUT ${dist_tarball_path} - COMMAND ${ZEEK_PLUGIN_SCRIPTS_PATH}/zeek-plugin-create-package.sh ${canon_name} + COMMAND ${ZEEK_PLUGIN_SHELL_PREFIX} + ${ZEEK_PLUGIN_SCRIPTS_PATH}/zeek-plugin-create-package.sh ${canon_name} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${target_name} ${FN_ARGS_SCRIPT_FILES} APPEND) @@ -188,10 +242,25 @@ function (zeek_add_dynamic_plugin ns name) # Tell CMake to install our tarball. Note: This usually runs from our # plugin-support skeleton. - install( - CODE "execute_process( - COMMAND ${ZEEK_PLUGIN_SCRIPTS_PATH}/zeek-plugin-install-package.sh ${canon_name} \$ENV{DESTDIR}/${install_dir} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND_ECHO STDOUT - )") + if (ZEEK_PLUGIN_SHELL_PREFIX) + install( + CODE " + if (DEFINED ENV{DESTDIR}) + set(_inst_dir \"\$ENV{DESTDIR}/${install_dir}\") + else () + set(_inst_dir \"${install_dir}\") + endif () + execute_process( + COMMAND \"${ZEEK_PLUGIN_SHELL_PREFIX}\" \"${ZEEK_PLUGIN_SCRIPTS_PATH}/zeek-plugin-install-package.sh\" ${canon_name} \"\${_inst_dir}\" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND_ECHO STDOUT + )") + else () + install( + CODE "execute_process( + COMMAND ${ZEEK_PLUGIN_SCRIPTS_PATH}/zeek-plugin-install-package.sh ${canon_name} \$ENV{DESTDIR}/${install_dir} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND_ECHO STDOUT + )") + endif () endfunction () diff --git a/zeek-plugin-create-package.sh b/zeek-plugin-create-package.sh index 12eb059..481ab34 100755 --- a/zeek-plugin-create-package.sh +++ b/zeek-plugin-create-package.sh @@ -28,4 +28,4 @@ tar czf "dist/${tgz}" -C dist "${name}" rm -rf "${DIST}" -ln -s "dist/${tgz}" "${name}.tgz" +ln -s "dist/${tgz}" "${name}.tgz" 2>/dev/null || cp "dist/${tgz}" "${name}.tgz" From 76c588a85e9c20aa3bb9f08d4adc2795bf91e583 Mon Sep 17 00:00:00 2001 From: Maor Hamami Date: Wed, 8 Apr 2026 22:24:50 +0300 Subject: [PATCH 2/2] code review changes --- ZeekPluginDynamic.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/ZeekPluginDynamic.cmake b/ZeekPluginDynamic.cmake index 53e18d4..52cc5bc 100644 --- a/ZeekPluginDynamic.cmake +++ b/ZeekPluginDynamic.cmake @@ -6,8 +6,6 @@ if (WIN32 AND NOT ZEEK_PLUGIN_SHELL_PREFIX) find_program(_bash_exe bash) if (_bash_exe) set(ZEEK_PLUGIN_SHELL_PREFIX "${_bash_exe}" CACHE INTERNAL "Shell prefix for .sh scripts") - else () - set(ZEEK_PLUGIN_SHELL_PREFIX "" CACHE INTERNAL "Shell prefix for .sh scripts") endif () endif () if (NOT DEFINED ZEEK_PLUGIN_SHELL_PREFIX)