# Compiling wxWidgets for 10.4?



## Kinniken (May 15, 2005)

Hi, I have a project to do in C++ with the wxWidgets UI libraries. I downloaded the latest stable release (2.6) from the official website (http://www.wxwidgets.org/dl_mac2.htm).

configure runs fine, but when trying to compile it using make I get:



> ./bk-deps g++ -c -o coredll_webkit.o -I.pch/wxprec_coredll -D__WXMAC__     -I../src/tiff -I../src/jpeg -I../src/png    -I../src/expat/lib -DWXUSINGDLL -DWXMAKINGDLL_CORE -DwxUSE_BASE=0 -dynamic -fPIC -DPIC -DWX_PRECOMP -DNO_GCC_PRAGMA -Ilib/wx/include/mac-ansi-release-2.6 -I../include -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -fpascal-strings -I../src/mac/carbon/morefilex -I/Developer/Headers/FlatCarbon -O2 -Wall -Wno-ctor-dtor-privacy -fno-common ../src/html/htmlctrl/webkit/webkit.mm
> ../src/html/htmlctrl/webkit/webkit.mm:69: error: 'wxStringWithNSString' declared as an 'inline' variable
> ../src/html/htmlctrl/webkit/webkit.mm:69: error: 'NSString' was not declared in this scope
> ../src/html/htmlctrl/webkit/webkit.mm:69: error: 'nsstring' was not declared in this scope
> ...



Now, since it mentions webkit extensively, I'm assuming that it must be the result of incompatibilities between it and 10.4. Does anyone know a work around?

TIA,

Cédric


----------



## Viro (May 15, 2005)

I got it to compile by adding the flags --disable-webkit. 

If you're using wxCocoa and not the Carbon port, just configure with --with-cocoa and webkit seems to work fine.


----------



## Kinniken (May 15, 2005)

Thanks, that solved it!

Is there a guide anywhere on developing projects with wxWidgets and xCode?


----------



## Viro (May 15, 2005)

Check out the wiki at http://wiki.wxwidgets.org/wiki.pl?Mac_OS_X_And_Xcode_1.5_Project_Setup_Guide

If you're after tutorials, wxWidgets is quite sparse with tutorials, I'm afraid. The sample code is the best way to learn.


----------



## Kinniken (Jun 1, 2005)

After an interruption due to more urgent projects, I'm back at it... I tried the tutorial you linked to. Even though it was written for XCode 1.5, I found all the settings described. However, when building the project, while the compilation phase works the linking fails with the following error:

/usr/bin/g++-4.0  -o /Users/cedricdj/Desktop/wxMac-2.6.0/demos/bombs/Bombs/build/Bombs.app/Contents/MacOS/Bombs  "-L/Users/cedricdj/Desktop/wxMac-2.6.0/demos/bombs/Bombs/build"  "-F/Users/cedricdj/Desktop/wxMac-2.6.0/demos/bombs/Bombs/build"  -filelist /Users/cedricdj/Desktop/wxMac-2.6.0/demos/bombs/Bombs/build/Bombs.build/Bombs.build/Objects-normal/LinkFileList  "-arch" "ppc" "-prebind" "-Wl,-no_arch_warnings"   
/usr/bin/ld: warning prebinding disabled because of undefined symbols
/usr/bin/ld: Undefined symbols:
wxMessageBox(wxString const&, wxString const&, long, wxWindow*, int, int)
wxGetStockLabel(int)
wxGetTopLevelParent(wxWindow*)
wxEntry(int&, char**)
wxAssert(int, wchar_t const*, int, wchar_t const*, wchar_t const*)
wxClientDC::wxClientDC(wxWindow*)
wxClientDC::~wxClientDC()
wxFontBase::~wxFontBase()
wxListBase::Init(wxKeyType)

(There basically the list of all the wx methods/classes used by the project, I cutted it short).

I assume that XCode cannot find the wx libraries, even though it can find the headers. Do you know where they are? I tried the "obvious" locations (/usr/lib, /usr/local...), but nothing works so far.

TIA,

Kinniken


----------



## Viro (Jun 1, 2005)

Did you do a "sudo make install"? If you did, and it installed correctly assuming you used the default install location, it will be in /usr/local. Just copy and paste the wx-config --cflags --libs and you should be set.

You might also want to be sure that you disable ZeroLink. It works wonders when developing certain apps, but it doesn't work at all with wxWidgets.


----------



## Kinniken (Jun 2, 2005)

I did all of that, and it still fails.

Concerning the install, I looked in /usr/local and I have in /usr/local/lib:

Many libs with names like libwx_base_carbon_net-2.6.0.0.0.dylib, libwx_base_carbon_xml-2.6.0.0.0.dylib, libwx_mac_xrc-2.6.0.0.0.dylib...

A "wx" folder containing two files in nested folders:

/usr/local/lib/wx/config/mac-ansi-release-2.6
/usr/local/lib/wx/include/mac-ansi-release-2.6/wx/setup.h

Is there anything missing?


----------



## Kinniken (Jun 3, 2005)

I just spent an other fruitless hour trying different options, include paths and so on, nothing works...
Assuming you have it running under 10.4, any chance you could email me (cedric "at" kstudio '.' net) a bare-bone wxWidgets project that compiles with Xcode? Hopefully I can figure out what's wrong from it...

TIA,

Kinniken


----------



## Viro (Jun 3, 2005)

I've just taken a look at my /usr/local/lib. I've got not .dylib files. All I have are .a files since I compiled everything as a static library. This maybe why I don't get any errors on mine.


----------



## wadesworld (Jun 4, 2005)

Did you add the needed wx libs to your project?  If you didn't, it won't link with them.

Wade


----------



## Viro (Jun 4, 2005)

I think he did. He's copied all the flags from wx-config that will tell you where and what libraries to link. So it's strange that he's getting the errors.


----------



## Kinniken (Jun 4, 2005)

Viro said:
			
		

> All I have are .a files since I compiled everything as a static library. This maybe why I don't get any errors on mine.



Probably, yes. How do I compile wxWidgets as a static library then? I used the exact command sequence below:

1) cd into the base dir
2) mkdir osx-build
3) cd osx-build
4) ../configure --disable-webkit
5) make
6) sudo make install
7) type <YOUR OWN PASSWORD>

