Unverified Commit 4ed3f8e1 authored by suokko's avatar suokko Committed by GitHub

Cmake build improvements for find_package(Pistache) (#795)

* Set default build type using _INIT variable

Language support checking offers a standardized method to set default
build type using CMAKE_BUILD_TYPE_INIT variable. The variable must be
set before enable_language is called implicitly from project

* Enable only C++ compiler

* Let C++ compiler detection to check for standard support

Setting CMAKE_CXX_STANDARD variables before implicit call to
enable_language handles checking for standard support automatically.

* Fix pistache_shared export

Exporting targets allows find_package(Pistache) to import them
correctly. The import makes it easier to use Pistache in a porject using
cmake build system.

* Add wildcard ignore for multiple build directories

I used multiple build directories to test different configurations work.
My alternative test configuration is a Debian Stretch chroot for an old
distro test.

* Detect Threads which is implicit requirement

Static library requires PistancheConfig.cmake to detect all dependencies
to allow simple linking to imported library to work.

* Use find_package to detect OpenSSL

Add OpenSSL configure time detection for the development package.
FindOpenSSL.cmake started support IMPORTED libraries only in 3.4. The
IMPORTED library helps users to link correctly to pistache static
library.

Headers use libssl directly which forces pistache to use public
definition and library link.

* Export include directories to IMPORTED library

* Do not add pistache to global build configuration

PistacheConfig shouldn't add include directories and libraries to the
global build configuration. Imported libraries provide all required
build configurations to a depending target.

* Check if atomic library is required

Pistache should link to atomic library only if system requires the
library. The easiest method appears to be use a modified LLVM
CheckAtomic helper.

* Use target include directories for GTest

* Detect libcurl and remove pthread linking

* Update CMake Pistache example

* Add CMake ConfigVersion file

* Update the date part of version
parent 4e48b6d3
# Build files
build
/*build*/
# Compiled Object files
*.slo
......
cmake_minimum_required (VERSION 3.1.3)
project (pistache)
cmake_minimum_required (VERSION 3.4)
set(CMAKE_BUILD_TYPE_INIT Release)
# CMAKE Pin cxx compiler to CXX14 until update to CXX17
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
project (pistache
LANGUAGES CXX)
include(GNUInstallDirs)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -pedantic -Wextra -Wno-missing-field-initializers")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
include(CheckAtomic)
if(CMAKE_BUILD_TYPE MATCHES "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage -fstack-protector-all --param=ssp-buffer-size=4")
......@@ -52,24 +60,12 @@ if (PISTACHE_BUILD_TESTS)
add_custom_target(coverage COMMAND ${CMAKE_CTEST_COMMAND} --force-new-ctest-process --test-action coverage)
endif()
# CMAKE Pin cxx compiler to CXX14 until update to CXX17
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if (PISTACHE_USE_SSL)
add_definitions(-DPISTACHE_USE_SSL)
link_libraries(-lssl -lcrypto)
endif (PISTACHE_USE_SSL)
link_libraries(-latomic)
include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include)
find_package(OpenSSL REQUIRED COMPONENTS SSL Crypto)
endif ()
# Set version...
......@@ -114,7 +110,10 @@ include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include)
# Set libraries...
# Minimum...
set(LIBS "-lpistache -lpthread -latomic")
set(LIBS "-lpistache -lpthread")
if (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
set(LIBS "-latomic")
endif ()
# If building with OpenSSL support...
if(PISTACHE_USE_SSL)
......@@ -156,11 +155,9 @@ endif()
if (PISTACHE_BUILD_TESTS)
find_package(GTest)
if (GTEST_FOUND)
include_directories(${GTEST_INCLUDE_DIRS})
else()
if (NOT GTEST_FOUND)
ADD_SUBDIRECTORY (third-party/googletest)
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
set(GTEST_INCLUDE_DIRS ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
endif()
enable_testing()
......
# Source: https://github.com/llvm-mirror/llvm/blob/master/cmake/modules/CheckAtomic.cmake
# atomic builtins are required for threading support.
INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckLibraryExists)
# Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics.
function(check_working_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
std::atomic<int> x;
int main() {
return x;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics)
function(check_working_cxx_atomics64 varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
#include <cstdint>
std::atomic<uint64_t> x (0);
int main() {
uint64_t i = x.load(std::memory_order_relaxed);
return 0;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics64)
# This isn't necessary on MSVC, so avoid command-line switch annoyance
# by only running on GCC-like hosts.
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
# First check if atomics work without the library.
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
if( HAVE_LIBATOMIC )
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
message(FATAL_ERROR "Host compiler must support std::atomic!")
endif()
else()
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
endif()
endif()
endif()
# Check for 64 bit atomic operations.
if(MSVC)
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
else()
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
endif()
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
if(HAVE_CXX_LIBATOMICS64)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!")
endif()
else()
message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.")
endif()
endif()
......@@ -91,16 +91,14 @@ To [use](https://autotools.io/pkgconfig/pkg_check_modules.html) with the GNU Aut
To use with a CMake build environment, use the [FindPkgConfig](https://cmake.org/cmake/help/latest/module/FindPkgConfig.html) module. Here is an example:
```cmake
cmake_minimum_required(2.8 FATAL_ERROR)
cmake_minimum_required(3.4 FATAL_ERROR)
project("MyPistacheProject")
# Tell CMake to add support for pkg-config, then use it to find the library...
include(FindPkgConfig)
pkg_search_module(PISTACHE REQUIRED libpistache>=0.0.2)
include_directories(${PISTACHE_INCLUDE_DIRS})
# Find the library.
find_package(Pistache 0.0.2 REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${PISTACHE_LIBRARIES})
target_link_libraries(${PROJECT_NAME} pistache_shared)
```
## Makefile
......
......@@ -15,9 +15,12 @@ add_library(pistache OBJECT ${SOURCE_FILES})
set_target_properties(pistache PROPERTIES POSITION_INDEPENDENT_CODE 1)
add_definitions(-DONLY_C_LOCALE=1)
target_include_directories(pistache PUBLIC
set(PISTACHE_INCLUDE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
)
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_include_directories(pistache PUBLIC ${PISTACHE_INCLUDE})
set(include_install_dir ${CMAKE_INSTALL_INCLUDEDIR})
set(lib_install_dir ${CMAKE_INSTALL_LIBDIR})
......@@ -26,8 +29,21 @@ set(bin_install_dir ${CMAKE_INSTALL_BINDIR})
add_library(pistache_shared SHARED $<TARGET_OBJECTS:pistache>)
add_library(pistache_static STATIC $<TARGET_OBJECTS:pistache>)
target_link_libraries(pistache_shared Threads::Threads)
target_link_libraries(pistache_static Threads::Threads)
target_link_libraries(pistache_shared PRIVATE Threads::Threads ${CMAKE_REQUIRED_LIBRARIES})
target_link_libraries(pistache_static PRIVATE Threads::Threads ${CMAKE_REQUIRED_LIBRARIES})
target_include_directories(pistache_shared INTERFACE ${PISTACHE_INCLUDE})
target_include_directories(pistache_static INTERFACE ${PISTACHE_INCLUDE})
if (PISTACHE_USE_SSL)
target_compile_definitions(pistache PUBLIC PISTACHE_USE_SSL)
target_compile_definitions(pistache_shared PUBLIC PISTACHE_USE_SSL)
target_compile_definitions(pistache_static PUBLIC PISTACHE_USE_SSL)
target_include_directories(pistache PRIVATE ${OPENSSL_INCLUDE_DIR})
target_link_libraries(pistache_shared PUBLIC OpenSSL::SSL OpenSSL::Crypto)
target_link_libraries(pistache_static PUBLIC OpenSSL::SSL OpenSSL::Crypto)
endif ()
set(Pistache_OUTPUT_NAME "pistache")
set_target_properties(pistache_shared PROPERTIES
......@@ -43,10 +59,11 @@ set_target_properties(pistache_static PROPERTIES
if (PISTACHE_INSTALL)
set(Pistache_CMAKE_INSTALL_PATH "${CMAKE_INSTALL_LIBDIR}/cmake/pistache")
set(Pistache_CONFIG_FILE "PistacheConfig.cmake")
set(Pistache_CONFIG_VERSION_FILE "PistacheConfigVersion.cmake")
install(
TARGETS pistache_shared
EXPORT ${targets_export_name}
EXPORT PistacheTargets
ARCHIVE DESTINATION ${lib_install_dir}
LIBRARY DESTINATION ${lib_install_dir}
RUNTIME DESTINATION ${bin_install_dir}
......@@ -72,8 +89,13 @@ if (PISTACHE_INSTALL)
INSTALL_DESTINATION ${Pistache_CMAKE_INSTALL_PATH}
PATH_VARS include_install_dir lib_install_dir
)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/${Pistache_CONFIG_VERSION_FILE}"
VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}
COMPATIBILITY AnyNewerVersion)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/${Pistache_CONFIG_FILE}"
"${CMAKE_CURRENT_BINARY_DIR}/${Pistache_CONFIG_VERSION_FILE}"
DESTINATION ${Pistache_CMAKE_INSTALL_PATH}
COMPONENT cmake-config
)
......
@PACKAGE_INIT@
set_and_check ( Pistache_INCLUDE_DIRS "@PACKAGE_include_install_dir@")
include_directories(${Pistache_INCLUDE_DIRS})
set_and_check ( Pistache_LIBRARIES "@PACKAGE_lib_install_dir@")
link_directories(${Pistache_LIBRARIES})
#Required for the static library
find_package(Threads REQUIRED)
if (@PISTACHE_USE_SSL@)
find_package(OpenSSL REQUIRED COMPONENTS SSL Crypto)
endif ()
include("${CMAKE_CURRENT_LIST_DIR}/PistacheTargets.cmake")
find_package(CURL REQUIRED)
function(pistache_test test_name)
set(TEST_EXECUTABLE run_${test_name})
set(TEST_SOURCE ${test_name}.cc)
add_executable(${TEST_EXECUTABLE} ${TEST_SOURCE})
target_link_libraries(${TEST_EXECUTABLE} gtest gtest_main pistache_static curl pthread)
target_include_directories(${TEST_EXECUTABLE} PRIVATE ${GTEST_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS})
target_link_libraries(${TEST_EXECUTABLE} gtest gtest_main pistache_static ${CURL_LIBRARIES})
add_test(${test_name} ${TEST_EXECUTABLE})
endfunction()
......
VERSION_MAJOR 0
VERSION_MINOR 0
VERSION_PATCH 002
VERSION_GIT_DATE 20200301
VERSION_GIT_DATE 20200708
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment