77//
88#pragma once
99
10- #if !defined(_WIN32) && !defined(_WIN64)
10+ // Feature detection: backtrace support
11+ #if !defined(GUNIT_HAS_BACKTRACE)
12+ #if (defined(__APPLE__) || defined(__linux__)) && !defined(__ZEPHYR__)
13+ #define GUNIT_HAS_BACKTRACE 1
14+ #else
15+ #define GUNIT_HAS_BACKTRACE 0
16+ #endif
17+ #endif
18+
19+ // Feature detection: addr2line support (requires popen/pclose)
20+ #if !defined(GUNIT_HAS_ADDR2LINE)
21+ #if (defined(__APPLE__) || defined(__linux__)) && !defined(__ZEPHYR__)
22+ #define GUNIT_HAS_ADDR2LINE 1
23+ #else
24+ #define GUNIT_HAS_ADDR2LINE 0
25+ #endif
26+ #endif
27+
28+ // Feature detection: C++ name demangling
29+ #if !defined(GUNIT_HAS_DEMANGLE)
30+ #if !defined(_WIN32) && !defined(_WIN64) && !defined(__ZEPHYR__)
31+ #define GUNIT_HAS_DEMANGLE 1
32+ #else
33+ #define GUNIT_HAS_DEMANGLE 0
34+ #endif
35+ #endif
36+
37+ // Feature detection: program name
38+ #if !defined(GUNIT_HAS_PROGNAME)
39+ #if (defined(__APPLE__) || defined(__linux__)) && !defined(__ZEPHYR__)
40+ #define GUNIT_HAS_PROGNAME 1
41+ #else
42+ #define GUNIT_HAS_PROGNAME 0
43+ #endif
44+ #endif
45+
46+ #if GUNIT_HAS_DEMANGLE
1147#include < cxxabi.h>
1248#endif
1349
1652
1753#include " gtest/gtest.h"
1854
19- #if defined(__APPLE__) || defined(__linux__)
55+ #if GUNIT_HAS_BACKTRACE
2056#include < execinfo.h>
2157#endif
2258
2359#if defined(__APPLE__)
2460#include < libproc.h>
25- #elif defined(__linux__)
61+ #elif GUNIT_HAS_PROGNAME && defined(__linux__)
2662extern const char *__progname_full;
2763#elif defined(_WIN32)
2864static const char *__progname_full = " progname_not_availabe_on_WIN32" ;
@@ -37,43 +73,42 @@ inline namespace v1 {
3773namespace detail {
3874
3975inline std::string demangle (const std::string &mangled) {
40- #if !defined(_WIN32) && !defined(_WIN64)
76+ #if GUNIT_HAS_DEMANGLE
4177 const auto demangled = abi::__cxa_demangle (mangled.c_str (), 0 , 0 , 0 );
4278 if (demangled) {
4379 std::shared_ptr<char > free{demangled, std::free};
4480 return demangled;
4581 }
82+ return {};
4683#else
4784 return mangled;
4885#endif
49- return {};
5086}
5187
5288inline auto &progname () {
53- #if defined(__linux__)
54- static auto self = __progname_full;
55- #elif defined(__APPLE__)
56- static char self[PROC_PIDPATHINFO_MAXSIZE] = {};
57- proc_pidpath (getpid (), self, sizeof (self));
89+ #if GUNIT_HAS_PROGNAME
90+ #if defined(__APPLE__)
91+ static char self[PROC_PIDPATHINFO_MAXSIZE] = {};
92+ proc_pidpath (getpid (), self, sizeof (self));
93+ #elif defined(__linux__)
94+ static auto self = __progname_full;
95+ #endif
5896#elif defined(_WIN32)
5997 static auto self = __progname_full;
98+ #else
99+ static const char *self = " embedded_target" ;
60100#endif
61101 return self;
62102}
63103
64104inline std::string call_stack (const std::string &newline, int stack_begin = 1 ,
65105 int stack_size = GUNIT_SHOW_STACK_SIZE) {
66- #if defined(_WIN32)
67- (void )newline;
68- (void )stack_begin;
69- (void )stack_size;
70- return " callstack not availabe on WIN32" ;
71- #else
106+ #if GUNIT_HAS_BACKTRACE
72107 static constexpr auto MAX_CALL_STACK_SIZE = 64 ;
73108 void *bt[MAX_CALL_STACK_SIZE];
74109 const auto frames = backtrace (bt, sizeof (bt) / sizeof (bt[0 ]));
75110 const auto symbols = backtrace_symbols (bt, frames);
76- std::shared_ptr<char *> free{symbols, std::free};
111+ std::shared_ptr<char *> free{symbols, []( char ** p) { std::free (p); } };
77112 std::stringstream result;
78113 stack_size += stack_begin;
79114
@@ -100,14 +135,16 @@ inline std::string call_stack(const std::string &newline, int stack_begin = 1,
100135 }
101136 }
102137 return result.str ();
138+ #else
139+ (void )newline;
140+ (void )stack_begin;
141+ (void )stack_size;
142+ return " callstack disabled or not available" ;
103143#endif
104144}
105145
106146inline std::pair<std::string, int > addr2line (void *addr) {
107- #if defined(_WIN32)
108- (void )addr;
109- return {" addr2line not availabe on WIN32" , 0 };
110- #else
147+ #if GUNIT_HAS_ADDR2LINE
111148 std::stringstream cmd;
112149 cmd << " addr2line -Cpe " << progname () << " " << addr;
113150
@@ -128,6 +165,9 @@ inline std::pair<std::string, int> addr2line(void *addr) {
128165 std::string res2 = data.substr (0 , space);
129166 const auto colon = res2.find (" :" );
130167 return {res2.substr (0 , colon), std::atoi (res2.substr (colon + 1 ).c_str ())};
168+ #else
169+ std::ignore = addr;
170+ return {" addr2line disabled or not available" , 0 };
131171#endif
132172}
133173
0 commit comments