log4cplus (現在の git master からコンパイル) を使用していますが、リンカーによって未定義の参照エラーが発生します。ただし、これらのエラーは一部のクラスでのみ発生します。
一般に、各クラスには次の形式があります。
ヘッダー (.h)
// ...
#include <log4cplus/loggingmacros.h>
// ...
// namespace(s)
class Example
{
public:
// ...
private:
// ...
static const log4cplus::Logger logger;
};
ソース (.cpp)
// includes
// namespace(s)
// implementations
const log4cplus::Logger Example::logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("Example"));
使用法
ロガーは、次のようにクラス内で使用されます。
LOG4CPLUS_WARN(logger, "Ha, ha – whatever you try I wont work!");
コンパイルが機能している間、リンカーは未定義の参照エラーを発生させます
log4cplus::Logger::getInstance(std::string const&)
と
log4cplus::detail::macro_forced_log(log4cplus::Logger const&, int, std::string const&, char const*, int, char const*)
いくつかのクラスのために。私はすでに作業クラスからロガー部分をコピーしました:同じ結果。
静的ロガーをクラスメンバーに置き換えても機能しません -getInstance()
見つかりません。
この問題の回避策は、代わりにルートロガーを使用することです。これはコンパイル/リンクします(getRoot()
同じクラスの一部ですが!?):
const log4cplus::Logger Example::logger = log4cplus::Logger::getRoot();
しかし、未定義の参照エラーがあります
log4cplus::detail::macro_forced_log(...)
タイプミスがないことを確認するために、宣言/定義にこれらのマクロを使用しました。
#define LOG_DECL(name) static const log4cplus::Logger logger
#define LOG_DEF(name) const log4cplus::Logger name::logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT(#name))
同じ結果で、以前は機能していたものも機能し、そうでないものも機能しませんでした。
詳しくは:
- Log4cplus は -llog4cplusSU (log4cplusS でもテスト済み) を使用してリンクされ、git master からコンパイルされました
- GCC 4.9 – C++11 を使用
- プロジェクトをビルドするための Eclipse CDT
- Log4cplus はメインで初期化されます
- すべてのクラスは、同じコンパイラとフラグを使用してコンパイルされます
- 完全にクリーン アンド ビルドのプロジェクト
- すべてのファイルは同じ方法でコンパイル/リンクされます
- const / not const は効果がありません
の結果nm <NAME>.o | grep -i log4cplus
:
作業対象
U _ZN9log4cplus6detail16macro_forced_logERKNS_6LoggerEiRKSbIwSt11char_traitsIwESaIwEEPKciSB_
0000000000000000 W _ZN9log4cplus6detail17macros_get_loggerERKNS_6LoggerE
U _ZN9log4cplus6detail18get_macro_body_ossEv
U _ZN9log4cplus6Logger11getInstanceERKSbIwSt11char_traitsIwESaIwEE
U _ZN9log4cplus6LoggerC1ERKS0_
U _ZN9log4cplus6LoggerD1Ev
00000000000002c8 r _ZN9log4cplusL13ALL_LOG_LEVELE
00000000000002ac r _ZN9log4cplusL13OFF_LOG_LEVELE
00000000000002bc r _ZN9log4cplusL14INFO_LOG_LEVELE
00000000000002b8 r _ZN9log4cplusL14WARN_LOG_LEVELE
00000000000002c0 r _ZN9log4cplusL15DEBUG_LOG_LEVELE
00000000000002b4 r _ZN9log4cplusL15ERROR_LOG_LEVELE
00000000000002b0 r _ZN9log4cplusL15FATAL_LOG_LEVELE
00000000000002c4 r _ZN9log4cplusL15TRACE_LOG_LEVELE
00000000000002cc r _ZN9log4cplusL17NOT_SET_LOG_LEVELE
U _ZNK9log4cplus6Logger12isEnabledForEi
未定義の参照がある場合:
U _ZN9log4cplus6detail16macro_forced_logERKNS_6LoggerEiRKSsPKciS7_
0000000000000000 W _ZN9log4cplus6detail17macros_get_loggerERKNS_6LoggerE
U _ZN9log4cplus6detail18get_macro_body_ossEv
U _ZN9log4cplus6Logger11getInstanceERKSs
U _ZN9log4cplus6LoggerC1ERKS0_
U _ZN9log4cplus6LoggerD1Ev
00000000000001ec r _ZN9log4cplusL13ALL_LOG_LEVELE
00000000000001d0 r _ZN9log4cplusL13OFF_LOG_LEVELE
00000000000001e0 r _ZN9log4cplusL14INFO_LOG_LEVELE
00000000000001dc r _ZN9log4cplusL14WARN_LOG_LEVELE
00000000000001e4 r _ZN9log4cplusL15DEBUG_LOG_LEVELE
00000000000001d8 r _ZN9log4cplusL15ERROR_LOG_LEVELE
00000000000001d4 r _ZN9log4cplusL15FATAL_LOG_LEVELE
00000000000001e8 r _ZN9log4cplusL15TRACE_LOG_LEVELE
00000000000001f0 r _ZN9log4cplusL17NOT_SET_LOG_LEVELE
U _ZNK9log4cplus6Logger12isEnabledForEi
失敗する最小限のクラス
//////////////////////// Header ////////////////////////
namespace so {
namespace example {
class FailingExample
{
public:
FailingExample(other_ns::Config* config, other_ns::Command* cmd);
bool updateData(uint8_t* dataPtr, uint32_t dataSize);
virtual ~FailingExample();
private:
static const log4cplus::Logger logger;
};
}}
//////////////////////// Source ////////////////////////
namespace so {
namespace example {
FailingExample::FailingExample(other_ns::Config* config, other_ns::Command* cmd)
{
}
bool FailingExample::updateData(uint8_t* dataPtr, uint32_t dataSize)
{
return true;
}
FailingExample::~FailingExample()
{
}
// Undefined reference to getInstance() here
const log4cplus::Logger FailingExample::logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("FailingExample"));
}}