неопределенная ссылка на ошибку wxLog::DoLog при сборке wxHaskell против wxWidget 3.0

Я пытаюсь собрать wxHaskell для wxWidgets 3.0. Я использовал последнюю версию git wxHaskell из https://github.com/wxHaskell/wxHaskell.

Я попытался следовать install.txt в wxHaskell-master.zip, что я сделал до сих пор:

cd wxdirect
cabal install
cd ../wxc
cabal install 

wxc не будет компилироваться, поскольку для его Setup.hs требуется wxWidgets 2.9. я заменил

let wxRequiredVersion = "2.9"

с

let wxRequiredVersion = "3.0"

а потом сделал:

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

Вся компиляция прошла нормально, но в конце я получил несколько ошибок ссылок. Сложнее всего решить следующее:

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

Соответствующий исходный код находится в 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);
                  }
              ....

Я не мог понять, что вызвало эту ошибку и как ее исправить. Я провел поиск по этой проблеме vtable, и некоторые предположили, что это вызвано объявлением виртуальной функции в дочернем классе без ее определения. Другие предположили, что это порядок, в котором объектные файлы задаются в командной строке g++. Но здесь, похоже, нет ни того, ни другого. Я попытался удалить функцию ELJLog::DoLog или закомментировать ключевое слово virtual. Как ни странно, всегда есть ошибка/ошибки ссылки, говорящие что-то о vtable для ELJLog и ссылающиеся на wxLog::DoLog, даже если DoLog не встречается.

Кроме того, в качестве примечания, wxLog::DoLog, кажется, отсутствует в документации wxWidgets 3.0. Я не уверен, устарела ли эта функция или нет. Но тем не менее, это вызывает ошибки для устаревших производных классов, что я не могу понять.

Любые идеи, что здесь происходит?

--- РЕДАКТИРОВАТЬ2 ---

Если я закомментирую рассматриваемую функцию

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

Я получил разные ошибки ссылок следующим образом:

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

--- РЕДАКТИРОВАТЬ ---

Я работал над этим под mingw32 с mingw.org. Я собрал стабильную версию wxWidgets 3.0.0 из исходного кода и сделал следующее:

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/

person tinlyx    schedule 05.03.2014    source источник


Ответы (2)


Кажется, определение для

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

отсутствует в подклассе ELJLog из wxLog. Добавление следующей копии DoLog, отличающейся интерфейсом, решило проблему только:

virtual void DoLog(wxLogLevel level, const char *szString, time_t t)
{
    wxString s(szString);
    func (EiffelObject, (int)level, (void*)&s , (int)t);
}
person atze    schedule 13.03.2014
comment
Спасибо. Это решило ошибку компиляции. Я не знаком с wxChar и не понимаю, зачем нужен дубликат с char *szString. Я лично сделал две копии функции DoLog, одну с char *szString, а другую с wchar_t *szString. Он также компилируется. - person tinlyx; 16.03.2014
comment
Это в конечном итоге решает проблему компиляции, но я получаю ошибки времени выполнения о wxc.dll. Я не уверен, безопасно ли дублировать такое определение. Должна ли каждая функция в wxWidgets быть определена дважды, один раз с помощью char, а другой с помощью wchar_t? - person tinlyx; 16.03.2014

Глядя на ваши шаги по сборке, я не понимаю, почему вы создаете как статическую, так и общую версии библиотек. Вам действительно нужны они оба? Обычно достаточно одного (обычно общего/DLL при создании расширений). Если вам нужны оба, вам действительно следует создавать их в разных каталогах сборки, чтобы избежать странных проблем со сборкой из-за наличия файлов из старой сборки. Поэтому я бы посоветовал сделать следующее:

  1. Полностью удалите существующие источники.
  2. Получите их заново (и примените исправление MinGW).
  3. Создайте подкаталог build_shared и запустите ../configure && make && make install там.
  4. Если этого недостаточно, т.е. если вам действительно нужны и статические библиотеки, создайте подкаталог build_static каталога исходников верхнего уровня и запустите ../configure --disable-shared && make && make install там.

Если в будущем что-то пойдет не так, вы всегда можете просто сделать rm -rf build_whatever и создать новый каталог сборки и пересобрать его там (cd build_whatever && make -s clean тоже работает, но rm -rf более удобен).


Оригинальный ответ ниже: он все еще может быть полезен кому-то другому, но, похоже, не применим в вашем случае.


Одна из возможностей состоит в том, что вы создали wxWidgets без совместимости с 2.8. Он включен по умолчанию, так что убедитесь, что вы не использовали опцию конфигурации --disable-compat28 (думаю, это в Unix?).

Если wxLog::DoLog() действительно есть в библиотеке (вы можете использовать nm или objdump, чтобы проверить это), то я бы проверил использование устаревших прагм g++ #pragma interface и #pragma implementation, поскольку они могут привести к такой поломке IME. Если вы найдете их где-нибудь, просто удалите их полностью (но удалите их оба, иначе у вас наверняка будут ошибки ссылок).

person VZ.    schedule 05.03.2014
comment
Спасибо за совет. Можно пошагово поподробнее? Я делал это под mingw32. Пожалуйста, смотрите обновление. - person tinlyx; 05.03.2014
comment
Я пересобрал wxWidgets с помощью --dsiable-compat28. Теперь ошибок ссылок гораздо больше. Первые два: dist\build\src\cpp\apppath.o:apppath.cpp:(.rdata$_ZTV20wxMDIParentFrameBase[vtab le for wxMDIParentFrameBase]+0xa0): неопределенная ссылка на wxWindowBase::SetVirtualSizeHints(int, int, int, int)' dist\build\src\cpp\apppath.o:apppath.cpp:(.rdata$_ZTV20wxMDIParentFrameBase[vtable for wxMDIParentFrameBase]+0x110): undefined reference to wxWindowBase::MakeModal(bool)' - person tinlyx; 06.03.2014
comment
Извините, я не хотел подразумевать, что вы «должны были» использовать --disable-compat2.8, это было просто предположение, что вы могли это сделать. Поскольку вы изначально его не использовали, единственная проблема, которую я вижу, заключается в том, что вы создаете как общую, так и статическую версии в одном и том же каталоге, я обновлю ответ, чтобы решить эту проблему. - person VZ.; 06.03.2014
comment
Спасибо за обновление. Еще одна потенциальная проблема — это сам wxLog::DoLog(). Я помню, как искал его документацию, и у него есть разные типы аргументов между 2.8 и 2.9. В 3.0 функцию вроде убрали (читал из документации). Сначала у меня было три ошибки ссылки, а две другие были около wxLog::OnLog(). Они исчезли после комментирования их в исходном коде. Однако проблема DoLog сохраняется. Даже если я прокомментирую это на проблемном сайте, он все равно сообщает о проблеме со ссылкой. - person tinlyx; 06.03.2014