Search code examples
c++haskellwxwidgetsvtablewxhaskell

undefined reference to wxLog::DoLog error building wxHaskell against wxWidget 3.0


I am trying to build wxHaskell for wxWidgets 3.0. I used the latest git version of wxHaskell from https://github.com/wxHaskell/wxHaskell.

I tried to follow install.txt in wxHaskell-master.zip, what I did so far is:

cd wxdirect
cabal install
cd ../wxc
cabal install 

wxc won't compile because its Setup.hs requires wxWidgets 2.9. I replaced

let wxRequiredVersion = "2.9"

with

let wxRequiredVersion = "3.0"

and then did:

cabal install --extra-lib-dirs=/usr/local/lib

All compilation went OK, but I got a few link errors in the end. The hardest one to solve is the following:

dist\build\src\cpp\eljlog.o:eljlog.cpp:(.rdata$_ZTV6ELJLog[vtable for ELJLog]+0x20): undefined reference to `wxLog::DoLog(unsigned long, char const*, long)'

The corresponding source code is in wxc/src/cpp/eljlog.cpp:

class ELJLog : public wxLog
{
    private:
        TLogFunc func;
        void*    EiffelObject;

    protected:
        virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t)
                  {
                    wxString s(szString);
                    func (EiffelObject, (int)level, (void*)&s , (int)t);
                  }
              ....

I couldn't figure out what caused this error and how to fix it. I did some search about this vtable issue, and some suggested that this is caused by declaring a virtual function in a child class without defining it. Others suggested that it's the order that object files are given on the g++ command line. But neither seems to be the case here. I tried removing the function ELJLog::DoLog function or commenting out the virtual keyword. Strangely, there is always a link error/errors saying something about vtable for ELJLog, and refers to wxLog::DoLog, even when there is no occurrence of DoLog.

Also, as a side note, wxLog::DoLog seems to be missing in the wxWidgets 3.0 documentation. I am not sure whether this function is deprecated or not. But still, it's causing errors for legacy derived classes in a way that I can't understand.

Any ideas what's going on here?

--- EDIT2 ---

If I comment out the function in question

virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t) ...

I got different link errors as follows:

dist\build\src\cpp\eljlog.o:eljlog.cpp:(.rdata$_ZTV6ELJLog[vtable for ELJLog]+0x
20): undefined reference to `wxLog::DoLog(unsigned long, char const*, long)'
dist\build\src\cpp\eljlog.o:eljlog.cpp:(.rdata$_ZTV6ELJLog[vtable for ELJLog]+0x
24): undefined reference to `wxLog::DoLog(unsigned long, wchar_t const*, long)'
collect2: ld returned 1 exit status

--- EDIT ---

I worked on this under mingw32 from mingw.org. I built wxWidgets 3.0.0 stable release from source, and the stpes I did were as follows:

per http://mingw.5.n7.nabble.com/win32api-version-4-td32288.html :
 edit line 2217 of /c/mingw/{,mingw32/}include/commctrl.h to read
 #define TV_DISPINFO NMTVDISPINFO
 instead of
 #define TV_DISPINFO __AW(NMTVDISPINFO) 
The above was needed to fix a MinGW32 4.8.1-4 issue. Then,

./configure --enable-stl --disable-shared
make
make install

./configure --enable-stl
make
make install 
mv /usr/local/lib/wx*.dll /c/mingw/bin/

Solution

  • It seems a definition for

    virtual void DoLog(wxLogLevel level, const char *szString, time_t t)
    

    is missing in the subclass ELJLog of wxLog. Adding the following copy of DoLog differing in the interface only solved the problem:

    virtual void DoLog(wxLogLevel level, const char *szString, time_t t)
    {
        wxString s(szString);
        func (EiffelObject, (int)level, (void*)&s , (int)t);
    }