1

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.

Burkhard
  • 14,596
  • 22
  • 87
  • 108

3 Answers3

2

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.

ossandcad
  • 778
  • 5
  • 18
0

It depends on what PANTHEIOS_EXTERN_C expands to. If it expands to extern - most likely - you get the error.

I'd either remove it completely or undefine it. (I'd go with the first one, no need for it to be extern.

Note that in this case, PANTHEIOS_FE_PROCESS_IDENTITY is not a global. If you want to make it global, you declare it as extern BUT only define it in one of the translation units.

So:

If PANTHEIOS_FE_PROCESS_IDENTITY is supposed to be global:

//log1.cpp

const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PSTR("fileX.cpp"); 
//definition here

//log2.cpp

PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[]; 
//declared as extern here

If not, and you want it different for the 2 files:

//log1.cpp

const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PSTR("fileX.cpp"); //not extern
                                                                      //definition

//log2.cpp

const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PSTR("fileX.cpp"); //not extern
                                                                      //definition
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I want the second one with X=1 for log1.cpp and 2 for log2.cpp. I still get the multiple definition error when I remove PANTHEIOS_EXTERN_C. – Burkhard Apr 03 '12 at 14:54
0

If you want a const PANTHEIOS_FE_PROCESS_IDENTITY in one file, file1.cpp, and another const PANTHEIOS_FE_PROCESS_IDENTITY in another file, file2.cpp, then declare it as static and it wont be exported beyond the file.

PANTHEIOS_EXTERN_C static const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PSTR("fileX.cpp");
Motomotes
  • 4,111
  • 1
  • 25
  • 24
  • That doesn't even compile: "log1.cpp:6: error: invalid use of ‘static’ in linkage specification" – Burkhard Apr 03 '12 at 15:08