Installing WxMac

From WxWiki
Jump to: navigation, search

Please note that this article is outdated. For up-to-date information, please see article Compiling_wxWidgets_using_the_command-line

General: Using Apple Developers Tools

Developers accustomed to Microsoft Windows and the GUI IDE's like MS VC++ may find developing on the Apple Mac running OSX a shock. This ships with a set of Apple Developers Tools installed on the hard disk, although you will need to run the installer to use them. However these are mainly Unix-based and command-line driven (the GUI Project Builder is dealt with elsewhere: if you have 10.3 and XCode 1.1, try Mac OS X And Xcode 1.1 Setup Guide for a GUI IDE). On the positive side, once you have learned how to do all this, it is very much the same in Linux or other Unix flavours, so you get two ports for the effort of one.

These notes are intended to help someone new to the Mac port their Ms Win wxWidgets application to it. As with all porting exercises, it is a good idea to develop in parallel, checking all platforms work as you go along.

Install.txt Notes

These notes expand on the standard install.txt, which is too brief for the Mac newcomer. They have been written using an iBook running Mac OS X 10.1, more or less out of the box, with no additional software. The version of wxWidgets at the time of writing is 2.4.2.

  • 2.4.2 can fail to compile on later versions of OSX such as 10.3, because the compiler is gcc 3.3. You can find out by typing gcc --version in a console. gcc 3.1 is needed. You may be able to change it back to 3.1 by the command sudo /usr/sbin/gcc_select 3.1. You will require the root password for this (by default, your default userid password which you set up when you installed your Mac). Do this before you do anything else in these instructions. For OSX 10.3 (Panther), you must use a different download of 2.4.2 (see below).
  • The installation of 2.5.1, a development snapshot, requires Mac OS X 10.2 or later, and has been tried on 10.3 using the Apple tools which include XCode 1.1. Although this does compile, many of the samples do not (such as the 'Hello world', minimal). One that does compile is splitter. However, this crashes when run if you click on the menu. So 2.5.1 cannot be considered usable for development.
  • The production 2.4.2 release does contain a number of things which do not work or are not implemented. Unfortunately no list seems to exist. However, fixed-font doesn't work. Also, if you click on a wxTextCtrl, the cursor position is not set correctly. There may be others. wxMac is a product which is still under development, and not as mature as the wxWin release, for instance. But it works fine for simple applications.

wxWidgets for Mac (wxMac) can be installed in several ways. The install.txt presumes that wxMac will be built as a library which is installed with the system software and used like a DLL in MS Windows. However, it is rarely desirable to install non-Apple software into system directories. While using this method is okay for development, it is not recommended that you require endusers to install wxWidgets into their system directories in order to use your program. One way to avoid this is to configure wxWidgets with --disable-shared. This ensures that wxMac is linked statically into the executable. This is the recommended approach. (Another way to avoid using dynamic libraries is to make a framework for wxWidgets. Making frameworks is beyond the scope of this document).

Differences from the install.txt are noted as we go along.

Install Steps

The steps to install wxWidgets for the Mac (wxMac) are as follows.

  1. Download and create a folder
  2. Open a Terminal Session
  3. Compile and install the wxWidgets library
    1. Static library (cf .lib)
    2. Shared Dynamic link library (cf .dll)
      1. Compile the wxWidgets library
      2. Installing the wxWidgets library
        1. Option 1: Enabling 'root' userid
        2. Option 2: Using an admin account
        3. Install the libraries
        4. Exit

Download and create a folder

Use your browser to get the download from the downloads page (use the wxwidgets-2.4.2.tar.gz). This will save onto the desktop, and then unpack and create a .tar file, and then a wxMac-2.4.2 folder, both on the desktop. The .tar file can be dragged to the trash icon and deleted. (Don't get the zip, get the tar.gz -- otherwise you may get some 'permissions' problems when compiling).

There is a known problem in Mac OSX 10.3 (Panther): the .gz download won't compile. The symptom is

 c++ -c   -I./lib/wx/include/mac-2.4 -I../include -I../src/png 
 -I../src/jpeg -I../src/tiff -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES 
 -no-cpp-precomp -fpascal-strings -I../src/mac/morefile 
 -I/Developer/Headers/FlatCarbon    -D__WXMAC__ -DWXMAKINGDLL  -O2 -MMD 
 -fno-common -Wall -dynamic -fPIC -o dc.o ../src/mac/dc.cpp
 ../src/mac/dc.cpp:1259: error: parse error before `<<' token
 ../src/mac/dc.cpp:1263: error: parse error before `short'
 make: *** [dc.o] Error 1

To compile with Panther, you'll need to download the wxMac 2.4.2 from CVS using the WX_2_4_BRANCH tag. See: CVS for instructions on checking out from CVS.

As you will be using this folder a lot, I recommend you rename it to wxmac. You can do this in the same way as in MS Windows. OSX is case sensitive, so keep the names all in lower case.

Open a Terminal session

You then need to start a Terminal session. This is equivalent to a DOS box, but the commands are all in UNIX. To start Terminal, click on the desktop to get the 'Finder', then Go|Applications. At the bottom of this folder will be the Terminal program. (Also in the same folder is the Netinfo manager that you will need later if you need 'root' access). Open a Terminal session by double-clicking on the icon. You will find yourself in the home folder of your userid. You may return here from anywhere using cd ~.

In the terminal window, type ls. This will give you a list of files. One of them will be 'Desktop'. Do cd Desktop (NB: Unix is case-sensitive). This will place you in the Desktop folder -- the same as your desktop, but if you use ls again, this time you will see it for what it is, a collection of files and folders.

Among the folders in the Desktop is wxMac. Use cd to change to this, and ls to verify the contents. You can also use pwd to check you are in the right folder. If you are in the wrong folder, it won't work.

You are now in the 'base dir'(ectory) -- ~/Desktop/wxmac.

Compile and install the wxWidgets library

As in MS Windows, wxMac can be compiled to either a static library, linked into the execute (like a .lib), or a dynamic library installed with the system software (like a Windows DLL). Both are detailed below. The former is the better solution, unless you never intend to distribute your applications.

  • Static library (cf .lib)
  • Shared Dynamic link library (cf .dll)

Static linking (cf. lib)

Starting in the base directory (wxMac) do:


1) ./configure --disable-shared

This will take a while, as it checks what options your system requires. This will create a file 'Makefile' which will be run to compile the libraries. It also creates a Makefile in each of the 'samples' folders, which will be useful later for compiling these. See Additional Notes for extra options to compile for OpenGL.

Note: The install.txt recommends creating a subdirectory 'build' or 'macbuild' or 'osx-build' under the base directory, and running configure from there. This keeps stuff out of the base folder. However it creates two sets of folders for everything: a build/samples for all the samples, which contains the executables. It is simpler not to do this, and allow executables to be created in the same folders as the source, as happens in MS Windows.

If you get an error running ./configure such as 'command not found' or some such wording, you probably downloaded the .zip rather than the tar.gz. The .zip file won't create the necessary unix permissions, and there are reports that the files have DOS line endings -- CRLF, rather than LF as required by Unix/MacOSX. If you install from the tar.gz file, the correct unix permissions are recreated (which makes configure executable) and the files don't have CRLFs on them.

2) make

This runs the Makefile, and compiles everything. It takes quite a while to run. A few warning messages about unused variables are normal.

Note on DistCC: However, you can speed up compilation with distcc, if you have two or three (or a lab) of Macs sitting around the office.

You'll need to install distcc first of course - and it's probably preferable to build it from source. I suggest installing DarwinPorts, then:

sudo /opt/local/bin/port install distcc

You'll need to do this on all machines involved in the distributed build.

Follow the instructions on the distcc page from there.

When you get read to build wxWidgets, first execute this command to set up your enviroment properly:

export CC="/opt/local/bin/distcc gcc" CXX="/opt/local/bin/distcc g++"

This will work if you are using the default shell on 10.3, the 'bash' shell. On 10.2 the default shell is 'tcsh', where the command would be:

setenv CC "/opt/local/bin/distcc gcc"; setenv CXX "/opt/local/bin/distcc g++"

now use this make command:

make -jN

(where N is replaced with the proper -j value - usually double the machines you have).

Note: the distcc instructions tell you to specify the CC and CXX commands in the make command, however some users have found that that causes wxWidgets to give strange compiler errors. It's not sure at this time if this is a pilot error, or something wrong with either distcc or wxWidgets.

3) rm *.o *.d

This cleans up the object files from the base folder, since they are no longer needed.

The samples can now be compiled as below.

(stuff about using `wx-config --in-place` in makefiles needed -- TBA).

Dynamic linking (cf .DLL)

