include(FindClangTidy) include(GetArchitecture) # 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}") endmacro () # Implements the dynamically linked version of zeek_add_plugin. function (zeek_add_dynamic_plugin ns name) # Sanity check: need ZEEK_PLUGIN_SCRIPTS_PATH. if (NOT EXISTS "${ZEEK_PLUGIN_SCRIPTS_PATH}") message( FATAL_ERROR "Cannot build dynamic plugins: ZEEK_PLUGIN_SCRIPTS_PATH is undefined or invalid") endif () # Helper variables. zeek_get_dynamic_plugin_target(target_name ${ns} ${name}) set(full_name "${ns}::${name}") set(canon_name "${ns}_${name}") set(base_dir "${CMAKE_CURRENT_BINARY_DIR}") set(lib_dir "${base_dir}/lib") set(bif_dir "${lib_dir}/bif") set(readme "${base_dir}/README") set(scripts_bin "${base_dir}/scripts") set(scripts_src "${CMAKE_CURRENT_SOURCE_DIR}/scripts") # Create the target if no begin function has been used. if (NOT TARGET ${target_name}) add_library(${target_name} MODULE) target_compile_features(${target_name} PRIVATE cxx_std_17) set_target_properties(${target_name} PROPERTIES CXX_EXTENSIONS OFF) 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( ${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${lib_dir}" PREFIX "" LIBRARY_OUTPUT_NAME "${ns}-${name}.${HOST_ARCHITECTURE}") # Parse arguments (note: DIST_FILES and SCRIPT_FILES are ignored in static builds). set(fn_varargs INCLUDE_DIRS DEPENDENCIES SOURCES BIFS DIST_FILES SCRIPT_FILES PAC) cmake_parse_arguments(FN_ARGS "" "" "${fn_varargs}" ${ARGN}) # Take care of compiling BIFs. if (FN_ARGS_BIFS) # Generate the targets and add the .cc files. foreach (bif ${FN_ARGS_BIFS}) bif_target(${bif} "plugin" ${full_name} ${canon_name} OFF) target_sources(${target_name} PRIVATE ${BIF_OUTPUT_CC}) endforeach () # Generate __load__.zeek when building the plugin outside of Zeek. if (ZEEK_PLUGIN_INTERNAL_BUILD) set(loader_target ${target_name}_bif_loader) bro_bif_create_loader(${loader_target} ${FN_ARGS_BIFS}) add_dependencies(${target_name} ${loader_target}) else () set(load_script "${bif_dir}/__load__.zeek") file(WRITE ${load_script} "# Warning, this is an autogenerated file!\n") foreach (bif ${FN_ARGS_BIFS}) get_filename_component(file_name ${bif} NAME) file(APPEND ${load_script} "@load ./${file_name}.zeek\n") endforeach () endif () endif () # Take care of PAC files. zeek_next_pac_block(at_end pacInputs pacRemainder ${ARGN}) while (NOT at_end) binpac_target(${pacInputs}) target_sources(${target_name} PRIVATE ${BINPAC_OUTPUT_CC}) zeek_next_pac_block(at_end pacInputs pacRemainder ${pacRemainder}) endwhile () # Add user-defined extra include directories. if (FN_ARGS_INCLUDE_DIRS) target_include_directories(${target_name} PRIVATE ${FN_ARGS_INCLUDE_DIRS}) endif () # Add user-defined extra dependencies. if (FN_ARGS_DEPENDENCIES) target_link_libraries(${target_name} PUBLIC ${FN_ARGS_DEPENDENCIES}) endif () # Add the sources for the plugin. if (FN_ARGS_SOURCES) target_sources(${target_name} PRIVATE ${FN_ARGS_SOURCES}) endif () # Add extra dependencies when compiling with MSVC. if (MSVC) target_link_libraries(${target_name} ws2_32) endif () # Pass compiler flags, paths and dependencies to the target. target_link_libraries(${target_name} PRIVATE Zeek::DynamicPluginBase) target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # Per convention, plugins have their headers and sources under src/ and # legacy/external plugins expect this to auto-magically be available as # include path. if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src) target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) endif () # Link scripts into the build directory (if present). if (IS_DIRECTORY "${scripts_src}") set(symlink_target ${target_name}_symlink) add_custom_target(${symlink_target} COMMAND "${CMAKE_COMMAND}" -E create_symlink "${scripts_src}" "${scripts_bin}") add_dependencies(${target_name} ${symlink_target}) endif () # Add BinPAC_INCLUDE_DIR for picking up paths from FindBinPAC.cmake. if (BinPAC_INCLUDE_DIR) target_include_directories(${target_name} PRIVATE ${BinPAC_INCLUDE_DIR}) endif () # Write the 'magic' __zeek_plugin__ file. We can do that once during CMake # invocation since it won't change. file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/__zeek_plugin__" "${full_name}\n") # Stop here unless building 3rd party plugins. if (ZEEK_PLUGIN_INTERNAL_BUILD) return() endif () # Plugins may set BRO_PLUGIN_INSTALL_ROOT to override the default # installation directory. Otherwise, we use ZEEK_PLUGIN_DIR from Zeek. if (BRO_PLUGIN_INSTALL_ROOT) set(install_dir "${BRO_PLUGIN_INSTALL_ROOT}") else () set(install_dir ${ZEEK_PLUGIN_DIR}) endif () # Create the binary install package. set(dist_tarball_dir ${CMAKE_CURRENT_BINARY_DIR}/dist/${canon_name}) set(dist_tarball_name ${canon_name}.tgz) set(dist_tarball_path ${CMAKE_CURRENT_BINARY_DIR}/${dist_tarball_name}) message(STATUS "Install prefix for plugin ${canon_name}: ${install_dir}") message(STATUS "Tarball path for plugin ${canon_name}: ${dist_tarball_path}") add_custom_command(OUTPUT ${dist_tarball_path} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Building binary plugin package: ${dist_tarball_path}") # Handle dist files: Pre-place user provided dist files into the # directory that zeek-plugin-create-package.sh will tar up. Previously, # the zeek-plugin-create-package.sh script had done this itself. # # This computes the relative path of individual DIST_FILES to the # PROJECT_SOURCE_DIR (last project() invocation) and uses the # resulting path in the tarball. foreach (df ${FN_ARGS_DIST_FILES}) get_filename_component(df_src "${df}" ABSOLUTE) if (NOT EXISTS "${df_src}") # This was silently ignored previously. message(WARNING "The file ${df} (${df_src}) given to DIST_FILES does not exist") continue() endif () file(RELATIVE_PATH df_dist ${PROJECT_SOURCE_DIR} ${df_src}) add_custom_command( OUTPUT ${dist_tarball_path} COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${df} ${dist_tarball_dir}/${df_dist} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${df} APPEND) endforeach () add_custom_command( OUTPUT ${dist_tarball_path} COMMAND ${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) add_custom_target(${target_name}_tarball ALL DEPENDS ${dist_tarball_path}) # 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 )") endfunction ()