pyobjc / pyobjc-xcode / Doc / XcodeIntegration.txt

PyObjC Xcode Templates

:Author: Bob Ippolito

The PyObjC Xcode Templates offer an alternative to developing
applications "by hand" using py2app, as described in the
tutorial.  As of PyObjC 1.3.1, these templates are py2app based,
so there is no longer a technical reason not to use them.

.. contents::


If you have installed PyObjC 1.3.1 or later using the installer, then
the Xcode templates are already installed.  

If you have installed any version of PyObjC prior to 1.3.1, then you
may have old Xcode templates installed.  These Xcode templates named
"Cocoa-Python Application" and "Cocoa-Python Document Based Application"
should NOT be used, and it would be wise to remove them.  They can
be found here::

    /Library/Application Support/Apple/Developer Tools/Project Templates

If you want to install the packages using setuptools use the following 

   $ easy_install pyobjc-xcode
   $ pyobjc-xcode-install

The latter command makes the templates available to Xcode as the former installs
the templates and support code in a location where Xcode won't pick them up.

Removing the templates is easy as well, but requires some manual intervention
at this time. Use ``pyobjc-xcode-uninstall`` to remove the templates from 
Xcode's search path, and then install the ``pyobjc-xcode`` egg the usual way.


- These templates are brand new in PyObjC 1.3.1 and haven't had much
  use yet.  If you think that you have found a bug or would like them to be
  changed in some way, please speak up on the `pyobjc-dev`_
  mailing list, and/or `report a bug`_.

.. _`pyobjc-dev`:
.. _`report a bug`:

- The Python interpreter used by the templates is determined by the
  first line of the ```` file.  By default, it points to::

      #!/usr/bin/env python

  This means that whichever Python that comes first on the ``PATH``
  will be used.  This will normally be the Python 2.3 interpreter
  that ships with Mac OS X.  If you would like to use a different
  interpreter, you have two choices:

  1. Edit the first line of ```` to point to the desired
     interpreter explicitly, for example::


     This change must be done to every project that you use the
     template from.  Alternatively, you can make this change
     to the templates themselves so that this is set for all
     new projects.  See the Installing section above for the
     location of these templates.  If you choose to do this,
     edit the ```` directly.  Do not open the
     ``.xcode`` project in the template, as Xcode templates
     can be rather fragile.

  2. Change your ``PATH`` environment variable so that the location
     of your Python interpreter appears before the others.  Since
     LaunchServices and thus Xcode is not started by your user shell,
     you will need to specify it in a plist.  See `QA1067`_, 
     `Runtime Configuration: Environment Variables`_, and the 
     `EnvironmentPrefs`_ System Preferences plug-in example that
     comes with PyObjC for more information about how to do this.

.. _`QA1067`:
.. _`Runtime Configuration: Environment Variables`:
.. _`EnvironmentPrefs`: file:///Developer/Python/PyObjC/Examples/Plugins/EnvironmentPrefs

     This change will be specific to your user account, and will
     take effect globally, which may or may not be a good thing.

- The Clean command currently does not remove everything, if you
  want to ensure that the project has actually been completely
  cleaned, then you should remove the ``build`` folder yourself.

- Like Xcode, the built product and temporary files will both end
  up in the ``build`` folder unless explicitly specified that they
  should go elsewhere.  When not using these templates, py2app
  would normally put the result in a ``dist`` folder.

- If you need to include non-system frameworks or dylibs that are not otherwise
  referenced by a Python extension, then link to them from an Objective-C
  plug-in.  py2app will find them and put them into your application!
  See PyObjC Mixed Application below for more information about using
  plug-ins to integrate non-Python code into your application.


The PyObjC Xcode templates use py2app to build applications,
but they parse the ``.xcode`` project file to determine
how they should be built, rather than directly in the
````.  The parser, in ``PyObjCTools.XcodeSupport``,
gives special meaning to several groups.  If these groups
are renamed or removed, your project may not build correctly!

Main Script:
    This group should contain exactly one file, the main script
    of your application.  The default main script in the template
    generally does not need to be changed.

    If you need to ensure that additional code is imported, simply
    place it in the Classes group.  You shouldn't need to modify
    your main script.

    ONLY the main script should be in this group.

    Every file in this group goes into the ``Resources`` folder
    inside of your application bundle.

    Any ``.nib`` files that are in this folder will
    be parsed with ``PyObjCTools.NibClassBuilder.extractClasses``
    by  the main script before any modules in the Classes group
    are imported, and before the run loop is started.  You should
    not need to call ``extractClasses`` manually in your code.

    Source code should not go in here.
    Modules in the classes group will be imported by the main
    script in the order that they appear in the Xcode project,
    after all classes are extracted from the nibs.

    Every Python module in this group is guaranteed to be scanned
    by py2app for dependencies.

