Skip to topic | Skip to bottom

You are here: ProductDocumentation > MaxUBSDK > ProjectDetails
ProductDocumentation.ProjectDetails r1.2 - 12 Jun 2006 - 20:54 - DavidZicarelli topic end


Start of topic | Skip to actions

Details About Xcode Projects for Max Externals

Xcode projects contain a large collection of settings for compiling and linking. As you can imagine, with hundreds of Max externals, each with its own project, your friends at Cycling '74 have spent a lot of time messing with these settings, and our current thinking as represented by this SDK may continue to evolve as new tricks become known. If you have several externals that you develop and maintain, you'll want to ensure that the settings you use are convenient and consistent.

While important settings for developing Max externals will be explained in this section, we still recommended that you use the method of copying example external object project files in order to ensure you have all settings properly configured rather than attempting to build projects from scratch using the basic templates built into Xcode. For one thing, it turns out that it is basically impossible to turn one kind of Xcode project into another. So for example, if you choose Application as the type of Xcode project, you can't really turn the project into a library.

At some point in the future, we may have a template for a Max external that allows you to avoid having to copy a project. However, in our experience, changing a template is almost as much work as copying a project.

Projects, Targets, and Configurations

Xcode has a three-level hierarchy of settings. First, there are Projects, which are associated with Xcode documents. You can think of projects as containers for Targets, which is where most of the action lies.

Targets specify what files are compiled and linked. They also specify the kind of thing you're building. So for example, we have a Project for building Max. It contains several targets: one for the regular editing version, one for the runtime version, and one for the MaxPlugLib library version that plug-ins use. The first two are applications, while the last is a library.

Within each Target is a Build Configuration. A build configuration is a collection of settings for the compiler and linker about how a Target will be built. For example, one build configuration might turn on compiler optimizations while another would turn them off.

The example Max external object projects in the SDK have one Target, named after the object, and two Build Configurations, called Development and Deployment. Here is a summary of the differences of the two Build Configurations.

Setting Development Deployment
Architecture Native to the processor you're using Universal Binary
Debug symbols Included Stripped out
Optimization Off Full ("Os")
Destination Development folder inside build folder Deployment folder inside build folder
ZeroLink On (watch out! see below) Off

The thinking is that you will use the Development build configuration while you are in the process of developing your object. Once you want to unleash it upon the world, you will use the Deployment build configuration. The Development build configuration is designed to be:

  • faster to compile (half as much compiling vs. universal binary, which has to compile each source file twice)
  • easier to debug (optimizations make it hard to track source code in a debugger)
  • easier to diagnose crashes (debug symbols are left in so Crash Logs can point you to the source line of your crash)

Editing Build Settings

To edit the build settings, bring your object's project window (the one with the list of files in it) to the front and choose Edit Active Target 'maximum' (or whatever your object's name is) from the Project menu. The window that appears is labeled Target 'maximum' Info, but we'll refer to it as the Build Settings window.

At the top of the window are several tabs.

General Tab

At the top of the General section, you can rename your Target. This is not renaming your object, just what Xcode displays as the name of your Target. We suggest this name should be the same as your object, but it could be any name -- Target, K-Mart, even Wal-Mart.

Build Tab

The Build tab is where most of the action is. Before we get into describing each build setting, it's critical that you notice and understand the menus at the top labeled Configuration and Collection.

The Configuration menu selects the Build Configuration you'll be editing. If you want to change a setting specific to a single build configuration (which in many cases you do not) choose either Development or Deployment from this menu). If you want to change something for all build configurations in a target, choose All Configurations from the Configuration menu.

