c++编译使用log4cplus
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、log4cplus是什么?
- 二、使用步骤
- 1.下载源代码
- 2.开始配置
- 1.配置介绍
- 2.开始编译
- 3.cmake引用
- 4.示例
- 总结
前言
C++很强大,但是仍然有很多不尽如人意的地方,比如打印日志方面就没有java的log4j那种信手拈来,自然而然地东西。目前官方没有推出这个东西,只能借助第三方开源项目实现,或者干脆自己实现。但是,今天我们说一说一个很强大地日志库log4cplus在c++项目中地使用。
一、log4cplus是什么?
看名字就明白了,为c++开发地日志库。接下来引用开发者的话:
log4cplus is a simple to use C++ logging API providing thread–safe, flexible, and arbitrarily granular control over log management and configuration. It is modeled after the Java log4j API.
二、使用步骤
1.下载源代码
这个地方需要注意地是现在master是3.x版本了,这个版本基于C++ 20以后,使用C++ 11会直接编译报错。如果你是C++ 11的话请在分支里找到2.x的版本(包括2.0.x和2.1.x)。
由于这两个版本编译上没有显著区别,今天就以2.0.x版本为基础讲一下log4cplus的编译使用。
log4cplus下载地址
git clone https://gitee.com/anold/log4cplus.git -b 2.0.x
这里克隆完了还不能拿来直接用,还需要同步下引用的子项目。直接克隆的代码很小,包括子项目之后的大概是不到60MB,请留一下项目大小。
进入到项目目录后执行以下命令:
git submodule update --init --recursive
一定要确认所有操作成功了才行,否则编译时一定失败。
2.开始配置
1.配置介绍
log4cplus配置项众多,可以根据需要来配置。
请注意,不同的版本分支配置项可能不一样,请注意区分。这个东西在配置文件里可以看到,这里不细说了。
Configure script options
--enable-debugging
This option is disabled by default. This option mainly affects GCC builds but it also has some limited effect on non-GCC builds. It turns on debugging information generation, undefines NDEBUG symbol and adds -fstack-check (GCC).
--enable-warnings
This option is enabled by default. It adds platform / compiler dependent warning options to compiler command line.
--enable-so-version
This option is enabled by default. It enables SO version decoration on resulting library file, e.g., the .2.0.0 in liblog4cplus-1.2.so.2.0.0.
--enable-release-version
This option is enabled by default. It enables release version decoration on the resulting library file, e.g., the -1.2 in liblog4cplus-1.2.so.2.0.0.
--enable-symbols-visibility-options
This option is enabled by default. It enables use of compiler and platform specific option for symbols visibility. See also the Visibility page on GCC Wiki.
--enable-profiling
This option is disabled by default. This option adds profiling information generation compiler option -pg to GCC and Sun CC / Solaris Studio builds.
--enable-threads
This option is enabled by default. It turns on detection of necessary compiler and linker flags that enable POSIX threading support.
While this detection usually works well, some platforms still need help with configuration by supplying additional flags to the configure script. One of the know deficiencies is Solaris Studio on Linux. See one of the later note for details.
--with-wchar_t-support
This option is enabled by default. When enabled, additional binaries will be built, marked with U suffix in file name and compiled with -DUNICODE=1 flag. In effect, these binaries assume that log4cplus::tchar is wchar_t.
--with-working-locale
This is one of three locale and wchar_t↔char conversion related options. It is disabled by default.
It is know to work well with GCC on Linux. Other platforms generally have lesser locale support in their implementations of the C++ standard library. It is known not to work well on any BSDs.
See also docs/unicode.txt.
--with-working-c-locale
This is second of wchar_t↔char conversion related options. It is disabled by default.
It is known to work well on most Unix--like platforms, including recent Cygwin.
--with-iconv
This is third of wchar_t↔char conversion related options. It is disabled by default.
The conversion using iconv() function always uses "UTF-8" and "WCHAR_T" as source/target encoding. It is known to work well on platforms with GNU iconv. Different implementations of iconv() might not support "WCHAR_T" encoding selector.
Either system provided iconv() or library provided libiconv() are detected and accepted. Also both SUSv3 and GNU iconv() function signatures are accepted.
--with-qt
This option is disabled by default. It enables compilation of a separate shared library (liblog4cplusqt4debugappender) that implements Qt4DebugAppender. It requires Qt4 and pkg-config to be installed.
--enable-tests
This option is enabled by default. It enables compilation of test executables.
--enable-unit-tests
This option is disabled by default. It enables compilation of unit tests along their units. These unit tests then can be executed through unit_tests test executable that is built during compilation.
主要包括调试,so版本号支持,宽字符支持和本地化等。如果看不懂英文就维持原样。
2.开始编译
编译方法原作者已经给出了,这里着重说一下LInux上的编译。
这里还是建议安装到/usr/local;一方面,因为/usr本身包含很多操作系统预装的应用,相比来说/usr/local基本上空空如也,管理起来方便。另一方面,也是为了以后使用pkgconfig查找方便,这个后面再说。
./configure --prefix=/usr/local --enable-so-version=yes --enable-release-version=yes \
--enable-threads=yes
配置好之后使用下面的命令:
make -j6 && sudo make install
安装好之后会在/usr/local下面找到,重点是/usr/local/lib/pkgconfig/log4cplus.pc
,一会配置要用到这个文件。
3.cmake引用
这里选用的是cmake,不为了别的就是因为简单。这里需要先通过cmake找到pkgconf这个包管理器,再通过pkgconf进一步定位log4cplus这个最终需要的包。
请看配置:
cmake_minimum_required(VERSION 3.10)
project(log_4_cplus)
set(CMAKE_CXX_STANDARD 11)
find_package(PkgConfig REQUIRED)
if (PKG_CONFIG_FOUND)
message(STATUS "PkgConfig Found")
pkg_search_module(
log4cplus
REQUIRED
log4cplus
IMPORTED_TARGET
)
if (TARGET PkgConfig::log4cplus)
message(STATUS "log4cplus Found")
add_executable(log_4_cplus main.cpp)
target_link_libraries(log_4_cplus PkgConfig::log4cplus)
endif ()
endif ()
重点就是find_package(PkgConfig REQUIRED)
和pkg_search_module
,前者找到Linux上面安装的pkgconf,后者通过pkgconf找到它管理的module,也就是log4cplus。
这个时候你就可以使用log4cplus了。下面列出几个简单的例子,其它的用法可以看下开发者的tests或wiki。
4.示例
简单实用1:
#include <iostream>
#include <iomanip>
#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>
#include <log4cplus/initializer.h>
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
void printTest(log4cplus::Logger const &logger) {
LOG4CPLUS_INFO(logger,
LOG4CPLUS_TEXT("This is")
<< LOG4CPLUS_TEXT(" a reall")
<< LOG4CPLUS_TEXT("y long message.") << std::endl
<< LOG4CPLUS_TEXT("Just testing it out") << std::endl
<< LOG4CPLUS_TEXT("What do you think?"));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a bool: ") << true);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a char: ")
<< LOG4CPLUS_TEXT('x'));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a short: ")
<< static_cast<short>(-100));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a unsigned short: ")
<< static_cast<unsigned short>(100));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a int: ") << 1000);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a unsigned int: ") << 1000U);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a long(hex): ")
<< std::hex << 100000000L);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a unsigned long: ")
<< static_cast<unsigned long>(100000000U));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a float: ") << 1.2345f);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a double: ")
<< std::setprecision(15)
<< 1.2345234234);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("This is a long double: ")
<< std::setprecision(15)
<< 123452342342.342L);
}
int main(){
log4cplus::Initializer initializer;
log4cplus::BasicConfigurator config;
config.configure(logger);
log4cplus::Logger logger = log4cplus::Logger::getInstance(
LOG4CPLUS_TEXT("main"));
printTest();
return 0;
}
简单实用2:
#include <iostream>
#include <iomanip>
#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>
#include <log4cplus/initializer.h>
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
//带时间格式的日志
void time_format_test() {
log4cplus::tchar const fmtstr[] =
LOG4CPLUS_TEXT("%s, %Q%%q%q %%Q %%q=%%%q%%;%%q, %%Q=%Q");
std::cout << "Entering main()..." << std::endl;
log4cplus::Initializer initializer;
try {
Time time;
log4cplus::tstring str;
time = now();
str = getFormattedTime(fmtstr, time);
log4cplus::tcout << LOG4CPLUS_TEXT ("now: ") << str << std::endl;
time = time_from_parts(0, 7);
str = getFormattedTime(fmtstr, time);
log4cplus::tcout << str << std::endl;
time = time_from_parts(0, 17);
str = getFormattedTime(fmtstr, time);
log4cplus::tcout << str << std::endl;
time = time_from_parts(0, 123);
str = getFormattedTime(fmtstr, time);
log4cplus::tcout << str << std::endl;
time = time_from_parts(0, 1234);
str = getFormattedTime(fmtstr, time);
log4cplus::tcout << str << std::endl;
time = time_from_parts(0, 12345);
str = getFormattedTime(fmtstr, time);
log4cplus::tcout << str << std::endl;
time = time_from_parts(0, 123456);
str = getFormattedTime(fmtstr, time);
log4cplus::tcout << str << std::endl;
time = time_from_parts(0, 0);
str = getFormattedTime(fmtstr, time);
log4cplus::tcout << str << std::endl;
}
catch (std::exception const &e) {
std::cout << "Exception: " << e.what() << std::endl;
}
catch (...) {
std::cout << "Exception..." << std::endl;
}
std::cout << "Exiting main()..." << std::endl;
}
int main(){
time_format_test();
return 0;
}
总结
1、蛮简单的,倒是log4cplus的使用有很多需要研究的地方