c++linkerg++pantheios

How to avoid multiple definition of PANTHEIOS_FE_PROCESS_IDENTITY?


I'm working on a project with multiple files and I need logging in each of it.

In order to compile a file I need the following:

/* Define the stock front-end process identity, so that it links when using
 * fe.N, fe.simple, etc. */
PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PSTR("fileX.cpp");

Let's say, I have log1.cpp and log2.cpp and log.h common to both files. These files get compiled to log1.o and log2.o. That works just fine.

Now, when I link these two files into one executable, I get the following error:

log2.o:(.rodata+0x11): multiple definition of `PANTHEIOS_FE_PROCESS_IDENTITY'
log1.o:(.rodata+0x45): first defined here

Now the problem is, that PANTHEIOS_FE_PROCESS_IDENTITY needs to be defined in both file1.cpp and file2.cpp in order to compile.

How do I need to change my code in order to be able to link it into an executable?

Here are the files used: log1.cpp:

#include "log.h"

const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PSTR("log1.cpp");

int main()
{
  PANTHEIOS_TRACE_NOTICE(PSTR("a string at NOTICE level"));
  return 0;
}

log2.cpp:

#include "log.h"
const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PSTR("log1.cpp");

log.h:

#ifndef LOG_H
#define LOG_H

/* Pantheios Header Files */
#include <pantheios/pantheios.h>                // Pantheios C main header
#ifndef STLSOFT_CF_SUPPORTS_VARIADIC_MACROS
# error This example uses the Tracing API, which requires that the compiler support variadic macros
#endif /* !STLSOFT_CF_SUPPORTS_VARIADIC_MACROS */
#ifdef STLSOFT_CF_FUNCTION_SYMBOL_SUPPORT
# include <string>
# define PANTHEIOS_TRACE_PREFIX     \
    (   std::basic_string< PANTHEIOS_NS_QUAL(pan_char_t)>(__FILE__ " " PANTHEIOS_STRINGIZE(__LINE__) ": ") + \
        __FUNCTION__ + \
        "(): " \
    ).c_str()
#endif /* STLSOFT_CF_FUNCTION_SYMBOL_SUPPORT */
#include <pantheios/trace.h>                    // Pantheios Trace API
#include <pantheios/pantheios.hpp>              // Pantheios C++ main header

/* Standard C/C++ Header Files */
#include <exception>                            // for std::exception
#include <new>                                  // for std::bad_alloc
#include <string>                               // for std::string
#include <stdlib.h>                             // for exit codes

#ifndef PANTHEIOS_DOCUMENTATION_SKIP_SECTION
# if defined(STLSOFT_COMPILER_IS_MSVC)
#  pragma warning(disable : 4702)
# endif /* compiler */
#endif /* !PANTHEIOS_DOCUMENTATION_SKIP_SECTION */

#define PSTR(x)         PANTHEIOS_LITERAL_STRING(x)

#include "pantheios/frontends/fe.simple.h" //for pantheios_fe_simple_setSeverityCeiling(level);

#endif //LOG_H

And the output of make:

g++ log1.cpp -c -I../pantheios-1.0.1-beta213/include -I../stlsoft-1.9.112/include
g++ log2.cpp -c -I../pantheios-1.0.1-beta213/include -I../stlsoft-1.9.112/include
g++ -o log log1.o log2.o -L../pantheios-1.0.1-beta213/lib \
        -lpantheios.1.core.gcc44\
        -lpantheios.1.be.fprintf.gcc44 -lpantheios.1.bec.fprintf.gcc44\
        -lpantheios.1.fe.simple.gcc44 -lpantheios.1.util.gcc44
log2.o:(.rodata+0x0): multiple definition of `PANTHEIOS_FE_PROCESS_IDENTITY'
log1.o:(.rodata+0x1): first defined here
/usr/bin/ld: Warning: size of symbol `PANTHEIOS_FE_PROCESS_IDENTITY' changed from 14 in log1.o to 9 in log2.o
collect2: ld returned 1 exit status

Edit: in pantheios-1.0.1-beta213/include/pantheios/frontends/stock.h:120 ‘PANTHEIOS_FE_PROCESS_IDENTITY’ is declared as extern, so I cannot redefine it as static.


Solution

  • I do apologize if my question/answer sounds odd: but why do want to define PANTHEIOS_FE_PROCESS_IDENTITY in each .cpp file? The PANTHEIOS_FE_PROCESS_IDENTITY needs to be defined only once per logging process, and is printed to the log statement at the start of each line. E.g. from my own pantheios-based logger project:

    [l.SPP.6408, 4/7/2012 6:28:44.702 PM; Notice]: .\Log.cpp(168): CLogApp::InitInstance: STARTING LOGGING

    I only have 1 PANTHEIOS_FE_PROCESS_IDENTITY defined - in Log.cpp (not the .h). as follows and is applicable for not only the LOG project but other projects in my solution (VS2005) that need access to the logger:

    PANTHEIOS_EXTERN_C const char PANTHEIOS_FE_PROCESS_IDENTITY[] = "l.SPP";

    You will get the filename+line-number from where the log statement is being printed out if you use PANTHEIOS_TRACE_NOTICE - see the example I posted above (in bold).

    I suggest that you determine if PANTHEIOS_FE_PROCESS_IDENTITY really needs to be defined per-cpp file or per-project - my experience shows the latter to be the answer.