使用宏优化编译时日志记录

问题描述 投票:0回答:1

我想为嵌入式设备编写一个 C++ 日志记录类。 非常重要的是,未“激活”的日志指令会被预处理器优化掉!

到目前为止,我做了类似的事情:

#define LOGLEVEL 3

#if LOGLEVEL > 3
#define LOG_DEBUG(...) Serial.printf(__VA_ARGS__)
#else
#define LOG_DEBUG()
#endif

#if LOGLEVEL > 2
#define LOG_INFO(...) Serial.printf(__VA_ARGS__)
#else
#define LOG_INFO()
#endif

LOG_DEBUG("var a is: &d", a); // will be completely optimized out
LOG_INFO("var b is: %f", b);

现在我想要更复杂一点,具有更可调的输出:

#define LOGLEVEL 5
#define LOGAREAS LOGAREA_THIS | LOGAREAS_THAT

#define LOGAREA_THIS 0x01
#define LOGAREA_THAT 0x02
#define LOGAREA_FOO 0x04
#define LOGAREA_BAR 0x08


#if LOGLEVEL > 4
#define LOG_TRACE(x, ...) if(x & LOGAREAS) Serial.printf(__VA_ARGS__)
#else
#define LOG_TRACE()
#endif

LOG_TRACE(LOGAREA_THIS, "var b is: %f", b);
LOG_TRACE(LOGAREA_FOO | LOGAREA_BAR , "var a is: &d", a); // only displayed if LOGAREA_FOO or LOGAREA_BAR is selected

问题在于该代码,未选择的消息仍然在 cpp 代码中,并且没有优化(用于调试)仍然可以进入我的二进制文件......

有没有一种具有类似可用性的方法,可以让我做我想做的事情,完全删除未使用的消息?

c++ logging macros
1个回答
0
投票

这里不需要宏。

constexpr auto LOGAREA_THIS = 0x01;
constexpr auto LOGAREA_THAT = 0x02;
constexpr auto LOGAREA_FOO = 0x04;
constexpr auto LOGAREA_BAR = 0x08;

constexpr auto LOGLEVEL = 5;
constexpr auto LOGAREAS = LOGAREA_THIS | LOGAREAS_THAT;

template<auto x, typename... Params>
constexpr void LOG_TRACE(const char* fmt, Params&&... params) {
    if constexpr((LOGLEVEL > 4) && (x & LOGAREAS))
        Serial.printf(fmt, std::forward<Params>(params)...);
}

//...

LOG_TRACE<LOGAREA_THIS>("var b is: %f", b);
LOG_TRACE<LOGAREA_FOO | LOGAREA_BAR>("var a is: &d", a);

在某些情况下,编译器可能不会内联对

LOG_TRACE
的调用,例如if 在
-O0
中构建,并且 if
LOG_TRACE
被使用相同的日志标志和参数类型多次调用。在这种情况下,向
[[gnu:always_inline]]
添加一些特定于编译器的
__forceinline
LOG_TRACE
类型属性会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.