They are straight from the www.wxwidgets.org mac install read me, except the --disable-webkit flag which you indicated.


----------



## Kinniken (Jun 4, 2005)

wadesworld said:
			
		

> Did you add the needed wx libs to your project?  If you didn't, it won't link with them.



I did not drag-and-drop any libraries to my project's files, just added the compiler flags from wx-config. I exactly followed the tutorial given in Viro's second post, no more, no less (though when it failed I did try different things which did not work, like specifying other include paths).


----------



## Viro (Jun 4, 2005)

When you do a configure, pass the flag --disable-shared.


----------



## Kinniken (Jun 4, 2005)

Thanks, I'll try that.

Before I install the static libraires though, how do I uninstall my previous install? I tried sudo make uninstall, but the "uninstall" target is blank... Should I do it manually?


----------



## Kinniken (Jun 4, 2005)

Just noticed something interesting... If I cannot manage to make the "bombs" demo compile with Xcode, the very same demo compiles without problems with a simple "make" command in the terminal.

I'm going to try peering though its makefile and try and configure my Xcode project to use the same settings.


----------



## wadesworld (Jun 4, 2005)

Paste the entire command you're trying to compile with - then we can see if the right libraries are being linked and the proper paths specified.


----------



## Kinniken (Jun 4, 2005)

How do I do that with Xcode?
If it helps, here are the results of the two wx-config commands:

cedricdj$ wx-config --cxxflags
-I/usr/local/lib/wx/include/mac-ansi-release-static-2.6 -I/usr/local/include/wx-2.6 -D__WXMAC__ -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -DNO_GCC_PRAGMA  
cedricdj$ wx-config --libs    
-L/usr/local/lib   -framework QuickTime -framework IOKit -framework Carbon -framework Cocoa -framework System  /usr/local/lib/libwx_mac_xrc-2.6.a /usr/local/lib/libwx_mac_qa-2.6.a /usr/local/lib/libwx_mac_html-2.6.a /usr/local/lib/libwx_mac_adv-2.6.a /usr/local/lib/libwx_mac_core-2.6.a /usr/local/lib/libwx_base_carbon_xml-2.6.a /usr/local/lib/libwx_base_carbon_net-2.6.a /usr/local/lib/libwx_base_carbon-2.6.a -lwxexpat-2.6 -lwxtiff-2.6 -lwxjpeg-2.6 -lwxpng-2.6 -lz -lpthread -liconv

All the paths listed in those commands look correct.


----------



## wadesworld (Jun 4, 2005)

OK, all running wx-config does is to setup wxWidgets.

If you want to actually use wxWindows in an xCode project, you need to add the appropriate wxWidgets libraries to your Xcode project.  You can either drag-and-drop them or use "Add to project".

