fix: portability patch for OS other than Linux
- Test for sys headers and disable depth/name if not found - Update the doc and bump to 0.3.
This commit is contained in:
parent
008aa7cf31
commit
3a4bdc0d57
4 changed files with 85 additions and 19 deletions
|
|
@ -12,7 +12,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
## Current version
|
## Current version
|
||||||
set(VERSION_MAJOR 0 CACHE STRING "Major version number" )
|
set(VERSION_MAJOR 0 CACHE STRING "Major version number" )
|
||||||
set(VERSION_MINOR 2 CACHE STRING "Minor version number" )
|
set(VERSION_MINOR 3 CACHE STRING "Minor version number" )
|
||||||
set(VERSION_PATCH 0 CACHE STRING "Patch version number" )
|
set(VERSION_PATCH 0 CACHE STRING "Patch version number" )
|
||||||
mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH)
|
mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH)
|
||||||
|
|
||||||
|
|
|
||||||
16
README.md
16
README.md
|
|
@ -12,7 +12,8 @@ Clutchlog allows to select which log messages will be displayed, based on their
|
||||||
- *source code location*: you can ask to display messages called from given files, functions and line number, all based on
|
- *source code location*: you can ask to display messages called from given files, functions and line number, all based on
|
||||||
regular expressions.
|
regular expressions.
|
||||||
|
|
||||||
Of course, Clutchlog is disabled by default if not in "Debug" mode.
|
Additionally, Clutchlog will do its best to allow the compiler to optimize out calls,
|
||||||
|
for instance debug messages in "Release" builds.
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
|
|
@ -182,7 +183,7 @@ for log levels which are under or equal to `progress`.
|
||||||
You can change this behavior at compile time by setting the
|
You can change this behavior at compile time by setting the
|
||||||
`CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG` preprocessor variable
|
`CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG` preprocessor variable
|
||||||
to the desired maximum log level, for example:
|
to the desired maximum log level, for example:
|
||||||
```
|
```cpp
|
||||||
// Will always allow to log everything even in Release mode.
|
// Will always allow to log everything even in Release mode.
|
||||||
#define CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG clutchlog::level::xdebug
|
#define CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG clutchlog::level::xdebug
|
||||||
```
|
```
|
||||||
|
|
@ -223,8 +224,13 @@ log.dump(clutchlog::level::xdebug, cont.begin(), cont.end(), "main.cpp", "main",
|
||||||
Limitations
|
Limitations
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Because the call stack depth and binary name access are system-dependent,
|
Because the call stack depth and program name access are system-dependent,
|
||||||
Clutchlog is only implemented for Linux at the moment.
|
the features relying on the depth of the call stack and the display of the program name
|
||||||
|
are only available for operating systems having the following headers:
|
||||||
|
`execinfo.h`, `stdlib.h` and `libgen.h` (so far, tested with Linux).
|
||||||
|
|
||||||
|
Clutchlog needs `C++-17` with the `filesystem` feature.
|
||||||
|
You may need to indicate `-std=c++17 -lstdc++fs` to your compiler.
|
||||||
|
|
||||||
|
|
||||||
Build and tests
|
Build and tests
|
||||||
|
|
@ -235,7 +241,7 @@ and either ensure that the `NDEBUG` preprocessor variable is not set,
|
||||||
either define the `WITH_CLUTCHLOG` preprocessor variable.
|
either define the `WITH_CLUTCHLOG` preprocessor variable.
|
||||||
|
|
||||||
If you're using CMake (or another modern build system),
|
If you're using CMake (or another modern build system),
|
||||||
it will unset `NDEBUG` ---and thus enable clutchlog---
|
it will unset `NDEBUG` —and thus enable clutchlog—
|
||||||
only for the "Debug" build type,
|
only for the "Debug" build type,
|
||||||
which is usually what you want if you use clutchlog, anyway.
|
which is usually what you want if you use clutchlog, anyway.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,19 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
// #include <iomanip>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
// #ifdef __unix__
|
#if __has_include(<execinfo.h>) && __has_include(<stdlib.h>) && __has_include(<libgen.h>)
|
||||||
#include <execinfo.h>
|
#include <execinfo.h> // execinfo
|
||||||
#include <stdlib.h>
|
#include <stdlib.h> // getenv
|
||||||
#include <libgen.h>
|
#include <libgen.h> // basename
|
||||||
// #endif
|
#define CLUTCHLOG_HAVE_UNIX_SYSINFO 1
|
||||||
|
#else
|
||||||
|
#define CLUTCHLOG_HAVE_UNIX_SYSINFO 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Enable by default in Debug builds.
|
* Enable by default in Debug builds.
|
||||||
|
|
@ -36,12 +38,20 @@
|
||||||
|
|
||||||
#ifndef CLUTCHLOG_DEFAULT_FORMAT
|
#ifndef CLUTCHLOG_DEFAULT_FORMAT
|
||||||
//! Default format of the messages.
|
//! Default format of the messages.
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
#define CLUTCHLOG_DEFAULT_FORMAT "[{name}] {level_letter}:{depth_marks} {msg}\t\t\t\t\t{func} @ {file}:{line}\n"
|
#define CLUTCHLOG_DEFAULT_FORMAT "[{name}] {level_letter}:{depth_marks} {msg}\t\t\t\t\t{func} @ {file}:{line}\n"
|
||||||
|
#else
|
||||||
|
#define CLUTCHLOG_DEFAULT_FORMAT "{level_letter} {msg}\t\t\t\t\t{func} @ {file}:{line}\n"
|
||||||
|
#endif
|
||||||
#endif // CLUTCHLOG_DEFAULT_FORMAT
|
#endif // CLUTCHLOG_DEFAULT_FORMAT
|
||||||
|
|
||||||
#ifndef CLUTCHDUMP_DEFAULT_FORMAT
|
#ifndef CLUTCHDUMP_DEFAULT_FORMAT
|
||||||
//! Default format of the comment line in file dump.
|
//! Default format of the comment line in file dump.
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
#define CLUTCHDUMP_DEFAULT_FORMAT "# [{name}] {level} in {func} (at depth {depth}) @ {file}:{line}"
|
#define CLUTCHDUMP_DEFAULT_FORMAT "# [{name}] {level} in {func} (at depth {depth}) @ {file}:{line}"
|
||||||
|
#else
|
||||||
|
#define CLUTCHDUMP_DEFAULT_FORMAT "# {level} in {func} @ {file}:{line}"
|
||||||
|
#endif
|
||||||
#endif // CLUTCHDUMP_DEFAULT_FORMAT
|
#endif // CLUTCHDUMP_DEFAULT_FORMAT
|
||||||
|
|
||||||
#ifndef CLUTCHDUMP_DEFAULT_SEP
|
#ifndef CLUTCHDUMP_DEFAULT_SEP
|
||||||
|
|
@ -150,12 +160,14 @@ class clutchlog
|
||||||
_format_log(CLUTCHLOG_DEFAULT_FORMAT),
|
_format_log(CLUTCHLOG_DEFAULT_FORMAT),
|
||||||
_format_dump(CLUTCHDUMP_DEFAULT_FORMAT),
|
_format_dump(CLUTCHDUMP_DEFAULT_FORMAT),
|
||||||
_out(&std::clog),
|
_out(&std::clog),
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
_depth(std::numeric_limits<size_t>::max() - _strip_calls),
|
_depth(std::numeric_limits<size_t>::max() - _strip_calls),
|
||||||
|
_depth_mark(CLUTCHLOG_DEFAULT_DEPTH_MARK),
|
||||||
|
#endif
|
||||||
_stage(level::error),
|
_stage(level::error),
|
||||||
_in_file(".*"),
|
_in_file(".*"),
|
||||||
_in_func(".*"),
|
_in_func(".*"),
|
||||||
_in_line(".*"),
|
_in_line(".*")
|
||||||
_depth_mark(CLUTCHLOG_DEFAULT_DEPTH_MARK)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -164,22 +176,28 @@ class clutchlog
|
||||||
std::string _format_log;
|
std::string _format_log;
|
||||||
std::string _format_dump;
|
std::string _format_dump;
|
||||||
std::ostream* _out;
|
std::ostream* _out;
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
size_t _depth;
|
size_t _depth;
|
||||||
|
std::string _depth_mark;
|
||||||
|
#endif
|
||||||
level _stage;
|
level _stage;
|
||||||
std::regex _in_file;
|
std::regex _in_file;
|
||||||
std::regex _in_func;
|
std::regex _in_func;
|
||||||
std::regex _in_line;
|
std::regex _in_line;
|
||||||
std::string _depth_mark;
|
|
||||||
|
|
||||||
struct scope_t {
|
struct scope_t {
|
||||||
bool matches; // everything is compatible
|
bool matches; // everything is compatible
|
||||||
level stage; // current log level
|
level stage; // current log level
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
size_t depth; // current depth
|
size_t depth; // current depth
|
||||||
|
#endif
|
||||||
bool there; // location is compatible
|
bool there; // location is compatible
|
||||||
scope_t() :
|
scope_t() :
|
||||||
matches(false),
|
matches(false),
|
||||||
stage(level::xdebug),
|
stage(level::xdebug),
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
depth(0),
|
depth(0),
|
||||||
|
#endif
|
||||||
there(false)
|
there(false)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
@ -203,6 +221,7 @@ class clutchlog
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
/***** Stack depth *****/
|
/***** Stack depth *****/
|
||||||
// Backtrace in second, quite fast.
|
// Backtrace in second, quite fast.
|
||||||
const size_t max_buffer = 4096;
|
const size_t max_buffer = 4096;
|
||||||
|
|
@ -214,6 +233,7 @@ class clutchlog
|
||||||
// Bypass if no match.
|
// Bypass if no match.
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/***** Location *****/
|
/***** Location *****/
|
||||||
// Location last, slowest.
|
// Location last, slowest.
|
||||||
|
|
@ -244,11 +264,13 @@ class clutchlog
|
||||||
void out(std::ostream& out) {_out = &out;}
|
void out(std::ostream& out) {_out = &out;}
|
||||||
std::ostream& out() {return *_out;}
|
std::ostream& out() {return *_out;}
|
||||||
|
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
void depth(size_t d) {_depth = d;}
|
void depth(size_t d) {_depth = d;}
|
||||||
size_t depth() const {return _depth;}
|
size_t depth() const {return _depth;}
|
||||||
|
|
||||||
void depth_mark(std::string mark) {_depth_mark = mark;}
|
void depth_mark(std::string mark) {_depth_mark = mark;}
|
||||||
std::string depth_mark() const {return _depth_mark;}
|
std::string depth_mark() const {return _depth_mark;}
|
||||||
|
#endif
|
||||||
|
|
||||||
void threshold(level l) {_stage = l;}
|
void threshold(level l) {_stage = l;}
|
||||||
level threshold() const {return _stage;}
|
level threshold() const {return _stage;}
|
||||||
|
|
@ -351,30 +373,38 @@ class clutchlog
|
||||||
std::string format(
|
std::string format(
|
||||||
std::string format,
|
std::string format,
|
||||||
const std::string& what,
|
const std::string& what,
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
|
#endif
|
||||||
const level& stage,
|
const level& stage,
|
||||||
const std::string& file,
|
const std::string& file,
|
||||||
const std::string& func,
|
const std::string& func,
|
||||||
const size_t line,
|
const size_t line
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
|
,
|
||||||
const size_t depth
|
const size_t depth
|
||||||
|
#endif
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
format = replace(format, "\\{msg\\}", what);
|
format = replace(format, "\\{msg\\}", what);
|
||||||
format = replace(format, "\\{name\\}", name);
|
|
||||||
format = replace(format, "\\{file\\}", file);
|
format = replace(format, "\\{file\\}", file);
|
||||||
format = replace(format, "\\{func\\}", func);
|
format = replace(format, "\\{func\\}", func);
|
||||||
format = replace(format, "\\{level\\}", _level_words.at(stage));
|
format = replace(format, "\\{level\\}", _level_words.at(stage));
|
||||||
format = replace(format, "\\{line\\}", line);
|
format = replace(format, "\\{line\\}", line);
|
||||||
format = replace(format, "\\{depth\\}", depth);
|
|
||||||
|
|
||||||
std::string letter(1, _level_words.at(stage).at(0)); // char -> string
|
std::string letter(1, _level_words.at(stage).at(0)); // char -> string
|
||||||
format = replace(format, "\\{level_letter\\}", letter);
|
format = replace(format, "\\{level_letter\\}", letter);
|
||||||
|
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
|
format = replace(format, "\\{name\\}", name);
|
||||||
|
format = replace(format, "\\{depth\\}", depth);
|
||||||
|
|
||||||
std::ostringstream chevrons;
|
std::ostringstream chevrons;
|
||||||
for(size_t i = _strip_calls; i < depth; ++i) {
|
for(size_t i = _strip_calls; i < depth; ++i) {
|
||||||
chevrons << ">";
|
chevrons << ">";
|
||||||
}
|
}
|
||||||
format = replace(format, "\\{depth_marks\\}", chevrons.str());
|
format = replace(format, "\\{depth_marks\\}", chevrons.str());
|
||||||
|
#endif
|
||||||
|
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
@ -388,9 +418,16 @@ class clutchlog
|
||||||
scope_t scope = locate(stage, file, func, line);
|
scope_t scope = locate(stage, file, func, line);
|
||||||
|
|
||||||
if(scope.matches) {
|
if(scope.matches) {
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
*_out << format(_format_log, what, basename(getenv("_")),
|
*_out << format(_format_log, what, basename(getenv("_")),
|
||||||
stage, file, func,
|
stage, file, func,
|
||||||
line, scope.depth );
|
line, scope.depth );
|
||||||
|
#else
|
||||||
|
*_out << format(_format_log, what,
|
||||||
|
stage, file, func,
|
||||||
|
line );
|
||||||
|
|
||||||
|
#endif
|
||||||
_out->flush();
|
_out->flush();
|
||||||
} // if scopes.matches
|
} // if scopes.matches
|
||||||
}
|
}
|
||||||
|
|
@ -428,9 +465,15 @@ class clutchlog
|
||||||
std::ofstream fd(outfile);
|
std::ofstream fd(outfile);
|
||||||
|
|
||||||
if(_format_dump.size() > 0) {
|
if(_format_dump.size() > 0) {
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
fd << format(_format_dump, "", basename(getenv("_")),
|
fd << format(_format_dump, "", basename(getenv("_")),
|
||||||
stage, file, func,
|
stage, file, func,
|
||||||
line, scope.depth );
|
line, scope.depth );
|
||||||
|
#else
|
||||||
|
fd << format(_format_dump, "",
|
||||||
|
stage, file, func,
|
||||||
|
line );
|
||||||
|
#endif
|
||||||
fd << sep; // sep after comment line.
|
fd << sep; // sep after comment line.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -479,11 +522,13 @@ class clutchlog
|
||||||
void out(std::ostream&) {}
|
void out(std::ostream&) {}
|
||||||
std::ostream& out() {}
|
std::ostream& out() {}
|
||||||
|
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
void depth(size_t) {}
|
void depth(size_t) {}
|
||||||
size_t depth() const {}
|
size_t depth() const {}
|
||||||
|
|
||||||
void depth_mark(std::string) {}
|
void depth_mark(std::string) {}
|
||||||
std::string depth_mark() const {}
|
std::string depth_mark() const {}
|
||||||
|
#endif
|
||||||
|
|
||||||
void threshold(level) {}
|
void threshold(level) {}
|
||||||
level threshold() const {}
|
level threshold() const {}
|
||||||
|
|
@ -519,12 +564,17 @@ class clutchlog
|
||||||
std::string format(
|
std::string format(
|
||||||
std::string,
|
std::string,
|
||||||
const std::string&,
|
const std::string&,
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
const std::string&,
|
const std::string&,
|
||||||
|
#endif
|
||||||
const level&,
|
const level&,
|
||||||
const std::string&,
|
const std::string&,
|
||||||
const std::string&,
|
const std::string&,
|
||||||
const size_t,
|
|
||||||
const size_t
|
const size_t
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
|
,
|
||||||
|
const size_t
|
||||||
|
#endif
|
||||||
) const
|
) const
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,31 +27,41 @@ int main(/*const int argc, char* argv[]*/)
|
||||||
log.out(std::clog);
|
log.out(std::clog);
|
||||||
|
|
||||||
std::clog << "depth: 99; threshold: xdebug; location: .*" << std::endl;
|
std::clog << "depth: 99; threshold: xdebug; location: .*" << std::endl;
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
log.depth(99);
|
log.depth(99);
|
||||||
|
#endif
|
||||||
log.threshold(clutchlog::level::xdebug);
|
log.threshold(clutchlog::level::xdebug);
|
||||||
log.location(".*",".*");
|
log.location(".*",".*");
|
||||||
f();
|
f();
|
||||||
|
|
||||||
std::clog << "depth: 4; threshold: xdebug; location: ,*" << std::endl;
|
std::clog << "depth: 4; threshold: xdebug; location: ,*" << std::endl;
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
log.depth(4);
|
log.depth(4);
|
||||||
|
#endif
|
||||||
log.threshold(clutchlog::level::xdebug);
|
log.threshold(clutchlog::level::xdebug);
|
||||||
log.location(".*");
|
log.location(".*");
|
||||||
f();
|
f();
|
||||||
|
|
||||||
std::clog << "depth: 99; threshold: warning; location: .*" << std::endl;
|
std::clog << "depth: 99; threshold: warning; location: .*" << std::endl;
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
log.depth(99);
|
log.depth(99);
|
||||||
|
#endif
|
||||||
log.threshold(clutchlog::level::warning);
|
log.threshold(clutchlog::level::warning);
|
||||||
log.location(".*");
|
log.location(".*");
|
||||||
f();
|
f();
|
||||||
|
|
||||||
std::clog << "depth: 99; threshold: xdebug; location: 'core','g'" << std::endl;
|
std::clog << "depth: 99; threshold: xdebug; location: 'core','g'" << std::endl;
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
log.depth(99);
|
log.depth(99);
|
||||||
|
#endif
|
||||||
log.threshold(clutchlog::level::xdebug);
|
log.threshold(clutchlog::level::xdebug);
|
||||||
log.location("core","g");
|
log.location("core","g");
|
||||||
f();
|
f();
|
||||||
|
|
||||||
std::clog << "depth: 99; threshold: debug; location: '.*','(g|h)'" << std::endl;
|
std::clog << "depth: 99; threshold: debug; location: '.*','(g|h)'" << std::endl;
|
||||||
|
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
|
||||||
log.depth(99);
|
log.depth(99);
|
||||||
|
#endif
|
||||||
log.threshold(clutchlog::level::debug);
|
log.threshold(clutchlog::level::debug);
|
||||||
log.location(".*","(g|h)");
|
log.location(".*","(g|h)");
|
||||||
f();
|
f();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue