Creating Xcode 3 projects for wxWidgets applications
This article applies to the following versions | ||
Platform | wxWidgets | Xcode |
---|---|---|
Mac OS X 10.5.5, 10.6.6 | 2.8.x, 2.9.x | 3.2 |
Status: Out of date |
Note: This article applies to Xcode 3. For newer versions of Xcode, see Creating Xcode projects for wxWidgets applications |
Creating the project and its files
- Start Xcode.
- Choose menu item File --> New Project --> Carbon C++ Application (or any Application template, which one doesn't matter very much as long as it's an app bundle one) then click Next
- Name the project and place it wherever you wish, then create it.
- Remove from the project all useless files the wizard created, leaving, namely, main.cp[p] and Info.plist (and maybe the .pch one, unless you don't want to use pch. then you'll need to deactivate them too in target settings)
- Replace the contents of main.cpp with that of a wxWidgets sample. Some samples may require images or other resources; in order to quickly build a template you can use the following minimal code :
#include "wx/wx.h"
class MyApp: public wxApp
{
virtual bool OnInit();
wxFrame *frame;
};
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
frame = new wxFrame(NULL, -1, wxT("Hello wxWidgets"), wxPoint(50,50), wxSize(800,600));
frame->Show();
return true;
}
If you chose a wxWidgets sample more complex than the dummy code posted above, it may also be necessary to copy the sample.xpm file from wxMac-2.8.x/samples to the folder above your project folder (you will know if Xcode gives the error "../sample.xpm: No such file or directory"). This should not be necessary for your own projects.
Configure build options
- Highlight your target under the "Targets" group in the tree on the left column
- Right-click on it and select Get info, then switch to the Build tab.
- In the combo boxes at the top, make sure the Configuration one is set to All so you don't have to do it twice for debug and release. In the second called Show you can select all settings which is the most useful.
- In the architectures subsection, edit setting architectures so it matches your wxWidgets build (most importantly, if your wxWidgets build is not universal, you will want to change this setting to not build universal binaries)
- In GCC Code Generation, uncheck Inline Methods Hidden, uncheck Symbols Hidden by Default (this will correct warnings you could get otherwise)
- In Packaging, fill in the product name.
- Now open a terminal window, execute one of these sets of commands :
# if you did make install (make sure you get the right wx-config, you may need to adjust PATH)
wx-config --cppflags
wx-config --libs
# if you left wxWidgets in-place
cd /path/to/wxWidgets/build-release
./wx-config --cppflags
./wx-config --libs
then copy the output of the two last commands.
Warning : if you built wxWidgets as a universal binary, it will output flags like -arch ppc and -arch i386. Drop these flags because Xcode needs to manage Universal Binary stuff itself, passing flags to gcc without Xcode knowing will mix it up and result in linking errors.
Warning : make sure you don't copy and paste linebreaks, this may cause obscure errors
Note: The commands given above will link against the core wx libraries only. If you build non-monolithic (the default) and wish to use more components than the default ones (like OpenGL, HTML, wxAUI, etc.) adapt the command with more library names. Example :
./wx-config --libs core,base,gl If you are not yet sure which libraries you will need, don't worry, you can start with the core ones and update the build settings later as needed by repeating this step. |
Note: A convenient way to manage wx compiler/linker flags, for "power users", is to store them as envrionment variables to be called as $(VAR_NAME) from Xcode (see Setting Environment Variable For XCode for more info on this; note that this other article cannot be followed literally for our current purpose; if you don't think you can/want to adapt environment variables for storing wx-config output, don't bother with this, and just continue the instructions, we'll use copy-and-paste instead!) |
Note: Another convenient way to manage wx compiler/linker flags, still for "power users", is to use a .xcconfig file, then you can have .xcconfig.in templates and a simple script that will generate the .xcconfig from the .in using wx-config automatically, so that the project can be adapted to run on any computer, or to quickly and painlessly switch between wx builds. Writing xcconfig files files is however beyond the scope of this article. Again, if you don't want/need this flexibility, don't bother, just use copy and paste like detailed below |
- Under GCC Language, find Other C Flags, and in this field add the output of the wx-config --cppflags command.
- Under Linking, locate Other Linking Flags and there add the output of the wx-config --libs command.
(Warning: If you copy and paste the result of "wx-config --libs" into a single row at Xcode's config, Xcode will correctly fix and populate the rest of the rows, but be careful that sometimes a blank line is also added. This could lead to "(blank): No such file or directory")
- Close the settings window.
Test and save as template
- Time to compile! Cross your fingers that no error occurs.
- You can also read the troubleshooting notes below.
- Note that by default, Xcode will create a distributable application package for you (unless you built wxWidgets as dynamic lib), located at [your project folder]/build/Debug/
- Put a copy of your project in ~/Library/Application Support/Developer/Shared/Xcode/Project Templates/Application/, so next time you can just select New project and choose this one from the template list (in older versions, the templates directoy was at ~/Library/Application Support/Apple/Developer Tools/Project Templates
Troubleshooting Errors
- If Xcode can't find a header *.h file, go back and check your build settings. There's probably some flags from wx-config missing or misplaced.
- If you get
ld: warning: in /Developer/SDKs/MacOSX10.6.sdk/usr/lib/libwx_macud-2.8.dylib, missing required architecture x86_64 in file
or similar, followed by lots of missing symbol errors, this means that your wxWidgets build is 32-bits (the default), but your Xcode project tries to build 64-bits binaries (the default on OS X 10.6). You need to edit your target settings, like mentionned in the instructions above, to build 32-bits binaries
- You can also check the full build log from Xcode, and compare it with those that Sample Makefiles output.
- If you ever changed the parameters to ./configure, you must always remove the prior build directory first and start from scratch in a new directory. Otherwise you can get a mixture of old and new files in the directory which will confuse the compiler, confuse you, and lead to strange errors and warnings.
- Make sure you don't enable monolithic build (--enable-monolithic) if you are generating a static library (--disable-shared). wxWidgets will probably build and install fine, until you try to link against the libraries with your code or one of the samples. You probably have monolithic and static enabled together (while they are mutually exclusive for some reason) if you see something like this:
Undefined symbols for architecture i386: "wxTopLevelWindowMac::DoCentre(int)", referenced from: vtable for MyFramein minimal_minimal.o ld: symbol(s) not found for architecture i386 collect2: ld returned 1 exit status
- If you program compiles in debug mode but will not run, check for a Zero Link unknown object error. wxWidgets will not work if ZeroLink is enabled. You can switch it off in Project Info->Build->Linking
- If your program crashes when compiled from Xcode, but does not crash when compiled from the "samples" makefile, then it means that your compiler settings in Xcode do not match the compiler settings you used when you compiled the wxWidgets library (like defining __WXDEBUG__ and linking against release libraries, or vice-versa)
- If you want to debug beyond your code and into the wxWidgets code, you need to do three things:
- Build a debug version of the wxWidgets library (see articles about building wxWidgets)
- Add the __WXDEBUG__ compile flag to your project.
- Add the debug library to your Xcode project, clean and rebuild.
Making a project that uses an external Makefile
This is another way to setup your project, if you wish to use an external build system (here make) instead of Xcode's built-in build system.
- Start Xcode.
- Choose menu item File --> New Project --> Empty Project (under other)
- Name the project and place it wherever you wish, then create it.
- add a cpp file e.g. main.cp[p]
- fill main.cp[p] with the abow example
- add a empty file and call it Makefile
- fill this file with:
hello: main.cpp
g++ main.cpp /*and here the output of wx-config as explained abow*/
- add a new target as "External Target"
- double click on the target to get the settings window and change the following
- give a product name
- Set the Directory giving the home of this project
- close this window
- right click on the target and build it
- hopfully you'll find the executable in the home (project) folder (not possible to run from the gui)
Debugging a project that uses an external Makefile
Here is a technique for using Xcode to debug a project which uses an external makefile, without making any changes to the existing project. This can be a smoother experience than using gdb from the command line, as Xcode will show you the source code and the stack trace etc.
You will need to have --enable-debug in your wxWidgets build so the app has debug information.
The idea is to create a new project <TestMyProject> purely for debugging, in a separate folder. You don't need to put any source files or anything in there apart from the project file which Xcode creates, and Xcode will create a "build" folder which you won't use.
Your real project remains where it was, don't change a thing, carry on using "make" to build it. You only need to create that test project once and never need to change it. The test project knows nothing about building.
- Create a new Xcode project called <TestMyProject> of type Mac OS - Other - External Build System.
- On the "Action" drop-down, Add - New Custom Executable. Add your app executable here. You must already have built it of course.
- You can specify command-line args on Project menu - Edit Active Executable.
- Right-click the "TestMyProject" item at the top of the "Groups & Files" column at the left of the project window, and "Add existing files". These files can be from any folder so you add your project source files, and also the wxWidgets sources if you want to be able to see those too. (assuming that you link them statically).
- On the Run menu you can now bring up the Debugger and the Console, and "Debug" your app (option-command-Y).
One catch: I find that breakpoints are not always "resolved". I create a breakpoint but in the Xcode Debug window it says "not resolved". The solution is to pause the app (ctrl-C in the Debug window) and after a couple of seconds we get a message saying "breakpoint resolved". It's especially a problem if I want to put a breakpoint in startup code as I don't get the chance to ctrl-C until it's too late. If I really need to then I put a wxTrap() call in there and recompile - not an ideal solution. With gdb we would load the program, set the breakpoint, then run it. But I don't know how to do this in Xcode.