If you try that and it still doesn't work, pull up the detailed build results window and paste the command-line output here (the command-line output is in the bottom pane of the window).

Wade


----------



## Kinniken (Jun 4, 2005)

According to the tutorial linked to by Viro in his second post, wx-config outputs the compilation and linking flags to be used by Xcode. I copy-pasted them in the corresponding target setting fields in Xcode.
I tried adding the libraries to the project as you proposed (including the target, of course), and it failed just as before.

Here is the result of the entire build process output:



> /Developer/Private/jam -d1 -j1 JAMBASE=/Developer/Makefiles/pbx_jamfiles/ProjectBuilderJambase JAMFILE=- build ACTION=build _DEFAULT_GCC_VERSION=4.0 BUILD_STYLE=Development CPP_HEADERMAP_FILE=/Users/cedricdj/Huygens/Travail/LO11/bombs/Bombs/build/Bombs.build/Bombs.build/Bombs.hmap SRCROOT=/Users/cedricdj/Huygens/Travail/LO11/bombs/Bombs OBJROOT=/Users/cedricdj/Huygens/Travail/LO11/bombs/Bombs/build SYMROOT=/Users/cedricdj/Huygens/Travail/LO11/bombs/Bombs/build DSTROOT=/tmp/Bombs.dst
> 
> PBXCp /Users/cedricdj/Huygens/Travail/LO11/bombs/Bombs/build/Bombs.app/Contents/PkgInfo
> /System/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp  -exclude .DS_Store -exclude CVS -exclude .svn -resolve-src-symlinks  /Users/cedricdj/Huygens/Travail/LO11/bombs/Bombs/build/Bombs.build/Bombs.build/PkgInfo  /Users/cedricdj/Huygens/Travail/LO11/bombs/Bombs/build/Bombs.app/Contents
> ...


----------



## wadesworld (Jun 4, 2005)

OK, so you do have the libraries linking.  Good.  Now that we know that, we need to determine:

1)  Is wxWindowBase::RegisterHotKey(int, int, int) just in a library that you're not linking?  This seems unlikely, because it looks like you're linking to all of them.

2)  Is wxWindowBase::RegisterHotKey(int, int, int) not being compiled into the library for some reason?  This is the tough part - you have to figure out if the wrong header is being included, if the library maintainer perhaps accidentally left it #ifdef'ed out, etc.

Go to /usr/local/lib and run the following command:

nm libwx* | grep RegisterHotKey

and post the output here.  That will show us if it is defined in any libraries.

Wade


----------



## Kinniken (Jun 5, 2005)

All your command returned was:

cdejacqu-rob-0:/usr/local/lib cedricdj$ nm libwx* | grep RegisterHotKey
nm: no name list
nm: no name list
nm: no name list
nm: no name list
nm: no name list
nm: no name list

However, it gave me the idea to try and search the wxMac directory for RegisterHotKey. It turned out that while it was implemented, the definition was simply "return false", with a comment stating that this function still had to be written. Since it was apparently useless (on mac at least) and since I don't need it, I commented it out in both the .cpp and the .h files and recompiled and reinstalled the libraries... and it works 

All my thanks to you and Viro, I would never have managed it without your help.


----------



## Viro (Jun 5, 2005)

It's very strange that you had to do that. What version of wxWidgets are you using, and what were your _entire_ configure flags? I didn't have to do any of that when I compiled my version of wxWidgets.


----------



## Kinniken (Jun 5, 2005)

I agree that it makes little senses, especially since command-line compilation worked fine without it...

I'm using 2.6.0, and my configure command was : ../configure --disable-webkit --disable-shared


----------



## Kinniken (Jun 6, 2005)

Quick question, now that I have started using it: how do I convert an int to wxString, in order to display it? All my (windows-based) teacher could suggest was itoa(), but it's a non ANSI-function which apparently does not exist in the stdlib Xcode uses...


----------



## Viro (Jun 6, 2005)

You've got quite a few options there. The C++ way would be to use a stringstream. 


```
#include <sstream>
using namespace std;

//.... somewhere in your code
stringstream s;
s<< myInt;

wxString myString;
myString = s.str().c_str();
```

You might be able to make the code shorter, but this is just me coding when I've just woken up .

The C way of doing it would be to use sprintf(or the safer snprintf). I dislike this method since it is possible to cause buffer overruns. They are used just like the normal printf except the string isnt printed to stdout, rather it's put in an array of characters of your choice.


----------



## Kinniken (Jun 6, 2005)

