diff --git a/.gitignore b/.gitignore index 703cf9576a..ab7965c96e 100644 --- a/.gitignore +++ b/.gitignore @@ -134,7 +134,7 @@ CTestTestfile.cmake DartConfiguration.tcl LibeventConfig.cmake LibeventConfigVersion.cmake -LibeventTargets.cmake +LibeventTargets*.cmake bin/ cmake_install.cmake Uninstall.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c98b619adf..5b2537d5bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -943,19 +943,21 @@ configure_file( include(AddEventLibrary) add_event_library(event_core SOURCES ${SRC_CORE}) add_event_library(event_extra - LIBRARIES event_core_shared + INNER_LIBRARIES event_core SOURCES ${SRC_EXTRA}) if (NOT EVENT__DISABLE_OPENSSL) add_event_library(event_openssl - LIBRARIES event_core_shared ${OPENSSL_LIBRARIES} + INNER_LIBRARIES event_core + OUTER_INCLUDES ${OPENSSL_INCLUDE_DIR} + LIBRARIES ${OPENSSL_LIBRARIES} SOURCES ${SRC_OPENSSL}) endif() if (CMAKE_USE_PTHREADS_INIT) set(SRC_PTHREADS evthread_pthread.c) add_event_library(event_pthreads - LIBRARIES event_core_shared + INNER_LIBRARIES event_core SOURCES ${SRC_PTHREADS}) endif() @@ -1449,18 +1451,24 @@ endif() # Installation preparation. # -if(WIN32 AND NOT CYGWIN) - set(DEF_INSTALL_CMAKE_DIR cmake) -else() - set(DEF_INSTALL_CMAKE_DIR lib/cmake/libevent) -endif() - set(EVENT_INSTALL_CMAKE_DIR - "${CMAKE_INSTALL_PREFIX}/${DEF_INSTALL_CMAKE_DIR}" - CACHE PATH "Installation directory for CMake files") + "${CMAKE_INSTALL_PREFIX}/lib/cmake/libevent") export(PACKAGE libevent) +function(gen_package_config forinstall) + if(${forinstall}) + set(CONFIG_FOR_INSTALL_TREE 1) + set(dir "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}") + else() + set(CONFIG_FOR_INSTALL_TREE 0) + set(dir "${PROJECT_BINARY_DIR}") + endif() + configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfig.cmake.in + "${dir}/LibeventConfig.cmake" + @ONLY) +endfunction() + # Generate the config file for the build-tree. set(EVENT__INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/include" @@ -1470,26 +1478,10 @@ set(LIBEVENT_INCLUDE_DIRS ${EVENT__INCLUDE_DIRS} CACHE PATH "Libevent include directories") -configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfigBuildTree.cmake.in - ${PROJECT_BINARY_DIR}/LibeventConfig.cmake - @ONLY) +gen_package_config(0) # Generate the config file for the installation tree. -# Calculate the relative directory from the Cmake dir. -file(RELATIVE_PATH - REL_INCLUDE_DIR - "${EVENT_INSTALL_CMAKE_DIR}" - "${CMAKE_INSTALL_PREFIX}/include") - -# Note the LIBEVENT_CMAKE_DIR is defined in LibeventConfig.cmake.in, -# we escape it here so it's evaluated when it is included instead -# so that the include dirs are given relative to where the -# config file is located. -set(EVENT_INSTALL_INCLUDE_DIR "\${LIBEVENT_CMAKE_DIR}/${REL_INCLUDE_DIR}") - -configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfig.cmake.in - ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/LibeventConfig.cmake - @ONLY) +gen_package_config(1) # Generate version info for both build-tree and install-tree. configure_file(${PROJECT_SOURCE_DIR}/cmake/LibeventConfigVersion.cmake.in @@ -1514,9 +1506,19 @@ install(FILES COMPONENT dev) # Install exports for the install-tree. -install(EXPORT LibeventTargets - DESTINATION "${DEF_INSTALL_CMAKE_DIR}" +macro(install_export type) + install(EXPORT LibeventTargets-${type} + NAMESPACE ${PROJECT_NAME}:: + DESTINATION "${EVENT_INSTALL_CMAKE_DIR}" COMPONENT dev) +endmacro() + +if (${EVENT_LIBRARY_STATIC}) + install_export(static) +endif() +if (${EVENT_LIBRARY_SHARED}) + install_export(shared) +endif() # Install the scripts. install(PROGRAMS diff --git a/cmake/AddEventLibrary.cmake b/cmake/AddEventLibrary.cmake index 52dc2be656..4a6802df14 100644 --- a/cmake/AddEventLibrary.cmake +++ b/cmake/AddEventLibrary.cmake @@ -35,6 +35,45 @@ macro(generate_pkgconfig LIB_NAME) ) endmacro() +# LIB_NAME maybe event_core, event_extra, event_openssl, event_pthreads or event. +# Targets whose LIB_NAME is not 'event' should be exported and installed. +macro(export_install_target TYPE LIB_NAME OUTER_INCLUDES) + if("${LIB_NAME}" STREQUAL "event") + install(TARGETS "${LIB_NAME}_${TYPE}" + LIBRARY DESTINATION "lib" COMPONENT lib + ARCHIVE DESTINATION "lib" COMPONENT lib + RUNTIME DESTINATION "lib" COMPONENT lib + COMPONENT dev + ) + else() + string(REPLACE "event_" "" PURE_NAME ${LIB_NAME}) + string(TOUPPER ${TYPE} UPPER_TYPE) + list(APPEND LIBEVENT_${UPPER_TYPE}_LIBRARIES "${PURE_NAME}") + set(OUTER_INCS) + if (NOT "${OUTER_INCLUDES}" STREQUAL "NONE") + set(OUTER_INCS ${OUTER_INCLUDES}) + endif() + target_include_directories("${LIB_NAME}_${TYPE}" + PUBLIC "$" + "$" + "$" + ${OUTER_INCS} + ) + set_target_properties("${LIB_NAME}_${TYPE}" PROPERTIES EXPORT_NAME ${PURE_NAME}) + export(TARGETS "${LIB_NAME}_${TYPE}" + NAMESPACE ${PROJECT_NAME}:: + FILE "${PROJECT_BINARY_DIR}/LibeventTargets-${TYPE}.cmake" + APPEND + ) + install(TARGETS "${LIB_NAME}_${TYPE}" + EXPORT LibeventTargets-${TYPE} + LIBRARY DESTINATION "lib" COMPONENT lib + ARCHIVE DESTINATION "lib" COMPONENT lib + RUNTIME DESTINATION "lib" COMPONENT lib + COMPONENT dev + ) + endif() +endmacro() # Global variables that it uses: # - EVENT_ABI_LIBVERSION @@ -55,11 +94,13 @@ macro(add_event_library LIB_NAME) cmake_parse_arguments(LIB "" # Options "VERSION" # One val - "SOURCES;LIBRARIES" # Multi val + "SOURCES;LIBRARIES;INNER_LIBRARIES;OUTER_INCLUDES" # Multi val ${ARGN} ) - set(ADD_EVENT_LIBRARY_TARGETS) + if ("${LIB_OUTER_INCLUDES}" STREQUAL "") + set(LIB_OUTER_INCLUDES NONE) + endif() set(ADD_EVENT_LIBRARY_INTERFACE) if (${EVENT_LIBRARY_STATIC}) @@ -68,18 +109,30 @@ macro(add_event_library LIB_NAME) OUTPUT_NAME "${LIB_NAME}" CLEAN_DIRECT_OUTPUT 1) - list(APPEND LIBEVENT_STATIC_LIBRARIES "${LIB_NAME}_static") - list(APPEND ADD_EVENT_LIBRARY_TARGETS "${LIB_NAME}_static") + if(LIB_INNER_LIBRARIES) + set(INNER_LIBRARIES "${LIB_INNER_LIBRARIES}_static") + endif() + target_link_libraries("${LIB_NAME}_static" + ${CMAKE_THREAD_LIBS_INIT} + ${LIB_PLATFORM} + ${INNER_LIBRARIES} + ${LIB_LIBRARIES}) + export_install_target(static "${LIB_NAME}" "${LIB_OUTER_INCLUDES}") + set(ADD_EVENT_LIBRARY_INTERFACE "${LIB_NAME}_static") endif() if (${EVENT_LIBRARY_SHARED}) add_library("${LIB_NAME}_shared" SHARED ${LIB_SOURCES}) + if(LIB_INNER_LIBRARIES) + set(INNER_LIBRARIES "${LIB_INNER_LIBRARIES}_shared") + endif() target_link_libraries("${LIB_NAME}_shared" ${CMAKE_THREAD_LIBS_INIT} ${LIB_PLATFORM} + ${INNER_LIBRARIES} ${LIB_LIBRARIES}) if (EVENT_SHARED_FLAGS) @@ -120,29 +173,16 @@ macro(add_event_library LIB_NAME) WORKING_DIRECTORY "lib") endif() - list(APPEND LIBEVENT_SHARED_LIBRARIES "${LIB_NAME}_shared") - list(APPEND ADD_EVENT_LIBRARY_TARGETS "${LIB_NAME}_shared") + export_install_target(shared "${LIB_NAME}" "${LIB_OUTER_INCLUDES}") set(ADD_EVENT_LIBRARY_INTERFACE "${LIB_NAME}_shared") - endif() - - export(TARGETS ${ADD_EVENT_LIBRARY_TARGETS} - FILE "${PROJECT_BINARY_DIR}/LibeventTargets.cmake" - APPEND - ) - install(TARGETS ${ADD_EVENT_LIBRARY_TARGETS} - EXPORT LibeventTargets - LIBRARY DESTINATION "lib" COMPONENT lib - ARCHIVE DESTINATION "lib" COMPONENT lib - RUNTIME DESTINATION "lib" COMPONENT lib - COMPONENT dev - ) - if (NOT WIN32 AND ${EVENT_LIBRARY_SHARED}) - install(FILES - "$/${LIB_LINK_NAME}" - DESTINATION "lib" - COMPONENT lib) + if (NOT WIN32) + install(FILES + "$/${LIB_LINK_NAME}" + DESTINATION "lib" + COMPONENT lib) + endif() endif() add_library(${LIB_NAME} INTERFACE) diff --git a/cmake/LibeventConfig.cmake.in b/cmake/LibeventConfig.cmake.in index 54223360a4..5e2a3d8d20 100644 --- a/cmake/LibeventConfig.cmake.in +++ b/cmake/LibeventConfig.cmake.in @@ -1,18 +1,177 @@ # - Config file for the Libevent package # It defines the following variables -# LIBEVENT_INCLUDE_DIRS - include directories +# LIBEVENT_FOUND - true if libevent and all required components found on the system +# LIBEVENT_xxx_FOUND - true if component xxx(see available components) found on the system +# LIBEVENT_VERSION - libevent version in format Major.Minor.Patch +# LIBEVENT_INCLUDE_DIRS - directories where libevent header is located. +# LIBEVENT_INCLUDE_DIR - same as DIRS +# LIBEVENT_LIBRARIES - libevent library to link against. +# LIBEVENT_LIBRARY - same as LIBRARIES +# +# These variables are deprecated, don't use them. # LIBEVENT_STATIC_LIBRARIES - libraries to link against (archive/static) # LIBEVENT_SHARED_LIBRARIES - libraries to link against (shared) +# +# When you try to locate the libevent libraries, you should specify which components you want to use. +# The following table lists all available components. If none is given, all imported targets will used. +# core - the core functons of libevent +# extra - extra functions, contains http, dns and rpc +# pthreads - multiple threads for libevent, not exists on Windows +# openssl - openssl support for libevent +# +# By default, the shared libraries of libevent will be found. To find the static ones instead, +# you must set the LIBEVENT_STATIC_LINK variable to TRUE before calling find_package(Libevent ...). +# If no component provided, all components will be used. +# example: +# set(LIBEVENT_STATIC_LINK TRUE) +# find_package(Libevent 2.2 REQUIRED COMPONENTS core) +# include_directories(${LIBEVENT_INCLUDE_DIRS}) # Can be omitted +# target_link_libraries(myapp ${LIBEVENT_LIBRARIES}) +# or target_link_libraries(myapp libevent::core) +# +# find_package() can handle dependencies automatically. For example, given the 'openssl' component, +# all dependencies (libevent_core, libssl, libcrypto and openssl include directories) will be found. -# Get the path of the current file. -get_filename_component(LIBEVENT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) - -# Set the include directories. -set(LIBEVENT_INCLUDE_DIRS "@EVENT_INSTALL_INCLUDE_DIR@") +set(CONFIG_FOR_INSTALL_TREE @CONFIG_FOR_INSTALL_TREE@) -# Include the project Targets file, this contains definitions for IMPORTED targets. -include(${LIBEVENT_CMAKE_DIR}/LibeventTargets.cmake) +set(LIBEVENT_VERSION @EVENT_PACKAGE_VERSION@) # IMPORTED targets from LibeventTargets.cmake set(LIBEVENT_STATIC_LIBRARIES "@LIBEVENT_STATIC_LIBRARIES@") set(LIBEVENT_SHARED_LIBRARIES "@LIBEVENT_SHARED_LIBRARIES@") + +if(LIBEVENT_STATIC_LINK) + set(_LIB_TYPE static) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + set(_AVAILABLE_LIBS ${LIBEVENT_STATIC_LIBRARIES}) +else() + set(_LIB_TYPE shared) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + set(_AVAILABLE_LIBS ${LIBEVENT_SHARED_LIBRARIES}) +endif() + +# Get the path of the current file. +get_filename_component(LIBEVENT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_INSTALL_PREFIX "${LIBEVENT_CMAKE_DIR}/../../.." ABSOLUTE) + +macro(message_if_needed _flag _msg) + if (NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + message(${_flag} "${_msg}") + endif() +endmacro() + +macro(no_component_msg _comp) + if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED_${_comp}) + set(pthreadlib) + if(NOT WIN32) + set(pthreadlib ", pthreads") + endif() + message(FATAL_ERROR "Your libevent library does not contain a ${_comp} component!\n" + "The valid components are core, extra${pthreadlib} and openssl.") + else() + message_if_needed(WARNING "Your libevent library does not contain a ${_comp} component!") + endif() +endmacro() + +set(_EVENT_COMPONENTS) +if(${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS) + list(REMOVE_DUPLICATES ${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS) + foreach(_comp ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS}) + list(FIND _AVAILABLE_LIBS ${_comp} _INDEX) + if(_INDEX GREATER -1) + list(APPEND _EVENT_COMPONENTS ${_comp}) + else() + no_component_msg(${_comp}) + endif() + endforeach() +else() + set(_EVENT_COMPONENTS ${_AVAILABLE_LIBS}) +endif() + +set(_POSSIBLE_PKG_NAMES) +list(APPEND _POSSIBLE_PKG_NAMES ${CMAKE_FIND_PACKAGE_NAME} LIBEVENT Libevent libevent) +list(REMOVE_DUPLICATES _POSSIBLE_PKG_NAMES) + +macro(set_case_insensitive_found _comp) + foreach(name ${_POSSIBLE_PKG_NAMES}) + if("${_comp}" STREQUAL "") + set(${name}_FOUND TRUE) + set(${name}_NOTFOUND FALSE) + else() + set(${name}_${_comp}_FOUND TRUE) + set(${name}_${_comp}_NOTFOUND FALSE) + endif() + endforeach() +endmacro() + +if(CONFIG_FOR_INSTALL_TREE) +## Config for install tree ---------------------------------------- +# Find includes +unset(_event_h CACHE) +find_path(_event_h + NAMES event2/event.h + PATHS "${_INSTALL_PREFIX}/include" + NO_DEFAULT_PATH) +if(_event_h) + set(LIBEVENT_INCLUDE_DIRS "${_event_h}") + message_if_needed(STATUS "Found libevent include directory: ${_event_h}") +else() + message_if_needed(WARNING "Your libevent library does not contain header files!") +endif() + +# Find libraries +macro(find_event_lib _comp) + unset(_event_lib CACHE) + find_library(_event_lib + NAMES "event_${_comp}" + PATHS "${_INSTALL_PREFIX}/lib" + NO_DEFAULT_PATH) + if(_event_lib) + list(APPEND LIBEVENT_LIBRARIES "libevent::${_comp}") + set_case_insensitive_found(${_comp}) + message_if_needed(STATUS "Found libevent component: ${_event_lib}") + else() + no_component_msg(${_comp}) + endif() +endmacro() + +foreach(comp ${_EVENT_COMPONENTS}) + find_event_lib(${comp}) +endforeach() +else() +## Config for build tree ---------------------------------------- +set(LIBEVENT_INCLUDE_DIRS "@EVENT__INCLUDE_DIRS@") +foreach(_comp ${_EVENT_COMPONENTS}) + list(APPEND LIBEVENT_LIBRARIES "libevent::${_comp}") + set_case_insensitive_found(${_comp}) +endforeach() + +endif() + +set(LIBEVENT_INCLUDE_DIR ${LIBEVENT_INCLUDE_DIRS}) +if(LIBEVENT_LIBRARIES) + set(LIBEVENT_LIBRARY ${LIBEVENT_LIBRARIES}) + if(CONFIG_FOR_INSTALL_TREE) + message_if_needed(STATUS "Found libevent ${LIBEVENT_VERSION} in ${_INSTALL_PREFIX}") + else() + message_if_needed(STATUS "Found libevent ${LIBEVENT_VERSION} in ${LIBEVENT_CMAKE_DIR}") + endif() + + # Avoid including targets more than one times + if(NOT TARGET event_core_${_LIB_TYPE}) + # Include the project Targets file, this contains definitions for IMPORTED targets. + include(${LIBEVENT_CMAKE_DIR}/LibeventTargets-${_LIB_TYPE}.cmake) + endif() +else() + if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "Can not find any libraries for libevent.") + else() + message_if_needed(WARNING "Can not find any libraries for libevent.") + endif() +endif() + +unset(_LIB_TYPE) +unset(_AVAILABLE_LIBS) +unset(_EVENT_COMPONENTS) +unset(_POSSIBLE_PKG_NAMES) +unset(_INSTALL_PREFIX) diff --git a/cmake/LibeventConfigBuildTree.cmake.in b/cmake/LibeventConfigBuildTree.cmake.in deleted file mode 100644 index 02edef32fc..0000000000 --- a/cmake/LibeventConfigBuildTree.cmake.in +++ /dev/null @@ -1,17 +0,0 @@ -# - Config file for the Libevent package -# It defines the following variables -# LIBEVENT_INCLUDE_DIRS - include directories for FooBar -# LIBEVENT_LIBRARIES - libraries to link against - -# Get the path of the current file. -get_filename_component(LIBEVENT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) - -# Set the include directories. -set(LIBEVENT_INCLUDE_DIRS "@EVENT__INCLUDE_DIRS@") - -# Include the project Targets file, this contains definitions for IMPORTED targets. -include(${LIBEVENT_CMAKE_DIR}/LibeventTargets.cmake) - -# IMPORTED targets from LibeventTargets.cmake -set(LIBEVENT_LIBRARIES event event_core event_extra) -