The dynamic libraries must be first created, and then installed into the system folders.

Compile the wxWidgets library for Dynamic linking

Under MacOS 10.1 with the Apple Developers Tools installed, do the following:

Steps 1 and 2 are optional (see note)

mkdir build 
cd build

This will create a new folder, in which all the binaries get built, separately from the source. It will then change into the directory.

Note: If you don't make a separate 'build' folder, and just do ./configure and make in the wxmac folder, this will work fine. In this case, all the samples binaries will be in the same folder as the source code (if you like that). Another benefit is that a makefile will be automatically created for each sample in that folder. Finally, there will not be the plethora of samples folders, and this will be convenient when you come to build your first app. On the negative side, obviously you can only make one build type in this "base" wxMac folder, though. One other problem is that the wxmac folder will have loads of .o and .d files created in it during the compile -- remove these at the end of this step with 'rm -f *.o' and 'rm -f *.d'.

3) ../configure.  

This will create the Makefile file, working out what options your Mac can support. There will be loads of stuff written to the screen, none of it of much interest. See Additional Notes to compile for OpenGL.

4) make

This actually builds the library, creating a set of files in the build folder called things like libwx_mac-2.4.0.1.1.dylib, libwx_mac-2.4.0.dylib. These are the equivalent of .lib files. Note that it takes absolutely ages.

Installing the wxWidgets library (as shared dynamic link libraries/DLLs)

The libraries must now be made available to your code. They can either be made available as shared libraries (like DLLs in MS Windows) or linked in statically to your code. The latter is preferred, obviously, as it makes it easier to distribute your applications.

Option 1: Using the libraries without installation

It is possible to use the libraries directly from the build directory, without installing them, and without requiring admin privileges. To do this, run the initial configure command as follows:

./configure --prefix=$(pwd)

This will set certain paths to point to the build directory.

Next, run

make

and skip the instructions below that suggest running make install.

The wx-config command to use will naturally have to be given with the full path to the build directory.

Option 2: Using an admin account

If you want to install the headers and libraries to a system-wide directory (which only makes sense on a system where multiple users develop with wxMac), you can use an admin account -- your normal id should be one.

First, run

./configure --disable-shared

Next, install the library with

sudo make install

The "sudo" is a command which allows a command to run with root privileges so long as the user is registered as an admin user. It will prompt you for your password.

NB: If you have to create a new user manually, (in the Accounts System Preference panel - Access this by going to the Apple menu and selection System Preferences) there will be a checkmark somewhere (it varies from OS X version to OS X version) about 'allow this user to administer computer'. (In OS X 10.3 this is in the Security tab)

Additional notes - Optional

If you want to activate OpenGL, replace your 'configure' step with

../configure --with-opengl

But this is unnecessary for a normal build.

Building the samples

This is very easy. In wxMac 2.4.2:

1) cd samples/minimal
2) make

This will build the minimal sample.

In wxMac 2.5.1 (the development snapshot), if you do this immediately after making the library, the make fails with "error: 'sample_xpm' undeclared' in samples. It is indeed absent.

Instead, use the makefile present in samples and compile all of them in one go. However, a significant number seem to fail.

1) cd samples
2) make

which will compile all of them, and create the necessary .xpm for subsequent individual compilations.

The sample can then be run either by clicking on the icon in the finder, or by doing this in the Terminal:

3) ./minimal &

This should run exactly as it does in MS Windows.

Note: In unix you have to specify the path, as unix can't find files in its own current directory without special configuration. And OSX is a flavour of unix.

That's all you need to do with any of the 'samples', 'demos' or 'contrib/samples' -- just change to the folder and run the Makefile. (These makefiles are very small, by the way, and you can open them for edit in the Finder using a GUI textedit).

You should now have a functional wxWidgets setup on your Mac.

However, if you compiled in a separate 'build' folder ('wxmac/macbuild' or 'osxbuild' or whatever you called it), then you will have to do more work:

Making samples if you compiled in 'build'/'macbuild'/'osx-build'

(NB: This step is written from memory, and the exact locations of the configure stuff is vague. But the general approach works).