The Collection menu is a way to navigate the many, many settings listed in this window. Settings are divided into sections (and even subsections). Typically the most important settings are near the top of each collection. If you are just copying a project, you can very quickly get to the one setting you typically need to change by choosing Packaging from the Collection menu (it's in the General section). After you do this, right at the top you will see the Product Name, which should be your external object's name.

Details on Important Project Settings

We'll go through all of the settings of any importance for Max external object development. To all the settings in the order we'll be presenting them, choose All Settings from the Collection menu.

Architectures

For the Development build configuration, this is $(NATIVE_ARCH), which means compile only PowerPC code when Xcode is running on PowerPC machines and only Intel code on Intel machines.

For the Deployment build configuration, this is ppc i386, which produces a Universal Binary version of your object.

SDK Path

This should be /Developer/SDKs/MacOSX10.4u.sdk for both build configurations. If you only developing on an Intel machine, you can leave it blank, but if you want to develop for Intel on a PowerPC, /Developer/SDKs/MacOSX10.4u.sdk is required. The SDK path is a path to an entire copy of all of the headers, frameworks, and libraries found in at the root level of the hard drive. On PowerPC machines, the 10.4 Universal SDK contains various libraries with universal binary code. The same libraries at the root level of the system typically are PowerPC-only.

Note that if you enter the SDK path while editing the Target settings, you have to know the exact name of the SDK folder. However, if you use the Project Settings window, a friendly pop-up menu lets you change the SDK Path for all Targets and build configurations without needing to know the exact pathname.

Build Products Path

By default this is set to build, which means that a subdirectory of the directory containing your Xcode project file will be created with the compiled objects you are making. You probably want to leave this as is, even if you don't ultimately want your external object to end up there. See the section on Making Xcode Install Your Object below for a way to move your object out of the build folder automatically.

Per-configuration Build Products Path

By default this is set to $(BUILD_DIR)/$(CONFIGURATION). The value of BUILD_DIR is what you set above as the Build Products Path. The value of CONFIGURATION is either Development or Deployment. This means, logically enough, that build/Development will house your completed extern when using the Development build configuration and build/Deployment will house your completed extern when using the Deployment build configuration. We find it's nice to keep the two builds separate, because it's not obvious in any other way which is which.

Header Search Paths

This determines where Xcode finds files you include in your source code, such as ext.h.

We have set these relative to the project file, but you can make them absolute if you wanted to. With the SDK configuration provided, the Header Search Paths are set to ../../c74support/max-includes for the maximum object. The folder ../../c74support/msp-includes is added to the plus~ object.

If you want to add a folder and all of its subfolders, you can use the double-star notation. For example, we could have included the entire c74support folder and all of its subfolders in the Header Search paths by saying ../../c74support/**

For those not familiar with UNIX relative path specifiers, the ../../ notation means to go two directory levels up in the folder hierarchy from the folder containing the Xcode project. So for example, for maximum, one level up is the "example-externs" folder. And one level above that is the MaxMSP UB SDK folder. Contained within the MaxMSP UB SDK folder is c74support.

Framework Search Paths

In order to use the Universal SDK while placing the MaxAPI.framework and MaxAudioAPI.framework inside /Library/Frameworks at the root level, you must have the Frameworks search path set to /Library/Frameworks for all build configurations. There is also a frameworks search bug in Xcode that this setting works around.

Mach-O Type

This must be Bundle for Max external objects.

Initialization Routine

Just a remark here. The CFM runtime architecture had a provision where objects could define a routine to be called when the object was first loaded. Unfortunately the Mach-O version of this feature is ultra-lame by comparison. You cannot call into another executable without crashing, so the only real use of the initialization routine would be to initialize some global variables. Since Max external objects have a known initial entry point (main), the Mach-O initialization routine is essentially superfluous. We leave it blank, and suggest you do the same.

Prebinding

This is a strange feature of Mac OS X that was supposed to make code load faster, but has been dropped in OS 10.4. If you have this checked you'll typically get a harmless warning if compiling for OS X 10.4 only (see below). Whether you check it or not seems relatively unimportant.

ZeroLink, by contrast, is not a strange feature of the OS but a feature of Xcode that invites confusion and errors. ZeroLink avoids combining all the various code modules that make up your object to save time linking. As a result, your supposedly compiled object, if created with ZeroLink enabled, may be much smaller than it really is. The rest of the code is sitting in various .o files in your project's build folder!

Naturally, if you try to move an object created using ZeroLink to another machine, it will not load, because some of the code was left behind. Worse, there are certain cases (we haven't quite figured out what they are), where entering this "extra" code will crash, because undefined function link errors are sometimes masked by ZeroLink.

Curiously, ZeroLink doesn't really seem to save much time over genuine linking. However, we've left it on for the Development build configuration, assuming that you would only release your object into the world using the Deployment build configuration. If we've managed to scare you into turning off ZeroLink for Development build configurations, you can do it globally by unchecking Allow ZeroLink from the Build menu.

You will always want to do this for Max external objects.

(Skipping a bunch of linker settings that don't apply.)

Product Name

This should be the name of your external object, without the .mxo extension.

(Avoid the use of Executable Prefix and Executable Extension.)

Wrapper Extension

This should be mxo (without the preceding period)

Force Package Info Generation

This should be checked in order to generate a PkgInfo file that avoids a conflict with the SubEthaEdit word processing application. If SubEthaEdit is installed and your external object does not contain a PkgInfo file in the Contents folder, Max will not see your .mxo bundle as an object and will not be able to load it.

Info.plist File

We use the name Info.plist for our Info.plist file. Typically an external object should have its Info.plist file stored in the same folder as the Xcode project, and the lack of a pathname in front of Info.plist here indicates that location.

Mac OS X Deployment Target

This sets the minimum system version required for your code to execute. The Compiler Default is perfectly adequate in our opinion. If the system supports the functions you're trying to use, your code will load. If it doesn't, it won't. This is probably what you want in most cases. However, there may be cases where a particular operating system feature you want to use actually works in a later version of the system. In this case you may want to require a specific version. Consider that it might be friendliest of all to the user to post a message to the Max window explaining why your object doesn't work on an older system.

Deployment Location, Installation Build Products Location, and Installation Directory

This setting, when checked, installs your object into a special location you specify using a combination of the Installation Build Products Location and the Installation Directory settings. This scheme is discussed below under Making Xcode Install Your Object.

Strip Linked Product

If checked, symbols are removed from the object code, making it quite a bit smaller.

Compile Sources As

By default this is set to According to File Type, which means that the C++ compiler will not be used if the source file ends in .c. If for some reason you really want to use the C++ compiler, feel free to set this to C++. However, if you do this you will need to declare a prototype for your main() function as follows:

extern "C" int main(void);

You also need to declare main() as returning an int, and have it return 0.

Prefix Header

For the SDK examples, the prefix header references the file max_sdk_macho_prefix.pch located in the max-includes folder. Specified relative to the project, the prefix header is ../../c74support/max-includes/max_sdk_macho_prefix.pch.

In order to compile Max external objects, the prefix header should contain

#include <Carbon/Carbon.h>
This includes most Apple header files you will need. Note that any references to Apple header files in your source code of the following form:
#include "Dialogs.h"
will generate an error in the compiler, and you should, at the very least, put
#if !TARGET_RT_MAC_MACHO
around them.

In the section Using Framework Headers below, we discuss how you can add all of the Max and MSP header files in the prefix header file.

Precompile Prefix Header

This should be checked -- it may speed up the compiler a fair amount, especially if all your projects share the same precompiled header and you compile a bunch of them at once.

Optimization Level

For the Development build configuration, this is set to None. For the Deployment build configuration, this is set to Fastest, Smallest (Os). Optimization is harder to debug and can, in certain cases, introduce introduce crashes where non-optimized code worked properly. In many cases, the problem is the programmer's fault, but it's useful to understand that it's not automatically a compiler bug when your optimized version crashes and the non-optimized version doesn't.

Next: More About Frameworks

Return to the Max/MSP Universal Binary SDK Table of Contents

-- DavidZicarelli - 05 Apr 2006
to top

-->

You are here: ProductDocumentation > MaxUBSDK > ProjectDetails

to top

Copyright © 2007 Cycling '74. All Rights Reserved.

...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT...WEBCOPYRIGHT... porn free porn