Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#15618 closed build error (invalid)

Undefined symbols (non-virtual thunk) when deriving from wxTextCtrl

Reported by: jdog Owned by:
Priority: normal Milestone:
Component: wxOSX Version: stable-latest
Keywords: Cc: vaclavslavik
Blocked By: Blocking:
Patch: no


I have a strange linking error that appeared after an upgrade to OS X Mavericks.

My setup is:

  • wxWidgets (Cocoa) from trunk, built using "./configure; make"
  • Xcode 5.0.1
  • Homebrew

I get undefined symbols when linking classes that derives from wxTextCtrl (and other classes such as wxChoice as well I think, but let's focus on wxTextCtrl).

Here is a minimal sample:

#include <wx/textctrl.h>

class MyTextCtrl : public wxTextCtrl
    MyTextCtrl(wxWindow* p);

MyTextCtrl::MyTextCtrl(wxWindow* p)
    : wxTextCtrl(p, -1)

int main(int argc, char* argv[])
    MyTextCtrl* t = new MyTextCtrl();

I build with the following command:

/usr/bin/c++ test.cpp `wx-config --cppflags --libs`

And get the following output:

Undefined symbols for architecture x86_64:
  "non-virtual thunk to wxTextCtrl::Cut()", referenced from:
      vtable for MyTextCtrl in main-cjEdjp.o
  "non-virtual thunk to wxTextCtrl::Copy()", referenced from:
      vtable for MyTextCtrl in main-cjEdjp.o
  "non-virtual thunk to wxTextCtrl::Paste()", referenced from:
      vtable for MyTextCtrl in main-cjEdjp.o

And it continues like that ...

I've tried everything I can think of. Any ideas?

Change History (13)

comment:1 Changed 7 years ago by jdog

It works when I use the compiler flag -mmaxosx-version-min=10.5. I found this when comparing all compiler flags used by the samples with the compiler flags I use.

I'm not sure if this has been documented anywhere. And I think wx-config --cxxflags should include it.

comment:2 Changed 7 years ago by vadz

Thanks for the update, it's nice to have a workaround for this. But I'm not sure if we can include this flag in wx-config output -- what if you want to use a different minimal version, e.g. 10.6? Wouldn't it be confusing/annoying to have wx-config override this?

OTOH failing to link by default is pretty bad too... So should we add this to wx-config flags or not? Doing it shouldn't be difficult, I'd just like to be sure that this is the right thing to do.

comment:3 Changed 7 years ago by plorkyeran

what if you want to use a different minimal version, e.g. 10.6

Then you should build wx with the minimum version set to 10.6. I think using libraries built with mixed versions of -mmacosx-version-min is supposed to work, but in practice often doesn't (as seen here), and is suboptimal even when it does work. IMO either wx should set -mmacosx-version-min in wx-config, or it should not be setting -mmacosx-version-min by default at all.

comment:4 Changed 7 years ago by jdog

I'm sorry to say that setting @-mmacosx-version-min@ does not work in all cases.

I think this is related to a new stdlib used by default in OSX Mavericks. Before @libstdc++@ was used by default, but 10.9 use @libc++@ by default. By specifying min version different stdlibs may be selected.

More info:

Do we need to specify @-mmacosx-version-min@ when build wx?

I will try to rebuild with no min version and using @-stdlib=libc++@ ...

comment:5 Changed 7 years ago by jdog

I configured wxWidgets using "--with-macosx-version-min=10.9" and then recompiled, and now everything works. I did not find any way to specify which stdlib to use, other than by different default depending om macosx min version...

I'm not sure what to do with this, perhaps some documentation would be enough. You have to be very careful right now when compiling each library on OSX so that the same stdlib is used for all parts. What makes it worse is that linking mostly works even when using different stdlibs, except for subtle things like this.

comment:6 Changed 7 years ago by plorkyeran

I've been building wx (and all of my other deps) with libc++ pre-10.9 by just adding -stdlib=libc++ to CXXFLAGS, OBJCXXFLAGS, and LDFLAGS. In wx's case this requires passing --with-macosx-version-min=10.7 to configure as the default of 10.5 is incompatible with libc++.

comment:7 follow-up: Changed 7 years ago by vadz

  • Cc vaclavslavik added

So the problem is actually the switch to libc++ in 10.9 which is incompatible with libstdc++ used in the previous versions, isn't it?

If so, is there anything we need to do here on wx side? Including the information about the standard library being used in the build options doesn't seem to be useful as it's not going to link anyhow. And what else can we do?

Vaclav, would you have any thoughts about this?

comment:8 Changed 7 years ago by csomor

  • Status changed from new to infoneeded_new

the c++ library used is either indicated explicitly by -stdlib=libc++ or -stdlib= libstdc++ or implicitly by the -mmacosx-version-min= setting.

The library build is getting its -mmacosx-version-min=10.5 by default, thus libstdc++ is used, but then for the source file in the example the compiler is not retrieved using the -cxx params but just set to /usr/bin/c++ which results in missing the-mmacosx-version-min value, thus libc++ is used by default under 10.9 and that's where things break. So just using wx-config for getting the correct compiler should make things work.

comment:9 in reply to: ↑ 7 Changed 7 years ago by vaclavslavik

  • Status changed from infoneeded_new to new

Replying to vadz:

And what else can we do?

Vaclav, would you have any thoughts about this?

It'd say it's a common sense requirement that the library and the user code must be compiled with the same ABI-affecting compiler settings (such as --stdlib or, in some cases (ehm, Boost, ehm) even --std=c++11) .

Consequently, I strongly agree with comment:3 -- wx should never set such potentially ABI-affecting flags on itself, as it currently does, and should instead require the user to explicitly say what they want, be it via CXX, CXXFLAGS or --with-macosx-version-min.

comment:10 Changed 7 years ago by vadz

  • Resolution set to invalid
  • Status changed from new to closed

I think we can't build wx without using --with-macosx-version-min, so if didn't set it to something by default, this would mean that all wxWidgets users would have to specify it themselves and for most of them this would be a problem as they'd have no idea what to use there. So I don't think it would be an improvement.

And as I still don't see anything else we could do, let's just close this for now...

comment:11 Changed 7 years ago by plorkyeran

At least on 10.9, building wx with -mmacos-version-min unset (by manually editing the Makefile after running configure) works fine.

comment:12 Changed 7 years ago by csomor

as I said, just don't fix code the compiler, but use

`wx-config --cxx`

as indicated in the second example in

then things are setup correctly without having to interfere manually

comment:13 Changed 7 years ago by csomor

one question that came to my mind is whether it is wise to have the version-min being put into the cxx and not the cxxflags config part, but I'm by no means an expert on that ...

Note: See TracTickets for help on using tickets.