我正在尝试构建 Boost.Log ( http://boost-log.sourceforge.net/libs/log/doc/html/index.html )。我将其添加到我的 boost 源中并执行了我常用的 boost 构建命令。
b2 --build-dir="D:\boost\1.51.0\boost" toolset=gcc variant=release link=static threading=multi runtime-link=static --build-type=complete
Run Code Online (Sandbox Code Playgroud)
但什么也没发生,我最终收到了这个:
D:/boost/1.51.0/src/tools/build/v2/build\generators.jam:1085: in ensure-type from module generators
error: target { simple_event_log.mc. } has no type
D:/boost/1.51.0/src/tools/build/v2/build\generators.jam:1319: in generators.construct from module generators
D:/boost/1.51.0/src/tools/build/v2/build\targets.jam:1495: in construct from module object(typed-target)@491
D:/boost/1.51.0/src/tools/build/v2/build\targets.jam:1298: in object(typed-target)@491.generate from module object(typed-target)@491
D:/boost/1.51.0/src/tools/build/v2/build\targets.jam:732: in generate-really from module object(main-target)@1871
D:/boost/1.51.0/src/tools/build/v2/build\targets.jam:704: in object(main-target)@1871.generate from module object(main-target)@1871
D:/boost/1.51.0/src/tools/build/v2/build\targets.jam:258: in object(project-target)@474.generate from module object(project-target)@474
D:/boost/1.51.0/src/tools/build/v2/build\targets.jam:848: in targets.generate-from-reference from module targets D:/boost/1.51.0/src/tools/build/v2/build\targets.jam:1217: in generate-dependencies from module object(install-target-class)@96 …Run Code Online (Sandbox Code Playgroud) 我需要一个用于调试目的的记录器,我正在使用Boost.Log(1.54.0和boost.org主页中的补丁).
一切都很好我已经创建了一些像这样的宏:
#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )
Run Code Online (Sandbox Code Playgroud)
现在这是一种只在调试模式下在BOOST_LOG_TRIVIAL(lvl)中显示LOG_MESSAGE(lvl)并在发布中忽略的方法吗?
例如:
LOG_MESSAGE( critical ) << "If I read this message we're in debug mode"
Run Code Online (Sandbox Code Playgroud)
编辑 我的第一次尝试是创建一个nullstream ...我认为在发布模式编译器将优化它...
#if !defined( NDEBUG )
#include <boost/log/trivial.hpp>
#define LOG_MESSAGE( lvl ) BOOST_LOG_TRIVIAL( lvl )
#else
#if defined( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-value"
#endif
#include <iosfwd>
struct nullstream : public std::ostream {
nullstream() : std::ios(0), std::ostream(0) {}
};
static nullstream g_nullstream;
#define LOG_MESSAGE( lvl ) g_nullstream
#if defined( __GNUC__ …Run Code Online (Sandbox Code Playgroud) 静态链接 Boost.Log 时出现链接错误。编译器版本是g++ 4.8.1。Boost版本是1.55.0。我可以毫无问题地进行动态链接(在 make 文件中使用“-DBOOST_LOG_DYN_LINK”),但是当我进行静态链接时,会出现链接错误。在其他 boost 库上不会出现此问题。我简化了代码以轻松重现此问题:
#include <boost/log/trivial.hpp>
int main()
{
BOOST_LOG_TRIVIAL(trace) << "test trace";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
生成链接错误的构建命令:
g++ test.cpp -lboost_thread -lboost_log
Run Code Online (Sandbox Code Playgroud)
但是,如果我明确指定 lib 文件,就不会有问题:
g++ test.cpp -lboost_thread /usr/local/lib/libboost_log.a
Run Code Online (Sandbox Code Playgroud)
我还尝试添加 -L 选项并得到相同的错误:
g++ test.cpp -L/usr/local/lib -lboost_thread -lboost_log
Run Code Online (Sandbox Code Playgroud)
这是错误日志:
test.cpp:(.text+0x29): undefined reference to `boost::log::v2s_mt_posix::trivial::logger::get()'
test.cpp:(.text+0x70): undefined reference to `boost::log::v2s_mt_posix::trivial::logger::get()'
/tmp/ccDUZ2gm.o: In function `boost::log::v2s_mt_posix::record::reset()':
test.cpp:(.text._ZN5boost3log12v2s_mt_posix6record5resetEv[_ZN5boost3log12v2s_mt_posix6record5resetEv]+0x23): undefined reference to `boost::log::v2s_mt_posix::record_view::public_data::destroy(boost::log::v2s_mt_posix::record_view::public_data const*)'
/tmp/ccDUZ2gm.o: In function `boost::log::v2s_mt_posix::record boost::log::v2s_mt_posix::sources::basic_composite_logger<char, boost::log::v2s_mt_posix::sources::severity_logger_mt<boost::log::v2s_mt_posix::trivial::severity_level>, boost::log::v2s_mt_posix::sources::multi_thread_model<boost::log::v2s_mt_posix::aux::light_rw_mutex>, boost::log::v2s_mt_posix::sources::features<boost::log::v2s_mt_posix::sources::severity<boost::log::v2s_mt_posix::trivial::severity_level>, void, void, void, void, void, void, void, void, void> >::open_record<boost::parameter::aux::tagged_argument<boost::log::v2s_mt_posix::keywords::tag::severity, boost::log::v2s_mt_posix::trivial::severity_level …Run Code Online (Sandbox Code Playgroud) 我需要帮助来初始化 boost 日志记录框架,以同时记录到命名日志文件和控制台 - (命名日志文件不需要定期轮换或按照许多 boost 教程进行任何花哨的设置)。
日志文本应该同时发送到两个接收器,但是我需要将控制台输出的格式稍微不同(因为用户将看到它)。我能够使用 boost 示例代码了解记录到 2 个独立接收器的基础知识。对于我需要做的事情来说,它过于复杂,并且就访问适当的记录器而言确实令人困惑。我需要做的就是将带有时间戳的消息发送到日志文件,并具有相同的信息,而无需将时间戳或换行符发送到控制台日志(仅像我通常使用的那样显式放入新行<< std::endl)。我真的很想坚持使用 boost 的日志框架,因为它提供了未来扩展的灵活性。
在这个例子中,我尝试了tail -f日志文件 - 但是日志输出似乎不会在每个日志条目后自动刷新。尽管这对于文件日志来说不是很重要,但这对于控制台输出流至关重要,因为它代表用户将监视的实时活动。
非常感谢任何帮助,甚至更好的一些非常简单的示例代码来使基础工作正常工作。
我设置日志记录的方式(根据上面的链接)如下所示,我想用控制台记录器替换这些注册接收器之一 - 但我不确定如何操作。我希望控制台记录器能够自动刷新。
// Setup the common formatter for all sinks
logging::formatter fmt = expr::stream
<< std::setw(6) << std::setfill('0') << line_id << std::setfill(' ')
<< ": <" << severity << ">\t"
<< expr::if_(expr::has_attr(tag_attr))
[
expr::stream << "[" << tag_attr << "] "
]
<< expr::smessage;
// Initialize sinks
typedef sinks::synchronous_sink<sinks::text_ostream_backend> text_sink;
boost::shared_ptr<text_sink> sink = …Run Code Online (Sandbox Code Playgroud) 我按照Daiane Angolini编写的教程安装了Yocto 1.6并运行bitbake来设置工具链.虽然我在$ SDKTARGETSYSROOT/usr/lib下看到了大多数boost库,但似乎没有libboost_log.a和libboost_log_setup.a.我相信这些是在Boost 1.55中引入的,Yocto 1.6已经升至1.55.他们不应该在那里,或者我做错了什么?
我的.../fsl-community-bsp/build/conf/local.conf:
BB_NUMBER_THREADS ?= "${@oe.utils.cpu_count()}"
PARALLEL_MAKE ?= "-j ${@oe.utils.cpu_count()}"
MACHINE ??= 'imx6qsabresd'
DISTRO ?= 'poky'
PACKAGE_CLASSES ?= "package_rpm"
EXTRA_IMAGE_FEATURES = "debug-tweaks tools-sdk"
USER_CLASSES ?= "buildstats image-mklibs image-prelink"
PATCHRESOLVE = "noop"
BB_DISKMON_DIRS = "\
STOPTASKS,${TMPDIR},1G,100K \
STOPTASKS,${DL_DIR},1G,100K \
STOPTASKS,${SSTATE_DIR},1G,100K \
ABORT,${TMPDIR},100M,1K \
ABORT,${DL_DIR},100M,1K \
ABORT,${SSTATE_DIR},100M,1K"
PACKAGECONFIG_pn-qemu-native = "sdl"
PACKAGECONFIG_pn-nativesdk-qemu = "sdl"
ASSUME_PROVIDED += "libsdl-native"
CONF_VERSION = "1"
BB_NUMBER_THREADS = '1'
PARALLEL_MAKE = '-j 1'
DL_DIR ?= "${BSPDIR}/downloads/"
ACCEPT_FSL_EULA = ""
CORE_IMAGE_EXTRA_INSTALL += "boost"
Run Code Online (Sandbox Code Playgroud) 我最近尝试通过 Boost log 将一些日志记录添加到一个小型应用程序中。但是,使用日志轮换,由于某种原因,我无法让它在日志目录中拾取正确的计数器。
例如,如果我的Logs目录包含文件Log_000.log并且Log_001.log我希望日志记录以Log_002.log,但它总是从 0 开始。
我可能错过了一些东西,但如果有人能发现一些东西,我将不胜感激。这是我的启动代码:
void initLogging()
{
boost::log::add_common_attributes();
auto core = boost::log::core::get();
core->add_global_attribute("UTCTimeStamp",boost::log::attributes::utc_clock());
auto x = boost::log::add_file_log(
boost::log::keywords::file_name = "Log_%3N.log",
boost::log::keywords::rotation_size = 2 * 1024, // 2k
boost::log::keywords::target = "Logs",
boost::log::keywords::min_free_space = 30 * 1024 * 1024,
boost::log::keywords::max_size = 20 * 1024, // 20k
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(boost::gregorian::greg_day(31)),
boost::log::keywords::scan_method = boost::log::sinks::file::scan_matching,
boost::log::keywords::format = "%UTCTimeStamp% (%TimeStamp%) [%ThreadID%]: %Message%",
boost::log::keywords::auto_flush = true
);
auto d = x->locked_backend()->scan_for_files();
}
Run Code Online (Sandbox Code Playgroud)
非常感谢
首先,我认为这个问题超出了C++标准。该标准处理多个翻译单元(实例化单元),从而处理多个目标模块,但似乎没有承认具有多个独立编译和链接的二进制模块(即.soLinux 上的文件和.dllWindows 上的文件)的可能性。毕竟,后者或多或少地进入了应用程序二进制接口(ABI)的世界,标准目前将其留给实现来考虑。
当仅涉及单个二进制模块时,以下代码片段说明了一个优雅且可移植(符合标准)的单例解决方案。
inline T& get() {
static T var{};
return var;
}
Run Code Online (Sandbox Code Playgroud)
此解决方案有两点需要注意。首先,inline说明符使该函数成为包含在多个翻译单元中的候选函数,这非常方便。请注意,该标准保证最终二进制模块中只有一个实例get()和局部静态变量(请参见此处)。var
第二件需要注意的事情是,从 C++11 开始,静态局部变量的初始化是正确同步的(请参阅此处的静态局部变量部分)。因此,并发调用就可以了。get()
现在,我尝试将此解决方案扩展到涉及多个二进制模块的情况。我发现以下变体适用于 Windows 上的 VC++。
// dllexport is used in building the library module, and
// dllimport is used in using the library in an application module.
// Usually controlled by a macro switch.
__declspec(dllexport/dllimport) inline T& get() {
static T var{};
return var;
} …Run Code Online (Sandbox Code Playgroud) 在Boost.Log文档中,据说是这样的
注意
库使用
basic_formatting_ostream流类型进行记录格式化,因此在自定义属性值格式化规则时,operator<<必须使用basic_formatting_ostream而不是std::ostream.
然而,在整个文档中,我看到的是超载operator <<的std::ostream,而不是basic_formatting_ostream在示例代码.例如,请在severity_level 此处查看自定义类型的重载.
根据我的测试,过载std::ostream和basic_formatting_ostream两者都很好.所以,我想知道在一个而不是另一个上重载的优点是什么.
我正在使用自定义boost::log格式化程序对输出日志消息进行颜色编码,但我找不到将TimeStamp和ThreadID属性添加到日志的正确方法。当我使用文件日志记录时,我只是将其写keywords::format = "[%TimeStamp%] [%ThreadID%] [%Severity%]: %Message%"为logging::add_file_log参数。我想在以下自定义格式化程序中具有类似的效果:
void coloring_formatter(const logging::record_view& record,
logging::formatting_ostream& stream)
{
auto severity = record[logging::trivial::severity];
assert(severity);
stream << "\e[1m";
switch (severity.get())
{
case logging::trivial::severity_level::trace:
stream << "\e[97m";
break;
case logging::trivial::severity_level::debug:
stream << "\e[34m";
break;
case logging::trivial::severity_level::info:
stream << "\e[32m";
break;
case logging::trivial::severity_level::warning:
stream << "\e[93m";
break;
case logging::trivial::severity_level::error:
stream << "\e[91m";
break;
case logging::trivial::severity_level::fatal:
stream << "\e[41m";
break;
}
stream // << output TimeStamp
// << output ThreadID …Run Code Online (Sandbox Code Playgroud) 我有一个使用增强日志记录的应用程序。在关闭期间,它会因空指针访问而发生访问冲突。当我单步执行代码直至失败时,似乎 boost::log dll 正在被解除分配,然后 boost::thread 代码尝试访问曾经被 log dll 占用的内存。
我没有在自己的代码中使用任何 boost 线程,因此假设 boost-thread dll 由 boost log 使用。
为了确保所有接收器在关闭之前被销毁,我调用: core->flush() 和 core->remove_all_sinks()
我正在使用 boost 1.60,并且也尝试过使用 boost 1.63。相同的结果。
有没有办法确保在退出/卸载 dll 之前完全关闭 boost 日志记录核心?