Once you have created the library and installed it, and returned to your own userid, do this:

  1. Make sure you're in the build folder (e.g. wxmac/build).
  2. Change to the "samples" folder.
  3. (This is the bit I'm unsure about) Run another "configure" file. This will build the Makefile -- a different one to that used above.
  4. make

This will create makefiles in each sample folder underneath "build". You compile the sample code from the build subfolders, not from the wxMac-2.4.2/samples folders in which the source code is (unlike in Windows where it's all in one place). <p> Then change to the folder for (e.g.) splitter and type "make". The binary "splitter" will be created in that folder. You can run it from the terminal by typing "./splitter". (the dot-slash is needed because your current directory is not in your Unix PATH, which it searches for binaries to run). You can run it from the Finder by clicking on its icon.

Building my first application -- a sample with a tiny change

The simplest approach is to take a sample folder such as 'minimal', and copy it to 'yourapp' in the same folder. If you keep the relative paths the same, the makefiles used for the samples will work for 'yourapp' also.

In detail:

  1. Go to wxMac/samples
  2. Copy the 'minimal' folder to 'myapp' This will copy the source minimal.cpp file. (You should change the wxFrame title in this, so you can prove to yourself when it runs that you are running your code and not the sample).
  3. Go to wxMac/build/samples. (if you created a 'build' folder -- ignore steps 3 and 4 if not)
  4. Copy the 'minimal' folder to 'myapp'
  5. Go into the 'myapp' folder. This will probably only contain one file 'Makefile'.
  6. Edit Makefile. Change the program_dir from 'samples/minimal' to 'samples/myapp'. Save the file.
  7. In the terminal, make sure you're in the build/samples/myapp folder, and type 'make'. The myapp should compile, and create a 'minimal' executable and 'minimal.app' folder (in Finder these will appear as two icons, one of which is the application and the other the resource. Click on either to start the application).

Note that a GUI project builder file exists in the minimal folder -- minimal.pbproj -- but not for any other sample. You can open this by double-clicking on it in the Finder. This is more fussy about folders and versions of OSX than the makefiles, tho. [I have not been able to compile this]

Building my second application -- more than one .cpp file, and a common mistake

Most real applications involve more than one .cpp file. The best way to do this is to start with a sample, and modify it. However you can use the TextEdit GUI tool (in Applications) to do this.

If you copy the 'minimal' folder to 'myapp2', then the Makefile file has to be changed to look like this. (mycode.cpp and myconsts.cpp are my new files: all the rest is exactly as generated).

# Generated automatically from Makefile.in by configure.
#
# File:		makefile.unx
# Author:	Julian Smart
# Created:	1998
# Updated:	
# Copyright:	(c) 1998 Julian Smart
#
# "%W% %G%"
#
# Makefile for minimal example (UNIX).
top_srcdir = ../..
top_builddir = ../..
program_dir = samples/myapp2

PROGRAM=myapp2

OBJECTS =$(PROGRAM).o mycode.o myconsts.o 
DEPFILES=$(PROGRAM).d mycode.d myconsts.d

include ../../src/makeprog.env

-include $(DEPFILES)

This will work.

One common error you get is this:

[localhost:~/wxmac/samples/myapp2] myuser% make clean
myconsts.o:1: warning: NUL character seen; rest of line ignored
myconsts.o:1: *** missing separator.  Stop.
[localhost:~/wxmac/samples/myapp2] myuser% 

Always start with a 'make clean', which deletes any .o (.obj) files. If it fails, you made a typo in your makefile.

This particular error is caused by putting a .o in the DEPFILES line. (The 'NUL character' error is not always there, but the 'missing separator' is a giveaway of a Makefile error). There is nothing wrong with myconsts.cpp at all.

Setting up your work area: creating an app outside of the wxWidgets folders -- the better alternative

In Ms Windows, you do not normally develop your code in the wxWidgets software directory. I believe it is possible to likewise do this under wxMac. This involves a fair bit of work, and there is another alternative:

Creating your work area underneath the 'samples' folder.

In all Unix flavours, including OSX, a 'soft-link' or 'alias' to a folder can be created. So if you have a deep chain of folders under your home area such as ~/1/2/3/4/5/6/7, you need not type cd forever. Instead, just create an alias:

ln -s ~/1/2/3/4/5/6/7 my7

This will create a pseudo-folder (alias) in the folder in which you run this, and you can just 'cd my7'. You can also do this through the Finder with File.Make Alias.

The way to structure things is to create a new folder under wxmac/samples, called (e.g.) myapps. Copy the minimal folder into myapps. Then edit the Makefile in your copy, by adding an extra '../' to each of the paths, and making sure you change the program_dir to samples/myapps/minimal. Then just compile away normally. You can nest these folders as deeply as you like, by adding more '../'s in, and the makefiles will still work. myapps may be deeply nested -- but just create an alias to it from your home area, so you don't care about the rest.

Platform specific code

We all have this. Stuff that uses MSVC pragmas. Stuff that has Windows system calls. Now this code all works, so you don't want to dump it: but it won't work on the Mac.

The solution is conditional defines in the code. Just stick

#ifdef __WXMSW__
...
#endif

around it.

The define for Mac is __WXMAC__. A full list of these Constants is in the wxWidgets Reference, under 'Constants'.

Remember that for file i/o, the slashes go in the other direction: c:\fred; ~/fred/

Executables ('Bundles')

On Mac OSX, the output from the compiler is not just a single binary executable file. The thing the user clicks on is not the executable, but a 'Bundle'. This is actually a folder, containing a hierarchy of folders. The actual executable created by the linker is in ./Contents/MacOS.

Just to confuse the newcomer, the compilation process runs the linker twice. This produces two files in your compilation directory -- myApp, and myApp.app. The latter is the bundle, and the file you want to distribute -- it has the wxWidgets icon if you look in the folder using the Finder. The former is best deleted, and has a Project Builder icon in Finder.

  • You can run myApp by doing ./myApp at the command line. However, this file has a Project Builder icon if you look at the folder in Finder.
  • The file labelled myApp in the Finder, with the pretty icon, is actually the folder myApp.app. This folder is the 'Bundle'. This you run at the command line by doing 'open myApp.app'.

The .app bundle system can be an extremely easy and flexible way to manage applications. Installation is usually not even necessary. Just drop the application into your programs (called "Applications") folder.

All support files for the application are inside the .app bundle, except for application preferences. Those are stored in the user's "~/Library/Preferences" folder. (That way, you can dump the application in the trash, and if you later download a newer version, etc. your prefs are still there.)

In some ways this system is easier for the end user to get their head around. Rather than have some 'start menu' with a bunch of programs that live in the ether (for all the user knows), on Mac there is just a special folder called Applications, and that's where your programs are. Double-click on the program icon, and the program starts. Move the icon, that's fine, program still works. Create folders and organize applications just as you would with other folders and files. You can also try an application without installing it, and just delete if you don't like it. No unnecessary clutter or complexity for the end user, or the developer. This does mean that most apps should bundle their shared libs with them, but it certainly beats Windows DLL hell.

Structure of a bundle, or, what goes where

Your executable is this folder, myapp.app: the 'application bundle', in Apple-speak. You can use the command line to explore inside the folder. There is also "Show Package Contents" in the context menu of a bundle so you're not stuck on the command-line manipulating the directory structure. (The 'context menu' comes up when you Ctrl+click on the file (or right click if you have a multi-button rodent)).

Inside is a set of sub-folders, organised in a set way. The first time you successfully compile your program, the makefile will create the bundle and sub-folders. You may need to create a couple more. The folders must be named as specified, so don't monkey with these.

myApp.app contains only a single folder Contents. Everything belongs under myApp.app/Contents.

The following folders exist in Contents:

  • MacOS -- where the executable (only) lives
  • Resource -- where .icns files live (Mac Icons files, editable with the Icon Composer utility in your Developer folder).
  • SharedSupport -- where static content like bitmaps, static data files, etc live (you will have to create this folder yourself using mkdir SharedSupport in your bundle, then you can use it.

There can be others, which don't matter to the newcomer:

  • myapp.app is a directory
  • myapp.app/Contents is a directory and is the ONLY thing inside tl.app
  • myapp.app/Contents/MacOS is a directory
  • myapp.app/Contents/MacOS/myapp is simply the normal UNIX binary (the wx 2.4 makefiles actually run the link step twice as noted above, but copying would be sufficient as well).
  • myapp.app/Contents/Resources is a directory
  • myapp.app/Contents/Resources/myapp.rsrc contains what would normally be in the resource fork of an unbundled application in the normal data fork in an old MacOS application. Use the -useDF option to Rez.
  • myapp.app/Contents/PkgInfo is an 8-byte file containing the type and creator codes. Typically this is APPL???? which means it is of the APPLication type with an unknown creator. You can if you wish register a creator code with Apple and use it instead of ????.
  • myapp.app/Contents/Info.plist is an XML file describing your application. Steal one from one of the samples and modify it to suit your tastes.

Since MacOSX is UNIX, you can create bundles entirely from the command line and the only special tool you really need is "Rez" which like any self respecting UNIX tool has a man page.

User preferences belong in the /Library/Preferences folder under the users home folder, and are best handled using wxConfig (there is a useful sample program to show you how).

Doing stuff with bundles

This involves making OSX system calls, and you'll want to look at the Apple documentation (see below). You'll need some includes:

#ifdef __WXMAC__

// For most stuff
#include <Carbon/Carbon.h>

// For bundle-related stuff
#include <CFBundle.h>

#endif

To find the system calls you need, look at things like CFBundleGetMainBundle() which gets the bundle for the currently running application (you are not responsible for releasing this) and CFBundleCopySharedSupportURL() which returns a CFURLRef that you are responsible for releasing. From there check the CFURLRef documentation to see how to eventually get a string representing the file path from which you can construct a wxFileName.

(On MSW you'd typically want to look in the directory from which the application started for this stuff and on UNIX you'd typically want to look in $(prefix)/share/appname (where prefix is usually /usr but sometimes also /opt/appname). So this is an area where wxWidgets really needs some expansion)

Here is some code to do some common things. (Remember to stick it all between #ifdef's, or your code won't compile on Windows, only on Mac OSX).

Code to find SharedSupport folder

Here's some code to find the full path to the 'SharedSupport' folder in the bundle (which is where you put your bitmaps, support files, anything read-only that your application needs -- the stuff that goes in the same folder as the executable in Windows, or as static content on UNIX belongs in ${prefix}/share ):

wxString myClass::GetBundleSharedSupportDir()
{
 CFBundleRef mainbundle = CFBundleGetMainBundle(); // Ref is NOT owned by us
 if(!mainbundle)
 {
  wxLogDebug("Application is not bundled!");
  return wxEmptyString;
 }
 CFURLRef CFurl = CFBundleCopySharedSupportURL(mainbundle);
 if(!CFurl)
 {
  wxLogDebug("Couldn't get executable URL");
  return wxEmptyString;
 }
 CFIndex bufLen = 1024;
 unsigned char buffer[1024];
 if(!CFURLGetFileSystemRepresentation(CFurl, TRUE, buffer, bufLen))
 {
  CFRelease(CFurl);
  wxLogDebug("Failed to get FS representation");
  return wxEmptyString;
 }
 // The docs on CFURLGetFileSystemRepresentation are unclear, be safe.
 buffer[1023] = '\0';
 CFRelease(CFurl);
 return wxString(buffer);
}

Note that this can return an empty string if you are running the executable outside the bundle, rather than the bundle. Note also that some of the handles obtained must be released using the CFRelease() API call, otherwise a memory leak occurs (whether you need to do this for a given API call is usually specified in the Apple docs).

Code to find full path of executable inside the bundle

It is questionable why you want to do this, tho. In Windows you do it because your data files are in the same folder as the exe, and you want to read them. But in MacOSX, they should be in the SharedSupport folder. The code is much the same as above, except for the use of a different 'Core Foundation' call.

#ifdef __WXMAC__
wxString stFindBundle()
// Find the full path of executable in the bundle -- may be blank
{

 CFBundleRef mainbundle = CFBundleGetMainBundle(); // Ref is NOT owned by us
 if(!mainbundle)
 {
  wxLogDebug("Application is not bundled!");
  return wxEmptyString;
 }
 CFURLRef CFurl = CFBundleCopyExecutableURL(mainbundle);
 if(!CFurl)
 {
  wxLogDebug("Couldn't get executable URL");
  return wxEmptyString;
 }
 CFIndex bufLen = 1024;
 unsigned char buffer[1024];
 if(!CFURLGetFileSystemRepresentation(CFurl, TRUE, buffer, bufLen))
 {
  CFRelease(CFurl);
  wxLogDebug("Failed to get FS representation");
  return wxEmptyString;
 }
 // The docs on CFURLGetFileSystemRepresentation are unclear, be safe.
 buffer[1023] = '\0';
 CFRelease(CFurl);
 return wxString(buffer);
}

Code to find a named file in the Resource sub-folder

 wxString stFindResourceFile(const char * name, const char * extension)
 // Find the full path of file name.extension in the resource folder of the bundle -- may be blank
 {
 //GetBundleSharedSupportDir()

 CFBundleRef mainbundle = CFBundleGetMainBundle(); // Ref is NOT owned by us
 if(!mainbundle)
 {
  wxLogDebug("Application is not bundled!");
  return wxEmptyString;
 }
 //If you have only one name, myfilename.gif, you could do this...
 //CFStringRef stSpl = CFSTR("myfilename");
 //CFStringRef stBmp = CFSTR("gif"); 

 CFStringRef stSpl = CFStringCreateWithCString ( NULL, name, kCFStringEncodingASCII  );
 CFStringRef stBmp = CFStringCreateWithCString ( NULL, extension, kCFStringEncodingASCII  );
 CFURLRef CFurl = CFBundleCopyResourceURL(mainbundle,stSpl,stBmp,NULL);
 if(!CFurl)
 {
  wxLogDebug("Couldn't get executable URL");
  return wxEmptyString;
 }
 CFIndex bufLen = 1024;
 unsigned char buffer[1024];
 if(!CFURLGetFileSystemRepresentation(CFurl, TRUE, buffer, bufLen))
 {
  CFRelease(CFurl);
  wxLogDebug("Failed to get FS representation");
  return wxEmptyString;
 }
 // The docs on CFURLGetFileSystemRepresentation are unclear, be safe.
 buffer[1023] = '\0';
 CFRelease(CFurl);
 return wxString(buffer);
}

Finding useful info in the Apple Developer Documentation

This documentation is not well-liked, as you need to have an overview before any of it makes sense, and there are no examples of how to use the system calls. In other words, it's just as bad as the poorer stuff in the MSDN.

The "problem" with the Apple documentation is that it's organized for developers who have some familiarity with the system already. Once you get to know more about the Mac it will all start to make a lot more sense.

There are at least a couple pages on the developer.apple.com website that provide an overview of OS X with some graphics showing you how Carbon and Cocoa (families of APIs) are built atop Quartz and that's built atop CoreFoundation and so on and so forth. This will give you clues to how the APIs all fit together.

It is recommended you spend an hour or so reading some of the basic system overview documentation and introductions to OS X development. Anything you can learn will help you.

To get an overview:

Reading that will give you a clearer understanding of where you might want to look when trying to find things. Unfortunately some of these files are large and full of marketting guff, so you will probably need to skim. A PDF form is available if you look.

(Would someone like to digest this down into something short and useful to Windows chaps and write a page in this Wiki about it?)

To find data on System calls concerned (e.g.) with Bundles:

  • Go to developer.apple.com and click on Documentation under the Reference Library heading.
  • From there click Core Foundation and then Core Foundation Reference. This will give a list of topics.
  • Find CFBundle in the list and bring up either the HTML or PDF documentation.

Documentation also comes installed on your machine: look in file:///Developer/Documentation/index.html.

More stuff on bundles, gestalt (finding out about your hardware) and other interesting topics: http://developer.apple.com/documentation/Carbon/ResourceManagement-date.html

Glossary note: You will see references to things such as 'CFBundle opaque type'. 'Opaque type' is really just Apple's term for an OO class done in C. It just means 'a class'.

Preferences -- the Mac equivalent to the Windows Registry

System-wide preferences are stored in /Library/Preferences, while user preferences are stored in ~/Library/Preferences. Preferences themselves are stored as indiviudal files, unlike the Windows registry, which expects you to store your preferences as a series of keys.

(Think of /Library/Preferences as similar to HKEY_LOCAL_MACHINE\SOFTWARE\, while ~/Library/Preferences is similar to HKEY_CURRENT_USER\SOFTWARE\.)

For more info on how the MacOS X file system is laid out by default, see

http://developer.apple.com/techpubs/macosx/Essentials/SystemOverview/FileSystem/How_the_Fil_s_Organized.html

Now from an application you should *not* access the preferences of another application unless you know what the hell you are doing. Further, you should not use the absolute paths given above (because in some circumstances these paths *can* *change*, such as in a netboot environment). Instead, if you are coding from the Carbon API, you should use FindFolder(), and 'kSystemPreferencesFolderType' as the selector. (See the header file 'Folders.h' for more information.)

Sample code

Apple places examples of how to use the functions here:

http://developer.apple.com/samplecode/

Feedback

Use the mailing list, or the google mirror of it, comp.soft-sys.wxwindows to ask questions, give feedback, etc. Expressions of appreciation always welcome!