I'm trying to write a C++ logging library. It uses boost::log
mainly for the BOOST_LOG_SEV
macro. I can use my library without an issue like LOG(debug) << "Test message"
. Here is my public header.
include/logger.hpp
#include "config.hpp"
#define BOOST_LOG_DYN_LINK 1
#include <boost/log/sinks.hpp>
#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/trivial.hpp>
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(logger, boost::log::sources::severity_channel_logger<severity_level>)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
#define LOG(severity) BOOST_LOG_SEV(logger::get(), severity)
class LoggerImpl; // forward declaration
namespace Logger {
void init(const Config &config);
inline std::unique_ptr<LoggerImpl> mImpl; // private implementation
}
Since I'm using the BOOST_LOG_SEV
macro and performing some boost configurations, I need to include boost headers in my public header. But, this causes me to need to publicly link the boost dependency with my output shared library (liblogger.so
). And consequently, libraries use liblogger as a dependency and need to link with boost::log
as well. How can I hide boost dependencies from public my header without affecting my library's usage?
I tried to move the BOOST_LOG_SEV
macro usage and all boost includes into the private implementation but it didn't work since I cannot capture the character stream given to the LOG(severity) <<
macro.
EDIT: CMakeLists.txt
set(PROJECT_NAME "Logger")
set(LIBRARY_NAME ${PROJECT_NAME})
string(TOLOWER ${PROJECT_NAME} LOWERCASE_PROJECT_NAME)
project(${PROJECT_NAME}
VERSION ${VERSION}
DESCRIPTION "Logging library"
)
add_subdirectory(include)
add_subdirectory(src)
set(Boost_USE_STATIC_LIBS OFF)
find_package(Boost 1.54 COMPONENTS log log_setup REQUIRED)
set(LIBRARIES
${Boost_LIBRARIES}
pthread
stdc++fs
)
add_library(${LIBRARY_NAME}
SHARED
${CXX_SOURCES}
${CXX_HEADERS}
)
set(INCLUDE_DIRS
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:include>")
target_include_directories(${LIBRARY_NAME} PUBLIC ${INCLUDE_DIRS})
target_link_libraries(${LIBRARY_NAME}
PUBLIC
${LIBRARIES}
)
set_target_properties(${PROJECT_NAME}
PROPERTIES
SKIP_BUILD_RPATH 1
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
OUTPUT_NAME ${LOWERCASE_PROJECT_NAME}
)
install(TARGETS ${PROJECT_NAME}
EXPORT "${PROJECT_NAME}Targets"
LIBRARY
DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT libraries
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
COMPONENT headers
)
install(EXPORT ${PROJECT_NAME}Targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
COMPONENT headers
)
After reading the comment I managed to solve the problem by adding include(CMakeFindDependencyMacro)
and a find_dependency
call into the config file used by configure_package_config_file
.
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(Boost 1.54 COMPONENTS log log_setup REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components(@PROJECT_NAME@)
Now, the libraries use liblogger
as dependency are no longer need to call find_package(Boost ... )
explicitly.