Other Sources:
    This group is not actually special.  You may put anything you
    want in this group.  It is used by the templates to store
    files and source code that do not fit into any of the above
    categories, such as the ``Info.plist`` and the ````.
        This is the script that is actually used to build your
        project.  It may also be used from the command line
        either directly or via ``xcodebuild``.  Read the file
        for more instructions.  This script must not be renamed
        or removed.

        If you need to customize the py2app or distutils
        build process, you should modify the ``setup_options``
        dict before the ``setup(...)`` function is called.

        When present, this file is used as a template for your
        application's ``Info.plist``.  If you rename or delete
        it, then it will not be used and plist will be
        generated by py2app.  For information about what
        can go in this plist, see
        `Runtime Configuration: Property List Key Reference`__.

.. __:


    This target will use py2app ``--alias`` build mode.  Executables
    built with this mechanism are produced very quickly, and use the
    sources in-place via symlinks and ``sys.path`` manipulations.
    These executables are not redistributable, much like development
    executables produced by Xcode when using Zero-Link.

    This target will use py2app's default build mode, ``--standalone``.
    This will create a standalone bundle out of your application that is
    redistributable.  Everything that py2app determines to be
    needed by your application will be included in the executable,
    including Python itself, extensions you use, and dynamic
    libraries or frameworks that are linked to by these extensions.
    If you are using a Python distributed by
    Apple, then it will be built in ``--semi-standalone`` mode.
    This means that Python and its standard library *will not*
    be included in the application.

    Using the Deployment *target* does not automatically
    imply that you are using the Deployment *build style*.  This is
    only relevant when using the PyObjC Mixed Application template,
    or are otherwise using the same project to compile non-Python
    source code.  To change the current build style, Get Info on the
    project.  The build style has no effect on Python code.

Custom Executable

The custom executable enables for your built application to be run from Xcode.

If you rename your main script or fiddle around with your ``Info.plist``,
the path to your application may change and this will no longer work.
If that is the case, use Get Info on the custom executable and change
the Arguments to point to the correct path.

By default, executables are launched with the ``USE_PDB`` environment variable
set for both Development and Deployment targets.  This turns on verbose stack
traces whenever an exception crosses the PyObjC bridge, and will drop you at
a pdb prompt in the console when an uncaught exception occurs.

Other useful environment variables that you can set, such as ``NSZombieEnabled``,
as well as all kinds of other debugging tricks you should know are covered
in `TN2124: Mac OS X Debugging Magic`__.

.. __:

If Xcode screwed up and didn't create a Custom Executable, which is not
beyond the realm of possibility, then you can create one as follows:

1. Create a Custom Executable for ``/usr/bin/env`` (yes, Xcode is dumb)
2. Set that it runs from the Built Product directory
3. Use ```` as the first (and only) argument
4. Optionally set the ``USE_PDB`` (or any other) environment variables

Note that when debugging using gdb, you'll get a trap signal because
``/usr/bin/env`` will be ``execve``'ing your application.  Unfortunately,
there's nothing we can do from the template, because Xcode can only create
Custom Executables to absolute paths.  However, you can probably modify
yours such that it points directly to your built application after it
has been built once.

Custom executables are specific to a particular user in Xcode, so anything
you do to this part of the template won't be seen by anyone else unless
they happen to have the same short user name as you.

PyObjC Application

This is a simple template that has a window and an application delegate.

PyObjC Document Based Application

This is template demonstrates a Document-based application written in Python.
It is a simple text editor (like the TinyTinyEdit example).

PyObjC Mixed Application

This template contains both Objective-C and Python code.  The Objective-C code
is built as a "ProjectNamePlugIn.bundle" plug-in in a separate target.  The plug-in
is placed in the ``Resources`` directory of your application.  A wrapper script
in the Classes group, "" can be imported from Python and will
contain all of the Objective-C classes referenced in the plug-in (even if there
is more than just the example ``ProjectNamePlugIn`` class).

The example class implements a simple method, ``-(BOOL)plugInLoaded`` which will
always return ``YES``.  The Python application delegate creates an instances of
this class, and will beep when the application has finished launching if the
plug-in loaded correctly.  If it didn't load correctly, you would get an exception,
but that shouldn't happen :)

Note that this template doesn't have any special machinery behind it.  If you find
that you later need to add Objective-C code to a project that you started with
one of the other templates, you can do the following:

1. Create a new Objective-C loadable bundle target
2. Make the Development and Deployment targets depend on this target
3. Drag the product loadable bundle into the Resources group
4. Create a wrapper module, that uses ``objc.loadBundle(...)`` in the
   Classes group (see the example in the template).

Note that switching between Development and Deployment targets does
not imply that you are switching to the build style of the same name.
See the Targets section for more information.