摘要 本文使用 c/cpp 的编译宏特性, 通过编译宏 ## 拼接的技巧,在现有大量存量代码接口不变更的情况下, 完成日志字符串二进制级别的控制.
背景 要求 Release 版本在二进制中去除调试日志,而 debug 版本保持不变; 代码中已存在大量使用旧日志接口的代码, 要做到存量代码零变更.
实现 二进制级别的去除, 不可能使用函数条件判断实现, 只能通过编译宏实现.
现有一日志宏, 通过调用log_func输出日志到某个文件。
1 2 3 4 5 6 7 8 9 10 11 #define debug_log(level, format, arg...) \ do { \ log_func((level), __FILE__, __LINE__, format, ##arg); \ } while (0 ) debug_log(DLOG_DEBUG, "int_var=%d" , int_var); debug_log(DLOG_INFO, "int_var=%d" , int_var); debug_log(DLOG_ERROR, "int_var=%d" , int_var);
通过编译宏技巧##, 以及条件编译宏实现日志宏隔离, 和接口的无感知变化.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #define debug_log(level, format, arg...) \ do \ { \ log_func((level), __FILE__, __LINE__, format, ##arg); \ } while (0 ) #define LOG_MARCO(level, format, arg...) \ do \ { \ log_func((level), __FILE__, __LINE__, format, ##arg); \ } while (0 ) #ifdef RELEASE #undef debug_log #define debug_log(level, format, arg...) LOG_##level(format, ##arg) #define LOG_DLOG_DEBUG(format, arg...) #define LOG_DLOG_MASS(format, arg...) #define LOG_DLOG_INFO(format, arg...) \ LOG_MARCO(DLOG_INFO, format, ##arg) #define LOG_DLOG_ERROR(format, arg...) \ LOG_MARCO(DLOG_ERROR, format, ##arg) #endif debug_log(DEBUG, "int_var=%d" , int_var); debug_log(INFO, "int_var=%d" , int_var); debug_log(ERROR, "int_var=%d" , int_var);
其他的部分, 无非是构建脚本,cmake 和编译宏之间的控制配合,不算复杂,按下不表。
验证 二进制级别的验证,可以使用二进制查看器, 或者gnu命令strings execute_bin|grep "some debug log"
Reference C语言宏定义中#与##的用法