Thanks, that worked 

Next question  :

How do I get a method to trigger when the window is resized? (preferably "live")

I tried overloading the OnSize() method of my frame,  but it never triggers...


----------



## Viro (Jun 6, 2005)

I don't know what you have, but did you declare an event table? This is very similar to MFC's DECLARE_MESSAGE_MAP macro.

At the start of your .cpp implementing the methods of you class you need the following

```
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_SIZE(MyFrame::OnSize)
END_EVENT_TABLE()
```

wxWidgets suffers from the same kludges that MFC suffers from. The functions are implemented using message maps, instead of the traditional inheritance hierarchy that most Object Oriented libraries use. This was done on the pretext of efficiency back in the days when C++ compilers were inefficient and every single byte counted.

Hence, overriding wxFrame::OnSize() isn't enough. You need to declare that you have overriden it, and map the resize event to MyFrame::OnSize(). Horribly contorted if you ask me.


----------



## Kinniken (Jun 6, 2005)

Well guessed Viro, that was my problem. Fixed! 

Now I can simulate anchor-based resizing behaviour instead of that sizer-based abomination. And I agree with you that this message map is ugly and unnecessary.

As much as I appreciate being able to code the GUI on OS X and port it to Windows with only a recompile (well, in theory at least...), I do find wxWidgets rather clumsy. It reminds me of AWT or NetBeans.


----------



## Viro (Jun 6, 2005)

