From dc4be869d5009f38e0ef02ff07dd799f9c2fef2f Mon Sep 17 00:00:00 2001 From: yuangongji <82787816@qq.com> Date: Thu, 7 Nov 2019 18:26:47 +0800 Subject: [PATCH 1/3] cmake: improve package config file --- .gitignore | 2 +- CMakeLists.txt | 64 ++++----- cmake/AddEventLibrary.cmake | 88 +++++++++---- cmake/LibeventConfig.cmake.in | 175 +++++++++++++++++++++++-- cmake/LibeventConfigBuildTree.cmake.in | 17 --- 5 files changed, 265 insertions(+), 81 deletions(-) delete mode 100644 cmake/LibeventConfigBuildTree.cmake.in diff --git a/.gitignore b/.gitignore index 703cf957..ab7965c9 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 c98b619a..5b2537d5 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 52dc2be6..4a6802df 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 54223360..5e2a3d8d 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(CONFIG_FOR_INSTALL_TREE @CONFIG_FOR_INSTALL_TREE@) -# Set the include directories. -set(LIBEVENT_INCLUDE_DIRS "@EVENT_INSTALL_INCLUDE_DIR@") - -# 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 02edef32..00000000 --- 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) - From cd15112b620feadafe8fd3531043870a5c19a4a6 Mon Sep 17 00:00:00 2001 From: yuangongji <82787816@qq.com> Date: Thu, 14 Nov 2019 18:28:31 +0800 Subject: [PATCH 2/3] cmake: test for find_package() --- .gitignore | 1 + test-export/CMakeLists.txt | 15 +++ test-export/test-export.c | 122 +++++++++++++++++++++++ test-export/test-export.py | 199 +++++++++++++++++++++++++++++++++++++ 4 files changed, 337 insertions(+) create mode 100644 test-export/CMakeLists.txt create mode 100644 test-export/test-export.c create mode 100644 test-export/test-export.py diff --git a/.gitignore b/.gitignore index ab7965c9..9614740e 100644 --- a/.gitignore +++ b/.gitignore @@ -149,6 +149,7 @@ event_extra.dir *.sln *.filters install_manifest.txt +test-export/build # ninja build.ninja diff --git a/test-export/CMakeLists.txt b/test-export/CMakeLists.txt new file mode 100644 index 00000000..89c1806c --- /dev/null +++ b/test-export/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.1.2) +if (POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +endif() +project(verify) +# set(CMAKE_VERBOSE_MAKEFILE 1) +if(NOT ${EVENT__CODE_COMPONENT} STREQUAL "") + string(TOUPPER ${EVENT__CODE_COMPONENT} _UPPER_COMPONENT) +endif() +find_package(Libevent 2.2.0 REQUIRED COMPONENTS ${EVENT__LINK_COMPONENT}) +add_definitions(-DEVENT_EXPORT_TEST_COMPONENT_${_UPPER_COMPONENT}) +add_executable(test-export test-export.c) +target_link_libraries(test-export ${LIBEVENT_LIBRARIES}) +enable_testing() +add_test(test-export test-export) diff --git a/test-export/test-export.c b/test-export/test-export.c new file mode 100644 index 00000000..90917775 --- /dev/null +++ b/test-export/test-export.c @@ -0,0 +1,122 @@ +#include +#if defined(EVENT_EXPORT_TEST_COMPONENT_EXTRA) +#include "event2/http.h" +#include "event2/rpc.h" +#include +#elif defined(EVENT_EXPORT_TEST_COMPONENT_PTHREADS) +#include +#elif defined(EVENT_EXPORT_TEST_COMPONENT_OPENSSL) +#include +#include +#include +#endif + +#if defined(EVENT_EXPORT_TEST_COMPONENT_EXTRA) +static int +test() +{ + struct event_base *base = NULL; + struct evhttp *http = NULL; + struct evdns_base *dns_base = NULL; + struct evrpc_base *rpc_base = NULL; + + base = event_base_new(); + if (base) { + http = evhttp_new(base); + dns_base = evdns_base_new(base, + EVDNS_BASE_DISABLE_WHEN_INACTIVE); + } + if (http) + rpc_base = evrpc_init(http); + + if (base) + event_base_free(base); + if (http) + evhttp_free(http); + if (rpc_base) + evrpc_free(rpc_base); + if (dns_base) + evdns_base_free(dns_base, 0); + + return 0; +} +#elif defined(EVENT_EXPORT_TEST_COMPONENT_PTHREADS) +static int +test() +{ + return evthread_use_pthreads(); +} +#elif defined(EVENT_EXPORT_TEST_COMPONENT_OPENSSL) +static int +test() +{ + struct event_base *base = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + struct bufferevent *bev; + int r = 1; + + SSL_library_init(); + ERR_load_crypto_strings(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); + + base = event_base_new(); + if (!base) { + goto error; + } + + ssl_ctx = SSL_CTX_new(SSLv23_method()); + if (!ssl_ctx) { + goto error; + } + ssl = SSL_new(ssl_ctx); + if (ssl == NULL) { + goto error; + } + bev = bufferevent_openssl_socket_new(base, -1, ssl, + BUFFEREVENT_SSL_CONNECTING, + BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); + if (bev == NULL) { + goto error; + } + r = 0; +error: + if (base) + event_base_free(base); + if (ssl_ctx) + SSL_CTX_free(ssl_ctx); + if (ssl) + SSL_free(ssl); + return r; +} +#else +static int +test() +{ + struct event_base *base = NULL; + + base = event_base_new(); + if (base) + event_base_free(base); + + return 0; +} +#endif + +int +main(int argc, char const *argv[]) +{ + int r = 0; +#ifdef _WIN32 + { + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); + } +#endif + r = test(); +#ifdef _WIN32 + WSACleanup(); +#endif + return r; +} diff --git a/test-export/test-export.py b/test-export/test-export.py new file mode 100644 index 00000000..3be8193f --- /dev/null +++ b/test-export/test-export.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +# +# Check if find_package(Libevent COMPONENTS xxx) can get the correct library. +# Note: this script has only been tested on python3. +# Usage: +# cd cmake-build-dir +# cmake .. && cmake --build . +# python /path/to/test-export.py [static|shared] + +import sys +import os +import shutil +import platform +import subprocess +import tempfile + +results = ("success", "failure") +FNULL = open(os.devnull, 'wb') +script_dir = os.path.split(os.path.realpath(sys.argv[0]))[0] +# working_dir is cmake build dir +working_dir = os.getcwd() +if len(sys.argv) > 1 and sys.argv[1] == "static": + link_type = sys.argv[1] +else: + link_type = "shared" + + +def exec_cmd(cmd, silent): + if silent: + p = subprocess.Popen(cmd, stdout=FNULL, stderr=FNULL, shell=True) + else: + p = subprocess.Popen(cmd, shell=True) + p.communicate() + return p.poll() + + +def link_and_run(link, code): + """Check if the source code matches the library component. + + Compile source code relative to one component and link to another component. + Then run the generated executor. + + Args: + link: The name of component that the source code will link with. + code: The source code related component name. + + Returns: + Returns 0 if links and runs successfully, otherwise 1. + """ + exec_cmd("cmake --build . --target clean", True) + generator = '' + if platform.system() == "Windows": + generator = '-G "Visual Studio 15 2017 Win64"' + cmd = 'cmake .. %s -DEVENT__LINK_COMPONENT=%s -DEVENT__CODE_COMPONENT=%s' % ( + generator, link, code) + if link_type == "static": + cmd = "".join([cmd, " -DLIBEVENT_STATIC_LINK=1"]) + r = exec_cmd(cmd, True) + if r == 0: + r = exec_cmd('cmake --build .', True) + if r == 0: + r = exec_cmd('ctest', True) + if r != 0: + r = 1 + return r + +# expect 0:success 1:failure +def testcase(link, code, expect): + r = link_and_run(link, code) + if link == "": + link = "all" + if code == "": + code = "all" + if r != expect: + print('[test-export] fail: link %s and run %s expects %s but gets %s.' % + (link, code, results[expect], results[r])) + sys.exit(1) + else: + print('[test-export] success: link %s and run %s expects and gets %s.' % + (link, code, results[r])) + +# Dependency relationships between libevent libraries: +# core: none +# extra: core +# pthreads: core,pthread +# openssl: core,openssl +def test_group(): + testcase("core", "core", 0) + testcase("extra", "extra", 0) + testcase("openssl", "openssl", 0) + testcase("", "", 0) + testcase("extra", "core", 0) + testcase("openssl", "core", 0) + testcase("core", "extra", 1) + testcase("core", "openssl", 1) + testcase("extra", "openssl", 1) + testcase("openssl", "extra", 1) + if platform.system() != "Windows": + testcase("pthreads", "pthreads", 0) + testcase("pthreads", "core", 0) + testcase("core", "pthreads", 1) + testcase("extra", "pthreads", 1) + testcase("pthreads", "extra", 1) + testcase("pthreads", "openssl", 1) + testcase("openssl", "pthreads", 1) + + +def config_restore(): + if os.path.isfile("tempconfig") and not os.path.isfile("LibeventConfig.cmake"): + os.rename("tempconfig", "LibeventConfig.cmake") + + +def config_backup(): + if os.path.isfile("tempconfig"): + os.remove("tempconfig") + if os.path.isfile("LibeventConfig.cmake"): + os.rename("LibeventConfig.cmake", "tempconfig") + + +shutil.rmtree(os.path.join(script_dir, "build"), ignore_errors=True) + + +def run_test_group(): + os.chdir(script_dir) + if not os.path.isdir("build"): + os.mkdir("build") + os.chdir("build") + test_group() + os.chdir(working_dir) + + +need_exportdll = False +if link_type == "shared" and platform.system() == "Windows": + need_exportdll = True + +# On Windows, we need to add the directory containing the dll to the +# 'PATH' environment variable so that the program can call it. +def export_dll(dir): + if need_exportdll: + os.environ["PATH"] += os.pathsep + dir + + +def unexport_dll(dir): + if need_exportdll: + paths = os.environ["PATH"].split(os.pathsep) + paths = list(set(paths)) + if dir in paths: + paths.remove(dir) + os.environ["PATH"] = os.pathsep.join(paths) + + +print("[test-export] use %s library" % link_type) + +# Test for build tree. +print("[test-export] test for build tree") +dllpath = os.path.join(working_dir, "bin", "Debug") +config_restore() +os.environ["CMAKE_PREFIX_PATH"] = working_dir +export_dll(dllpath) +run_test_group() +del os.environ["CMAKE_PREFIX_PATH"] +unexport_dll(dllpath) + +# Install libevent libraries to system path. Remove LibeventConfig.cmake +# from build directory to avoid confusion when using find_package(). +print("[test-export] test for install tree(in system-wide path)") +if platform.system() == "Windows": + prefix = "C:\\Program Files\\libevent" + dllpath = os.path.join(prefix, "lib") +else: + prefix = "/usr/local" +exec_cmd('cmake -DCMAKE_INSTALL_PREFIX="%s" ..' % prefix, True) +exec_cmd('cmake --build . --target install', True) +config_backup() +os.environ["CMAKE_PREFIX_PATH"] = os.path.join(prefix, "lib/cmake/libevent") +export_dll(dllpath) +run_test_group() +unexport_dll(dllpath) +del os.environ["CMAKE_PREFIX_PATH"] + +# Uninstall the libraries installed in the above steps. Install the libraries +# into a temporary directory. Same as above, remove LibeventConfig.cmake from +# build directory to avoid confusion when using find_package(). +print("[test-export] test for install tree(in non-system-wide path)") +exec_cmd("cmake --build . --target uninstall", True) +tempdir = tempfile.TemporaryDirectory() +cmd = 'cmake -DCMAKE_INSTALL_PREFIX="%s" ..' % tempdir.name +exec_cmd(cmd, True) +exec_cmd("cmake --build . --target install", True) +config_backup() +os.environ["CMAKE_PREFIX_PATH"] = os.path.join(tempdir.name, "lib/cmake/libevent") +dllpath = os.path.join(tempdir.name, "lib") +export_dll(dllpath) +run_test_group() +unexport_dll(dllpath) +del os.environ["CMAKE_PREFIX_PATH"] +config_restore() + +print("[test-export] all testcases have run successfully") From 63f73ee2ad037bf0d03aea4d489fdd9e85a21ff1 Mon Sep 17 00:00:00 2001 From: yuangongji <82787816@qq.com> Date: Thu, 14 Nov 2019 18:34:56 +0800 Subject: [PATCH 3/3] CI: integrate testing for components export --- .travis.yml | 18 +++++++++++++++--- appveyor.yml | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6cb07751..96825bd6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,6 +42,11 @@ matrix: # coveralls - os: linux env: EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__COVERAGE=ON -DCMAKE_BUILD_TYPE=debug" COVERALLS=yes + # test-export + - os: linux + env: EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON" TEST_EXPORT=STATIC + - os: linux + env: EVENT_BUILD_METHOD=cmake EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=SHARED -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON" TEST_EXPORT=SHARED # for openssl1.1 - os: linux dist: bionic @@ -124,9 +129,16 @@ script: mkdir build && cd build && - cmake .. $EVENT_CMAKE_OPTIONS && - travis_wait $TIMEOUT - cmake --build . --target verify; + cmake .. $EVENT_CMAKE_OPTIONS; + if [ "$TEST_EXPORT" == "STATIC" ]; then + cmake --build .; + sudo python3 ../test-export/test-export.py static; + elif [ "$TEST_EXPORT" == "SHARED" ]; then + cmake --build .; + sudo python3 ../test-export/test-export.py shared; + else + travis_wait $TIMEOUT cmake --build . --target verify; + fi fi - if [ "$TOOL" == "doxygen" ]; then eval "$(ssh-agent -s)"; diff --git a/appveyor.yml b/appveyor.yml index ec08a1ce..a2687237 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,6 +23,7 @@ environment: global: APPVEYOR_SAVE_CACHE_ON_ERROR: true OPENSSL_ROOT: C:/OpenSSL-Win64 + PYTHON3: C:/Python37-x64/python.exe MPATH: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin;C:/msys64/usr/bin EVENT_TESTS_PARALLEL: 20 EVENT_BUILD_PARALLEL: 10 @@ -66,6 +67,14 @@ environment: - EVENT_BUILD_METHOD: "cmake" EVENT_CMAKE_OPTIONS: "" APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2019" + - EVENT_BUILD_METHOD: "cmake" + EVENT_CMAKE_OPTIONS: "-DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON" + APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017" + TEST_EXPORT: "SHARED" + - EVENT_BUILD_METHOD: "cmake" + EVENT_CMAKE_OPTIONS: "-DEVENT__LIBRARY_TYPE=STATIC -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON" + APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017" + TEST_EXPORT: "STATIC" matrix: exclude: @@ -123,7 +132,13 @@ build_script: if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) } cmake --build . -j $env:EVENT_BUILD_PARALLEL -- /nologo /verbosity:minimal if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) } - ctest --output-on-failure -j $env:EVENT_TESTS_PARALLEL + if ($env:TEST_EXPORT -eq 'STATIC') { + &$env:PYTHON3 ../test-export/test-export.py static + } elseif ($env:TEST_EXPORT -eq 'SHARED') { + &$env:PYTHON3 ../test-export/test-export.py shared + } else { + ctest --output-on-failure -j $env:EVENT_TESTS_PARALLEL + } } cache: