dfeneyrou / palanteer

Visual Python and C++ nanosecond profiler, logger, tests enabler
Other
2.1k stars 88 forks source link

Question - How to use palanteer c++ library and avoid multiple definition #41

Closed Exicweirdo closed 12 months ago

Exicweirdo commented 1 year ago

For some project with c++ its always necessary to compile different part separately. However, the single-header lib seems to result in multiple definition in this case.

Take this minimum project as an example

main.cpp

#define PL_IMPLEMENTATION 1
#include "../work/palanteer/c++/palanteer.h"
#include <iostream>
int add(int a, int b);

int main() {
    plFunction();
    add(1, 2);
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

add.cpp

#define PL_IMPLEMENTATION 1
#include "../work/palanteer/c++/palanteer.h"

int add(int a, int b) {
    plFunction();
    return a + b;
}

Then compile it with

g++ -c main.cpp -o 1.o -DUSE_PL=1; g++ -c add.cpp -o 2.o -DUSE_PL=1; g++ 1.o 2.o -o ./main.out

It fails and return

...
testpl2.cpp:(.text+0x9838): multiple definition of `plGetStats()'; 1.o:testpl1.cpp:(.text+0x9838): first defined here
/usr/bin/ld: 2.o: in function `plDeclareVirtualThread(unsigned int, char const*, ...)':
testpl2.cpp:(.text+0x9879): multiple definition of `plDeclareVirtualThread(unsigned int, char const*, ...)'; 1.o:testpl1.cpp:(.text+0x9879): first defined here
/usr/bin/ld: 2.o: in function `plDetachVirtualThread(bool)':
testpl2.cpp:(.text+0x9919): multiple definition of `plDetachVirtualThread(bool)'; 1.o:testpl1.cpp:(.text+0x9919): first defined here
/usr/bin/ld: 2.o: in function `plAttachVirtualThread(unsigned int)':
testpl2.cpp:(.text+0x996e): multiple definition of `plAttachVirtualThread(unsigned int)'; 1.o:testpl1.cpp:(.text+0x996e): first defined here
collect2: error: ld returned 1 exit status

have i misunderstood sth? how to avoid this issue if i want to use palanteer?

dfeneyrou commented 1 year ago

You shall "implement the core library only once. In your example, you included it twice, hence the multiple definition issue.

So simply remove the first line #define PL_IMPLEMENTATION 1 of your file add.cpp.

The second issue is that you shall enable the library at runtime, by default it does nothing (not to be intrusive). The USE_PL compilation flag is a compile time disabling, and you set it ok. Your main function shall look like:

int main() {

    // This call starts the profiling library  in "connection mode". It requires the viewer to be launched beforehand.
    // To write rather in a file (to be imported later in the viewer), add a second argument `PL_MODE_STORE_IN_FILE`
    plInitAndStart("My test program");

    add(1, 2);
    std::cout << "Hello, World!" << std::endl;

   // This call is not mandatory, but it is cleaner
   plStopAndUninit();

    return 0;
}
Exicweirdo commented 12 months ago

Thanks a lot!