It's a real pity that wxWidgets is so contorted. I like the fact that it uses native widgets and the licensing isn't GPL (rather it's LGPL). This is an advantage compared to Qt.

But these days, I seem to like Qt better just because the API is cleaner. But then you have got moc. And the license is GPL unless you pay $1500 for a commercial license.

Can't beat them all I guess .


----------



## Kinniken (Jun 7, 2005)

Yeah, Qt would be useless for me for those license reasons - I can't afford $1500 for a commercial one... Anyway, for the moment it's not like I have a choice: my assignment requires using wxWidgets. For that matter, technically it requires using MS Visual Studio, but since I can port it back when I'm done that's no biggy.

Anyway, I have an other small problem... I can't seem to get the ids of selected rows in a wxGrid component... consider:



> void MyFrame::GridSelChange() {
> 
> cout<<"1"<<endl;
> 
> ...



The cout<<2 never triggers, even when I have several rows selected (the cout<<1 triggers fine) (I have selection mode set to rows only).

Any idea what I could be doing wrong?


----------



## Viro (Jun 7, 2005)

No idea . That looks like it should work. Did you try it out on Windows to see if the problem is only with the Mac port (quite possible)?


----------



## Kinniken (Jun 7, 2005)

No, I would have to go to university for that. I might this afternoon.

Hmm, looking more closely, it seems there are two "selection" levels - one when rows get an aqua background and one when a cell gets a thick black border.
Possibly because I have cell editing disabled, all I can do is the "aqua" select, when I click on a row. Cell 0,0 has the black border when the grid is created, and I can't move it anywhere else.
Could this be the problem? Is a "selection" for wxWidgets the aqua background or the black border?


----------



## Viro (Jun 7, 2005)

It should be like on any OS X app. Selection is a light blue aqua color.


----------



## Kinniken (Jun 7, 2005)

I'm totally at a loss on this problem... Here is what it looks like:







Notice the odd black outline on cell (0,0), which is there when the grid is created and is impossible to move or make disappear. The selected row is never taken into account, nowhere - IsInSelection() called on one of its cell always return false, for exemple.
The oddest part is that if I select a row from the code, using SelectRow(), the row appears selected in the window exactly as if the user has clicked on it, but this time it is recognised as being selected by wxWidgets!
I haven't had time to try it on PC, but I will. I badly need to get it to work though, handling data displayed in lists is central to my project...

Oh, and an other anomaly: when live cell editing is enabled, it works - but only for cell(0,0), the one in the black outline. Double-clicking on anyone of the others fail.

If it turns out that wxGrid is broken on mac, I'm in trouble. Sight.


----------



## Viro (Jun 7, 2005)

Try running your wxGrid sample that comes with wxWidgets to see if you have the same problem. I don't use the grid widget, and am not familiar with it.

Also, 2.6.1 was released recently, but there is no mention of any bugs with wxGrid.


----------



## Kinniken (Jun 7, 2005)

And as usual, the insight comes ten minutes after acknowledging defeat: my override of the SelChange() event is preventing the triggering of parts of the wx code devoted to sel change... I switch my event to an other trigger and the first "miracle" happens: the black outline now moves to the cell clicked (on top of the row being highlighted), and a call to IsInSelection() on the cell returns true.

However and a few more tests later, I have to say wxGrid's way of handling selection is one of the most warped things I've ever seen. First, there's this thing of having two "selections", à la Excel: the black outline which is only present on a cell at a time and the aqua background which can be present on any number of cells. When the selection mode is set to "rows only", the black outline does not disappear as it should, but clicking on a cell colours the row in aqua on top of moving the outline to the cell in question. Weird.

Far weirder than that though is the fact that a row highlighted in aqua like that does not count as "selected"... The only way I've found to mark a row as selected from the UI is to click on its header.

Anyway, I can sort my way out of this mess now... all I need to do is:
- trigger the wxGrid SelChange() event inside my overloaded one
- write a custom selectedRow() function using the black outline and not the aqua background, via the IsInSelection() method

Speak of kludges...

Oh, concerning step one, I have to admit I forgot how you call a parent's function when overloading it in a child class (apart from constructors)... Do you remember?


----------



## Kinniken (Jun 7, 2005)

Viro said:
			
		

> Try running your wxGrid sample that comes with wxWidgets to see if you have the same problem. I don't use the grid widget, and am not familiar with it.



Which one would that be?


----------



## Kinniken (Jun 7, 2005)

erratum: all the cells highlighted in aqua return true to IsInSelection(). It's just that they are not in SelectedRows().


----------



## Kinniken (Jun 7, 2005)

This thing is even weirder than I thought. Even when using .Skip(), the method supposed to ensure that the normal event behaviour is executed, every wxGrid methods to detect selections fails.

However, someone pointed out an obvious workaround to me: the event passed in parameter has a GetRow() method which surprisingly enough works fine. Problem solved, at last.

Next question  :

Is there a way to tie events to controls without defining subclasses? IE, to have different methods execute when the user click on different buttons without having to declare a new class for every single one of them? It would be very useful...


----------



## Viro (Jun 7, 2005)

Kinniken said:
			
		

> Oh, concerning step one, I have to admit I forgot how you call a parent's function when overloading it in a child class (apart from constructors)... Do you remember?



I haven't used wxWidgets for a while, and I'm not certain of the other bits of your questions. This I am certain. To call your parent classes method, just do ParentClass::methodname(). It's simple .

I'm a little fuzzy on the message map pattern. If it is anything similar to the observer pattern common in other OO libraries (or signal/slots in Qt), you should be able to bind a message to any method, even multiple methods to a single message. In lieu of any better advice, you could just play around with what you think should work. In my experience, C++ is usually quite consistent :ha: and what you think would work normally does.


----------



## Kinniken (Jun 8, 2005)

Quick and (hopefully) easy C++ question... how do I initialise a static const table of either strings or char* in one of my class? I tried things like:

static const char** myStrings = {"s1","s2","s3"};

or

static const string* myStrings = {"s1","s2","s3"};

But the compiler refuses them...


----------



## Viro (Jun 8, 2005)

Kinniken said:
			
		

> Quick and (hopefully) easy C++ question... how do I initialise a static const table of either strings or char* in one of my class? I tried things like:
> 
> static const char** myStrings = {"s1","s2","s3"};
> 
> ...




```
static const string a[] = {"hello", "I", "b"};
```

That seems to work fine. That how I normally deal with arrays, probably due to the fact that I program in Java. Don't ask me what the difference is though...


----------



## Kinniken (Jun 8, 2005)

It doesn't work  :

UTC.h:69: error: a brace-enclosed initializer is not allowed here before '{' token
UTC.h:69: error: invalid in-class initialization of static data member of non-integral type 'const std::string []'


----------



## Kinniken (Jun 8, 2005)

I guess I'll just use global constants until I find a better way.

In the meantime, I have yet an other question... How do you create a multi-line wxTextCtrl? According to the doc I thought txAdresse->SetWindowStyle(wxTE_MULTILINE); would do it but it seems to have no effect...


----------



## Viro (Jun 8, 2005)

Static constants do not get defined in the .h file. They get defined in the .cpp file. In the header file, you need to have an 'extern' reference to the constant. Something like extern const std::string a[];


----------



## Kinniken (Jun 11, 2005)

I'm pleased to say that I'm about done with that project 
Only a few wrinkles to iron out (like that annoying vector sorting problem) and I'll be done.

Thanks for your help, you saved me many fruitless hours peering at stupid bugs


----------

