Distributing WxWidgets Applications-Distributing WxMac Programs

From WxWiki

Jump to: navigation, search

(This page is a work in progress)

Contents

[edit] Creating a Bundle

On Mac, it's nice to distribute your applications as one self-contained 'Bundle'. A 'bundle' is basically a directory with a given structure, typically named 'foo.app', which shows up as a drag-and-droppable, startable 'program'.

TODO: describe this better.

Gotcha: when you change Info.plist, sometimes the information in it is still cached somewhere. A reboot might help, I'm not sure how to do this gracefully.

[edit] Statically compiling

This didn't really work for me.

I compiled wxMac like this:

 ./configure --disable-shared --enable-monolithic --disable-dynlib --disable-dynamicloader --prefix=/Users/arnoutengelen/local

Now you can simply compile using wx-config, but it will link dynamically to some libraries like libiconv (though this might not be a problem since supposedly this dylib is distributed with any reasonably recent (10.3+) versions of MacOS X). Adding '-static' to the command fails with the following error message:

 /var/tmp//ccPTunDf.s:9427:FATAL:incompatible feature used: directive .non_lazy_symbol_pointer (must specify "-dynamic" to be used)

I don't know how to fix that (yet).

[edit] Including shared libraries in the bundle

Luckily the site at http://doc.trolltech.com/qq/qq09-mac-deployment.html explains how to include the shared libraries in the bundle itself:

  • Create a Contents/Frameworks directory in the bundle
  • Use 'otool -L' (the Mac alternative for 'ldd') to see which shared libs are required
  • Copy the shared libraries into it
  • For the library:
     install_name_tool -id @executable_path/../Frameworks/whatever.dylib demo.app/Contents/Frameworks/whatever.dylib
     
 And for the executable:
 
     install_name_tool -change /path/to/whatever.dylib @executable_path/../Frameworks/whatever.dylib demo.app/Contents/MacOS/demo
  • check if that worked with otool

(untested right now..)

[edit] Including shared libraries in the bundle (Verified)

The problem of the method above is that the dynamic libraries themselves depend on the library. With patching the executable only it's not done.

All library-internal cross references have to be removed (replaced) too. The library is linked internally to the major.minor.micro named versions of the dynamic libraries (e.g. libwx_mac_qa-2.6.0.dylib).

To accomplish this task I've written a bash script which is listed here (I haven't found a sourcecode highlighting function for this wiki -- is there any?):

     WXLIBPOSTFIX=*wx*2.6.0.dylib
     APP=WorldApp
     
     WXLIBDIR=../../../wxwidgets/build-dynamic/lib
     BINDIR=./build/Release/$APP.app/Contents/MacOS
     LIBDEFDIR=/usr/local/lib
     
     echo "Copying dynamic libraries to " $BINDIR " ..."
     cp $WXLIBDIR/*.dylib $BINDIR
     
     echo "Changing directory to " $BINDIR " ..."
     export TMP=$PWD
     cd $BINDIR
     
     # patch all wx dynlibs and Saracon executable
     for file in `ls $WXLIBPOSTFIX`
     do
           # patch all library internal cross references
           echo "Patching " $file "..."
           for fileother in `ls $WXLIBPOSTFIX `
           do
                 # library
                 echo "  Patching " $fileother " with " $file "..."
                 install_name_tool  -change $LIBDEFDIR/$file @executable_path/$file  $fileother
           done
           # patch current library itself
           install_name_tool  -id  @executable_path/$file  $file
           # patch executable
           install_name_tool  -change $LIBDEFDIR/$file @executable_path/$file $APP
     done
     cd $TMP

This script can be added for instance to the build phases of XCode or called from within of a makefile. Make sure that's a bash shell. Others might cause errors. Furthermore the executable has to be linked with the

 -headerpad_max_install_names

option enabled to ensure install_name_tool will work correctly (otherwise complications may arise due to the fact that there is no room for the new pathnames in the executable)

The following variables are required:

  • WXLIBPOSTFIX: The wx dylib pattern which matches the desired version and wx-internal cross references.
  • APP: The executable name.
  • WXLIBDIR: Directory of the wxWidgets dylibs (can also be a system directory when installed)
  • BINDIR: Directory of the executable AND dylibs (it's a limitation of this script but it can be adapted easily)
  • LIBDEFDIR: Default dylib directory when linking (ususally it's '/usr/local/lib'). It can be found out when inspecting the crash report...

[edit] Creating a .DMG

http://www.stepwise.com/Articles/Technical/2001-03-29.01.html describes how to package your application as a DMG. This seems to be slightly outdated though. The steps I'm using are:

  • hdiutil create -megabytes 10 -layout NONE Pathalizer.dmg
  • hdid -nomount Pathalizer.dmg
  • newfs_hfs -v pathalizer /dev/disk1
  • hdiutil eject /dev/disk1
  • hdid Pathalizer.dmg
  • cp -r Pathalize.app /Volumes/pathalizer/
  • eject using finder


[edit] See also

 http://developer.apple.com/technotes/tn2002/tn2071.html 
 http://developer.apple.com/documentation/DeveloperTools/Conceptual/cross_development
Personal tools