Fail to link GUI example

Hi,
I try to compile the GUI example buttonTest.C
At the prompt it work using .x buttonTest.C++
But if I had a main and try to compile:
produit@yoga$ c++ buttonTest.C (root-config --cflags) (root-config --glibs)
/usr/bin/ld: /tmp/ccNjYcVb.o: warning: relocation against _ZTV12ButtonWindow' in read-only section .text’
/usr/bin/ld: /tmp/ccNjYcVb.o: in function ButtonWindow::ButtonWindow()': buttonTest.C:(.text+0x60): undefined reference to vtable for ButtonWindow’
/usr/bin/ld: buttonTest.C:(.text+0x71): undefined reference to vtable for ButtonWindow' /usr/bin/ld: /tmp/ccNjYcVb.o: in function TextMargin::TextMargin(TGWindow const*, char const*)‘:
buttonTest.C:(.text._ZN10TextMarginC2EPK8TGWindowPKc[_ZN10TextMarginC5EPK8TGWindowPKc]+0x50): undefined reference to vtable for TextMargin' /usr/bin/ld: buttonTest.C:(.text._ZN10TextMarginC2EPK8TGWindowPKc[_ZN10TextMarginC5EPK8TGWindowPKc]+0x5e): undefined reference to vtable for TextMargin’
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status

I can solve some problems by using -fPIC (why it is not given by root-config?)
produit@yoga$ c++ buttonTest.C (root-config --cflags) (root-config --glibs) -f PIC
c++: error: unrecognized command-line option ‘-f’
produit@yoga$ c++ buttonTest.C (root-config --cflags) (root-config --glibs) -fPIC
/usr/bin/ld: /tmp/ccBRVDtf.o: in function ButtonWindow::ButtonWindow()': buttonTest.C:(.text+0x60): undefined reference to vtable for ButtonWindow’
/usr/bin/ld: buttonTest.C:(.text+0x75): undefined reference to vtable for ButtonWindow' /usr/bin/ld: /tmp/ccBRVDtf.o: in function TextMargin::TextMargin(TGWindow const*, char const*)‘:
buttonTest.C:(.text._ZN10TextMarginC2EPK8TGWindowPKc[_ZN10TextMarginC5EPK8TGWindowPKc]+0x50): undefined reference to vtable for TextMargin' /usr/bin/ld: buttonTest.C:(.text._ZN10TextMarginC2EPK8TGWindowPKc[_ZN10TextMarginC5EPK8TGWindowPKc]+0x62): undefined reference to vtable for TextMargin’
collect2: error: ld returned 1 exit status

_ROOT Version: 6.24/06
_Platform: Ubuntu 22.04.1 LTS
_Compiler: gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)


Hi @produit ,

indeed I get the same with my ROOT build, after adding a main function at the end of tutorials/gui/buttonTest.C:

$ g++ buttonTest.C $(root-config --libs --cflags --glibs)
/usr/bin/ld: /tmp/ccIsXq8F.o: warning: relocation against `_ZTV12ButtonWindow' in read-only section `.text'
/usr/bin/ld: /tmp/ccIsXq8F.o: in function `ButtonWindow::ButtonWindow()':
buttonTest.C:(.text+0x5c): undefined reference to `vtable for ButtonWindow'
/usr/bin/ld: buttonTest.C:(.text+0x6d): undefined reference to `vtable for ButtonWindow'
/usr/bin/ld: /tmp/ccIsXq8F.o: in function `TextMargin::TextMargin(TGWindow const*, char const*)':
buttonTest.C:(.text._ZN10TextMarginC2EPK8TGWindowPKc[_ZN10TextMarginC5EPK8TGWindowPKc]+0x4c): undefined reference to `vtable for TextMargin'
/usr/bin/ld: buttonTest.C:(.text._ZN10TextMarginC2EPK8TGWindowPKc[_ZN10TextMarginC5EPK8TGWindowPKc]+0x5a): undefined reference to `vtable for TextMargin'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status

The warnings and errors are due to two classes (TextMargin and ButtonWindow) having a ClassDef – it looks like cling and ACLiC can deal with it just fine but g++ cannot. @Axel @pcanal @bellenot do you have any more insight into what’s going on?

Cheers,
Enrico

P.S.

as far as I can tell, the ClassDefs are not needed and buttonTest.C can be compiled as a standalone program and runs correctly with these changes:

diff --git a/tutorials/gui/buttonTest.C b/tutorials/gui/buttonTest.C
index bbd0134299..2c72b8dd83 100644
--- a/tutorials/gui/buttonTest.C
+++ b/tutorials/gui/buttonTest.C
@@ -36,7 +36,6 @@ public:
    }
    TGTextEntry *GetEntry() const { return fEntry->GetNumberEntry(); }

-   ClassDef(TextMargin, 0)
 };

 ////////////////////////////////////////////////////////////////////////////////
@@ -54,7 +53,6 @@ public:
    void DoTopMargin(char*);
    void DoBottomMargin(char*);

-   ClassDef(ButtonWindow, 0)
 };


@@ -234,3 +232,9 @@ void buttonTest()

    new ButtonWindow();
 }
+
+int main() {
+   TApplication app("app", nullptr, nullptr);
+   buttonTest();
+   app.Run();
+}

Hi Nicolas,

This example was not intended to be built. To compile it, you need to create a dictionary for the two classes. To do so, move their definition in a header file (e.g. buttonTest.h) and create a Linkdef.h file containing the following code:

#ifdef __CINT__
#pragma link C++ class TextMargin;
#pragma link C++ class ButtonWindow;
#endif

Then create the dictionary with:

rootcling -f buttonTestDict.cxx buttonTest.h Linkdef.h

And finally:

g++ buttonTest.C buttonTestDict.cxx $(root-config --libs --cflags --glibs)

That should work (hopefully).

Cheers, Bertrand.

The linkdef fragment can be improved as follow:

#ifdef __ROOTCLING__
#pragma link C++ class TextMargin+;
#pragma link C++ class ButtonWindow+;
#endif

@pcanal Out of curiosity, for a “ClassDef(..., 0)” (i.e., no I/O, dummy streamer), why do you want the “+”?

I missed the 0 (read too fast), so indeed in this case it makes no practical difference. However since it makes no difference I prefer to recommend the ‘default/recommended’ syntax (and it would make a difference it such a class is then has its version number incremented)

Thanks,
for me removing the classdef is the most simple solution.

Cheers

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.