Chapter 17. Building Projects

WHAT'S IN THIS CHAPTER?

  • Starting and stopping builds

  • Selecting a build target and settings

  • Navigating build transcripts, warnings, and errors

  • Understanding build settings and build configurations

  • Editing build settings

  • Distributing builds to a workgroup

Building projects is Xcode's ultimate ambition. It might not be yours — you probably want your finished application to run flawlessly and be wildly popular. While Xcode does provide additional tools for debugging and performance analysis that are covered in subsequent chapters — sorry, it can't do much about your application's popularity — its central purpose is to faithfully compile and assemble your finished application.

This chapter explains how to choose what you want built and how to start, stop, and customize the build process. This chapter also explains build settings and build configurations, which are used to customize everything from compiler options to packaging, so your products come out just the way you want them to.

Starting a build is relatively simple, and is described first. After that, the chapter covers targets selection, the build window preferences, and build locations. Builds often don't go flawlessly, so the next sections describe how to dig into the details of your build transcript and navigate any warnings or errors.

The bulk of this chapter explores the build settings: a multi-dimensional hierarchy of named values that control everything from the name of your application to what compiler errors are important. Knowing how to organize, find, edit, and customize your build settings is critical to using Xcode effectively. This is followed by a section describing some of the more important build settings.

Finally, I describe how to distribute your builds to a network of other Xcode users for improved productivity.

STARTING AND STOPPING A BUILD

To build your project, choose one of the Build commands:

  • Build

    STARTING AND STOPPING A BUILD
  • Build

    STARTING AND STOPPING A BUILD
  • Build

    STARTING AND STOPPING A BUILD
  • Build

    STARTING AND STOPPING A BUILD
  • Build

    STARTING AND STOPPING A BUILD
  • Or from Interface Builder, File

    STARTING AND STOPPING A BUILD

The Build

STARTING AND STOPPING A BUILD

The Build

STARTING AND STOPPING A BUILD

These same commands can be invoked from toolbar buttons, as shown in Figure 17-1, if you find that more convenient. Xcode provides three build buttons for toolbars: Build, Build and Run/Debug, and the Build (menu). The Build and the Build and Run/Debug buttons are the same as the Build

STARTING AND STOPPING A BUILD
FIGURE 17-1

Figure 17-1. FIGURE 17-1

The Build button with the drop-down triangles is a combination of a Build button and a drop-down menu of build and clean commands. The clean commands are described later in the "Clean Builds" section. Click it quickly to execute the Build command. Click and hold to select one of the other commands. This toolbar button is useful if you want to keep Build, Clean, and Clean All buttons in your toolbar, but are short on toolbar space.

The progress and results of the build are displayed in the build window for the project. The build window is covered in detail in the "The Build Window" section. The progress of a build also appears in the Activity Viewer window, and in the status bar — at the bottom of many Xcode windows. The status bar shows a one-line summary of the build's progress, as shown in Figure 17-2. At the right end of the bar is a small round progress indicator with Xcode's estimate of how much of the build has been completed.

FIGURE 17-2

Figure 17-2. FIGURE 17-2

When the build is finished, a completion statement replaces the progress message. If the build is successful, the message "Build succeeded" is displayed. If not, the message indicates that the build failed, possibly with an explanation of why. It may also include a count of the number of errors or warnings that were encountered.

Note

On systems with multiple processors, multi-core processors, or in a distributed build workgroup, Xcode will attempt to perform build tasks within a single target in parallel. By default, Xcode completes all of the phases in a target before building the next target. If you have many relatively independent targets, consider enabling the Build Independent Targets In Parallel option found in the General tab of the project's Info window (see Figure 17-13). Xcode will then build dependent targets in parallel, whenever possible.

You can build only one target in a project at a time, but you can start a build in multiple projects simultaneously.

Selecting the Active Target and Build Configuration

All of the previously described build commands begin a build based on what's "active" at that time. These five items define what the "active" target of the build is:

  • The current project

  • The active target

  • The active build configuration

  • The active architecture

  • The active SDK

The current project is implied.

The active target is set using the Project

Selecting the Active Target and Build Configuration

Note

Changing the active target may also change the active executable. The active executable is the executable product that will be launched by any of the Run, Debug, or Analyze commands. See Chapter 18 for more about executables.

The active build configuration is set using the Project

Selecting the Active Target and Build Configuration

The active architecture and SDK can be set using the Project

Selecting the Active Target and Build Configuration

The active SDK settings have an explicit Use Base SDK setting, which defers to the Base SDK setting in your active build configuration. If you've selected a specific SDK in your build settings, the menu will let you choose a newer, but not an older, SDK with which to build.

In projects with multiple products, build configurations, and deployments, switching between different targets, build configurations, and architectures becomes a common activity. Xcode provides an entire family of toolbar controls to make those tasks easier, and to make the currently active settings readily visible. The toolbar in Figure 17-3 show all of the individual toolbar controls for build settings.

FIGURE 17-3

Figure 17-3. FIGURE 17-3

From left to right in Figure 17-3, the toolbar controls display and let you set the active target, executable, build configuration, architecture, and SDK. As you can see, this consumes a fair amount of toolbar space, so either remove the toolbar controls you don't change often (ever), or consider the more compact Overview control, shown in Figure 17-4.

FIGURE 17-4

Figure 17-4. FIGURE 17-4

The Overview toolbar control displays a compact summary of the current SDK, build configuration, target, executable, and architecture. Its drop-down menu lets you individually change any of those settings. How many settings are displayed in the Overview control depend on what other individual build setting controls — that is, those shown in Figure 17-3 — you've added to your toolbar. It always shows the active SDK, build configuration, and architecture settings but might not include the active target or executable if you also have individual target and executable controls in the same toolbar.

Controlling the Build of Individual Items

Xcode is constantly reevaluating what items need to be built. It does this in the background whenever changes are made to your project or to any of its source files — it doesn't wait until you start a build to decide. Whenever Xcode has decided that a source file needs to be rebuilt, it sets the item's build flag and marks it in the build (hammer) column of the details pane, as shown in Figure 17-5.

FIGURE 17-5

Figure 17-5. FIGURE 17-5

A check mark in the build column indicates that the source file will be built in the next build. You can manually uncheck that item, which tells Xcode to ignore the changes and treat the file as if it were up to date. Conversely, checking an unchecked item tells Xcode to rebuild it anyway. The Build

FIGURE 17-5

You can use this ability as a more exacting alternative to a clean build, described later. By checking a source file's build flag, you can force it to be rebuilt, even when Xcode is convinced that it doesn't need to be. The new state of the build flag persists only until Xcode decides to reevaluate the condition of the file. For example, clearing the build flag for a file and then modifying it causes Xcode to, once again, mark the file to be built.

Building an Inactive Target

Although the build commands in the main menu and toolbar always apply to the active target, there is a shortcut for immediately building any of the other targets in your project. Control/Right+click a target in the target's smart group. In the contextual pop-up menu for the target you will find Build, Build and Start, Build and Debug, and Clean build commands. Selecting any of these is equivalent to making that target active, starting a build, and then switching back to the previously active target.

CLEAN BUILDS

A "clean" build is a build that constructs everything in the product solely from the project's source files. You might think this would be true of every build, but it isn't. Xcode, like most Make systems, keeps all of the intermediate files that were produced during previous builds. It reuses these intermediate files to reduce the work required for subsequent builds: a C source file is compiled into an object file, which is later linked to form an executable. The C file is the source and the executable is the product, but the object file is an intermediate file. Xcode normally only recompiles the source file when its modification date is later than the intermediate object file. Likewise, the executable is only re-linked if one or more of the intermediate objects are newer than the latest executable.

Xcode does this to avoid recompiling everything in the project and all of its libraries and frameworks every time you make a single change. For large projects the difference can be a 20-minute build versus a 5-second build. However, it's possible for Xcode to become confused. The classic example is to build a project and then to replace a source file with an earlier version. The source file is different and needs to be recompiled, but its modification date is still earlier than the intermediate object file. Xcode does not recompile the file and much consternation ensues. Other actions, such as deleting or renaming components in a project, can also leave obsolete intermediate files behind.

Some build systems have a "build clean" option that simply ignores the state of intermediate files and recompiles everything. In Xcode, this is a two-step process using the Clean (Command+Shift+K) command or Clean All Targets command followed by a new build. These two commands delete the product and all intermediate files generated by that target. The next time a build is executed, everything in the target will need to be rebuilt. The Clean command only applies to the active target. The Clean All Targets command cleans out all targets in the project. Both present the dialog box shown in Figure 17-6.

FIGURE 17-6

Figure 17-6. FIGURE 17-6

Remember that the product will also be deleted, so you probably don't want to clean a target while your application is still running.

If you check the option Also Remove Precompiled Headers, the precompiled headers for the target are also deleted. Precompiling the system headers is a lot of work, so saving the precompiled headers will save a fair amount of time on the next build. Because the precompiled headers for most projects consist of just the headers from the system frameworks, they are also unlikely to have changed or be out of synchronization. On the other hand, it is also possible to include your own headers and symbols in your precompiled headers and, though rare, system frameworks do change from time to time. In any case, clearing the headers is the safest choice.

The other option is Also Clean Dependencies. If checked, any targets the active target depends on are also cleaned.

Warning

It's worth noting that running the Clean command is not equivalent to deleting the contents of your build folder, and is one reason that Xcode provides a command to do this. There are two potential pitfalls to avoid here: the Clean command might not erase all intermediate items, and deleting the build folder might have unintended consequences. The build folder is also the repository for other project support files, possibly files from other projects. The support files are used to provide auto-completion, data modeling, predictive compilation, and other intelligent features of Xcode. Problems can arise if you impulsively delete these support files while Xcode is running. Conversely, if you issue a Clean command after removing a target the products of the target you deleted won't be removed, because they are no longer part of the project.

If you want to ensure that everything in your project is clean, and do so in a way that won't confound Xcode, follow these steps:

  1. Close the project.

  2. Trash the project's build folder.

  3. Re-open and build the project.

Xcode automatically re-creates the build folder, along with whatever support files it needs. The build folder is normally the folder named "build" inside the project folder — unless you've relocated it. The "Build Locations" section explains how to change or identify a project's build location.

PARTIAL BUILDS

There are a few commands for compiling a single file without committing a full build. These commands are:

  • Build

    PARTIAL BUILDS
  • Build

    PARTIAL BUILDS
  • Build

    PARTIAL BUILDS

Each is enabled whenever you are editing, or have selected, a program source file that belongs to the project. Selecting one of these commands compiles the file using the current, or only, target that compiles that file.

The Compile and Preprocess commands are quick ways of checking that this source file compiles, without waiting for any other files or dependent targets to be built. The Preprocess command only runs the file though the compiler looking for errors. It does not replace the object code last compiled for the file, nor does it perform any other build-related steps.

The Show Assembly Code command is a little different. It compiles the source file using flags that cause the compiler to output assembly source code for the file instead of a compiled object file. This can be instructive if you need to examine the actual machine code produced by the compiler. The assembly source file exists in the build directory and will be overwritten by the next Show Assembly

Code command or the next time a clean build is run. If you want to compare the assembly code differences between two versions of your source code, you'll have to save or copy the first one before producing another.

Xcode also includes a feature called Predictive Compilation. You turn this on in the Build tab of the Xcode preferences, explained a little later in this chapter. When this feature is enabled, Xcode quietly compiles sources files that you have, or are still, editing in the background. It does this to optimize the build process by trying to compile as many source files as it can before you request a build. Unless you've just made sweeping changes to a project, it's likely that most of your source files will already be compiled before the build begins.

While Xcode is precompiling your source files, it saves the precompiled object files in a temporary cache. Predictive compilation never overwrites any of the intermediate object files in your build folder until you start a build. When you do finally begin the build, Xcode makes one last check to see whether each precompiled object file is still up to date. If it is, Xcode quickly replaces the intermediate object file in the build folder with the one it precompiled — skipping the need to compile the source file again. If the precompiled object file is not up to date, it is discarded and the build proceeds normally.

THE BUILD WINDOW

The build window is your central control for builds, as shown in Figure 17-7. Choose Build

THE BUILD WINDOW
FIGURE 17-7

Figure 17-7. FIGURE 17-7

The build window's toolbar can contain a number of build-related buttons and controls. The more useful are the controls to display and change the active target and build configuration (described earlier), the various Build buttons, and the Clean and Clean All buttons. Note that the Build button turns into a Stop Build button whenever a build is in progress.

The build window is divided into two panes. The upper pane displays progress messages and the build transcript. The lower pane is an editor pane that will automatically focus on the source file associated with the selected issue in the transcript.

The items in the transcript pane can be filtered and organized in different ways using the controls in the ribbon at the top of the pane. The three groups of controls are as follows:

  • Choosing All Results shows the results of all recent builds for this project. Switching to Latest Results hides the results of previous builds.

  • Choosing By Step or By Issue either groups together the issue, warning, and error messages produced in the step that produced them, or by the type of issue. See the section "Message Groups" for more details.

  • The Messages control is a drop-down menu that lets you filter the items it the build transcript so that it shows:

    • All build steps and messages

    • Only issues — essentially any message other than completed build steps

    • Only error and warning messages

    • Only error messages

    • Only static analyzer messages

Build Transcript Items

The build transcript is a structured view of the build log produced by the Xcode tools. It takes the (often voluminous) text output the by the various compilers, tools, and scripts; digests it; compacts it; and presents it as an intelligent, organized summary of the results. Xcode displays five types of messages in the build transcript window:

  • Progress Messages

  • Message Groups

  • Build Steps

  • Issue, Warning, and Error Statements

  • Build Summary

Progress messages are transient messages displayed only while a build step (compile, link, copy, and so on) is in progress. Once that step in complete, the progress message is replaced by a completed build step or it simply disappears. Progress messages appear as grey text and let you follow the activity of your build in detail. The CompileXIB statement in Figure 17-8 is a progress message.

FIGURE 17-8

Figure 17-8. FIGURE 17-8

The persistent items that appear in your build transcript are the results of the build. These are described in the following sections, and are shown in Figure 17-7 and Figure 17-8.

A build step appears for each completed step in the build, distinguished by a green check mark. If the step is associated with a specific source file, selecting the step displays that file in the editor pane.

Message Groups

Anytime a build transcript item encompasses one or more submessages, it becomes a message group. Use the disclosure triangle to expand or to collapse the group.

The build results of each target are contained within a group for that target. Collapse the target group if you want to hide (or ignore) the build results for that target.

The Choosing By Step or By Issue switch above the build transcript determines whether build issues (warnings, errors, and similar notices) are grouped by step or by type:

  • By Step groups build issues together in the step where they occurred. If a single source file produced an error and two warnings, those three issues are grouped in the single Compile step that built that file.

  • By Type groups build issues together by type. If three different source files each contained a call to a deprecated method, all three messages are grouped together under a single "is deprecated" group.

Issue, Warning, and Error Statements

The items of most interest in the build transcript are the issues. These are the warnings, errors, and other informational messages that tell you what is, or could be, wrong with your project.

Issues are decorated with an icon indicating their type and severity. You can selectively filter out lesser issues, using the Messages control above the pane, so that the transcript only shows you the more severe problems. There are programmers who routinely ignore compiler warnings; they might set the filter to display Errors Only, hiding all warnings and other informational messages. I trust that you're not one of those programmers, but we know they're out there.

Build Summary

At the end of each build Xcode inserts a build summary. It's a tall — approximately three lines high — message summarizing the success, or failure, of the build and the time it was started. The build summary conveniently delineates between the results of multiple builds.

Transcript Item Text

As mentioned early, the build results that you see in the build window isn't the actual output of the build. It's an interpreted version, with the important bits highlighted and the minutia hidden.

Sometimes, however, the details of what went wrong are buried in that minutia. When this happens, you'll want to examine the raw output of the build process. There are three techniques for digging into the details of the build transcript.

See the Entire Message

Sometimes the build message is too long to fit on a single line, or is abbreviated for clarity. In either case, hovering the cursor over the text of the message shows the complete message in a tooltip.

Issues that are too long for a single line may also have a "more" link at the right edge of the window, as was shown in Figure 17-7. Clicking this link expands the message into multiple lines so you can read the entire message. A "less" link appears in the expanded message, which will return it to its compact state.

Reveal the Source Build Output

To the right of some messages is a reveal transcript button, as shown in Figure 17-9. Clicking it reveals the source build output that the message, or messages, were constructed from.

FIGURE 17-9

Figure 17-9. FIGURE 17-9

Right/Control+clicking any message in the build transcript reveals two commands: Expand All Transcripts and Collapse All Transcripts. These commands reveal, or hide, the transcripts for every message in the window.

Extract Some or All of the Build Log

Right/Control+click any message in the build transcript and choose either the Copy or the Open These Latest Results as Transcript Text file command. The Copy command copies the raw build log output associated with the selected message to the clipboard.

The Open These Latest Results as Transcript Text file command — possibly a nominee for the longest command name — exports the entire log from the latest build to a new editor window, where you can sift through it for clues. This is particularly useful when looking for problems that don't produce build transcript messages.

Navigating Errors and Warnings

Having a concise summary of the problems in your project is only half the battle. You have to get to the source of the problems and fix them. Xcode provides a number of navigation shortcuts for quickly getting to the root of your build issues.

Build Window Editor Pane

The build window editor pane is probably the simplest and quickest way to fix small problems. Select any single message in the build transcript; the associated source file (if it has one) is immediately displayed in the editing pane, with the suspect text selected. Use the editor to fix the problem and move on.

Note

The View

Build Window Editor Pane

Jumping to the Source

Double-click any build issue and Xcode jumps right to the location in the source file that generated the problem. You will be transported to either the project window or a separate text editing window, depending on your layout preferences.

Issues from the build are used to annotate your source code, so it's easy to see the location of the issue, a description of the problem, and any other issues in the same file. The section "Message Bubbles" describes this in more detail.

Jumping to the Next Warning or Error

If your build resulted in a large number of errors, you have my condolences. You also have a couple of commands that will quickly navigate to the next error or warning:

  • Build

    Jumping to the Next Warning or Error
  • Build

    Jumping to the Next Warning or Error

These two commands jump immediately to the next warning or error in the build transcript. If the build window is active, it jumps to next issue in the list and reveals it in the editor pane of the build window. If you are currently in a separate editing window, the commands skip to the next issue in that file, or opens the next file with a problem.

Message Bubbles

Though message bubbles were mentioned briefly in Chapter 6, this is where they become useful — or annoying, depending on the circumstances. Each build issue that's associated with a particular location in a source file appears as a message bubble at that location. A build issue indicator appears in the gutter, and a message bubble describing the issue appears to the right of, or below, the suspect text, as shown in Figure 17-10.

FIGURE 17-10

Figure 17-10. FIGURE 17-10

While having the description of the problem appear right where the problem lies is exceptionally handy, the message bubbles can get in the way of serious editing — particularly when several errors occur on a single line. There are a number of ways to hide, and later reveal, them if they become a hindrance:

  • Click on the issue's icon in the gutter

  • View

    FIGURE 17-10
  • View

    FIGURE 17-10
  • View

    FIGURE 17-10
  • View

    FIGURE 17-10
  • View

    FIGURE 17-10

Clicking an issue's icon in the gutter toggles the display of that single message bubble. The remaining commands selectively hide or reveal all of the message bubbles, or message bubbles of a particular class. The command settings change the message bubbles display for all windows and are remembered between builds.

Note

All of the commands in the View

FIGURE 17-10

BUILD PREFERENCES

The Build tab in the Xcode Preferences, as shown in Figure 17-11, is where you'll find a number of global build preferences.

FIGURE 17-11

Figure 17-11. FIGURE 17-11

Establishing Common Build Locations

The Place Build Products In and Place Intermediate Build Files In options define the default build locations projects. If you have special build locations that should be used for all projects, set them here. Otherwise, leave them set to Project Directory and With Build Products. The meanings of these locations are described in the "Build Locations" section, later in this chapter.

Automating Build Window Behavior

The Build Results Window options let you choose when the build window for the project is automatically opened and closed. The choices for automatically opening the build window are:

  • Always

  • Never

  • On Errors

  • On Issues

The Always and Never choice will, or will not, automatically open the project's build window whenever a build is started, respectively. The other two choices open the build window only when the build concludes with one or more errors or issues, respectively.

There is also a set of choices for automatically closing the build window at the conclusion of a build. These choices are:

  • Never

  • Always

  • On Success

  • On No Errors

  • On No Issues

The Never choice leaves the build window alone. The remaining choices will automatically close the build window at the end of every build, only if the build is successful, only if there are no errors, or only if there are no issues, respectively.

If you like to follow and interact with the build process in the build window, I suggest settings the open option to Always and the close option to either On Success or On No Issues. This will open the build window at the beginning of the build and close it automatically if successful, or leave it open if there were problems.

If you want to let your builds run quietly in the background, set the open option to On Issues and the close option to Never. With this configuration, the build will run quietly until it completes or encounters a problem. If issues arise, the build window will automatically open to show them to you.

Other Global Build Options

The Continue Building After Errors option permits phases like Compile Sources to continue compiling source files even after one has failed. It's usually more efficient to concentrate on fixing the errors of just one file at a time, so stopping the build as soon as a compilation fails makes sense. However, there are rare occasions when an error in a second file is the root cause of the error in the first, in which case you'll want Xcode to show them all. Or maybe you simply prefer to fix as many errors as you possibly can before building again. For any of these cases, turn this option on. This is a global setting that affects all projects.

The Use Predictive Compilation option enables anticipatory compilation of source files while you are editing them, which was explained in the "Partial Builds" section earlier in this chapter.

Handling Unsaved Files

The For Unsaved Files option, on the right, controls the automatic saving of source files in the project before a build begins. You have four choices:

  • Ask Before Building presents a standard Save All dialog if there are any unsaved source files. (See Chapter 6 for information about the Save All dialog window.)

  • Always Save automatically saves all open source files without asking.

  • Never Save builds the project without regard to unsaved changes in source files.

  • Cancel Build simply blocks the build from starting if there are files with unsaved changes.

If you choose Cancel Build, there's almost no indication that the build was canceled — besides the obvious fact that it didn't start. I recommend using either the Ask Before Building or Always Save; the Never Save choice is a very hazardous one, and will inevitably result in your making a change to a file and then building your product without that change. This can be immensely frustrating during development.

Warning

The automatic save options only save files belonging to the active project. This is a concern if your project contains cross-project target dependencies. If you have other projects open and have modified files in those projects, starting a build in your active project will not save the files belonging to those other projects. If you are using multiple projects with cross-project dependencies, you should cultivate the habit of manually saving all of your files before beginning a build.

BUILD LOCATIONS

When you start a build, Xcode (hopefully) begins producing a lot of files. The build locations determine where those files get written. There are two build locations. The product location is where the final products of a target are written. The intermediate files location is where all of the derived and intermediate files, like individual object files, are saved between builds.

Wherever the build location is, it has the same structure. Within the product location folder, Xcode creates one product folder for each build configuration. Build configurations are discussed later in this chapter, but you should know that build configurations can produce variations of a single product. Xcode keeps each variant separate by creating a folder for each, as shown in Figure 17-12. In this example, there are two versions of the Brick House application: one built using the Debug build configuration and a second using the Release configuration.

Within the intermediate files location, Xcode creates a single .build folder for each project. Within that folder are individual subfolders for each build configuration. Again, these are used to separate the intermediate files produced by a single target built with different build configurations. This location is also used by the project to store its project and symbol index files.

FIGURE 17-12

Figure 17-12. FIGURE 17-12

The product and intermediate files location can be the same location or different locations. As was shown in Figure 17-9, both the product and intermediate files locations are the same, so all of the build subfolders coexist in one place.

The default for a new installation of Xcode is to use a build folder within each project's folder as the location for both products and intermediate files. Technically, the build location is set to $(SRCROOT)/build (SRCROOT is a build variable set to the path of your project's folder). This is a foolproof setting and works fine for all independent projects of any size or complexity. You many never have to change this setting.

Warning

The various build locations and intermediate directory structures are actually controlled by a group of build settings. As you'll see later in this chapter, you have a great deal of control over build settings and can customize many of the standard build location paths. However, I suggest that you don't attempt to do that; changing build paths can have many unexpected consequences. Set the build location using the settings provided in the General tab of the project's Info window, and let Xcode define the rest of its build locations relative to those.

There are, however, some very good reasons why you might need to alter these locations. The most obvious is to resolve cross-project product references. All product references in Xcode are relative to the product location. Within a single project this will never fail, because all of the targets in a project share a single build location — another reason for why single-project projects are easier to maintain. Two projects that have separate build locations, however, cannot refer to each other's products because their build locations will be different.

Say you have two projects. Project A builds a static library that Project B needs to link to. In the target of the Project B you create a dependency on Project A (to make sure it's up to date before linking), and then add the product of Project A to the link phase of Project B. With the default Xcode build locations, the link phase fails with a "library not found" error. Why? Because Xcode is expecting the library to be in the products location of Project B, along with the rest of the products, but it isn't. It's in the products location of Project A where it was produced.

This problem extends beyond Xcode. An application that loads plug-ins may be expecting those plug-ins to be in the same folder as the application. If the plug-ins are produced by a different project, they could be somewhere else when you test your application. Or maybe your project files are on a (relatively) slow network volume and you'd like your intermediate files written to your (relatively) fast local hard drive. The point is that there are lots of reasons for relocating your build folders.

The straightforward way of fixing these and similar dilemmas is to define a common build location, so the products from all projects are written to the same location. Products produced by Project A will be accessible to Project B just as if targets in Project B had produced them.

So where do you change the build locations for a project? The first option is to change the global build locations in the Build tab of the Xcode Preferences, as previously shown in Figure 17-11. The defaults are to use the project folder for the products location and to use that same location for the intermediate files. You can specify a different location for the products folder by clicking the Customized Location radio button and then entering an absolute path to the desired location, or by clicking the Choose button and browsing to a folder.

The intermediate files location can be the same as the products location, or it can be independent. Again, select the Customized Location and choose a location. Unfortunately, you can't set a common location for the products while keeping the intermediate files location relative to the project.

The problem is that you just redefined the build locations for every project you open with this installation of Xcode. (That's not entirely true, but the caveat will have to wait a moment.) This may never be a problem, but there are some serious pitfalls to watch out for. The biggest problem is project and product name collisions. The intermediate and index files for a project are kept in a .build folder derived from the project's name. If you have two or more projects with the same name, they will all try to use the same index and intermediate build files. Just as bad is the situation of two or more projects that produce products with identical names. The product of one project will simply overwrite the product of the other project. These consequences can range from amusing to disastrous.

Alternatively, you can set the build locations for an individual project. You do this through the Info window of the project, as shown in Figure 17-13.

FIGURE 17-13

Figure 17-13. FIGURE 17-13

The choices for the Place Build Products In setting are:

  • Default Build Products Location

  • Custom Location

The default option refers to the setting in the Xcode Preferences pane you saw earlier. The custom option lets you to specify an absolute path by entering it into the field below the radio button, or by clicking the Choose button. Whenever you create a new project in Xcode, its build location is set to use the default products location. Changing the global preference changes the build location for all projects that use the default location, but it doesn't affect projects with custom locations.

Similarly, the Place Intermediate Build Files In setting has three choices:

  • Default Intermediates Location

  • Build Products Location

  • Custom Location

The default location refers to the global default, which could be the project location or a custom location. The Build Products Location is whatever location was chosen for the products — in other words, whatever location was ultimately decided on by the build products location settings. Finally, the custom choice allows you to select an arbitrary location.

Warning

Whenever you change the build locations for a project, do a little housecleaning. Close the project and delete all of the project's build folders. This saves disk space and you won't have, potentially, thousands of orphaned files cluttering up your development folder. Xcode automatically re-creates whatever build folders it needs.

Xcode conveniently uses the two custom location path fields to preview the location of your build folders. If you select anything other than Custom Location, the disabled path field will display the actual path that Xcode intends to use — calculated using the project's folder location, the project location settings, and global location settings in the Xcode Preferences.

BUILD LOCATION STRATEGIES

Although you might have other reasons, the primary reason for redefining build locations is to share a single location with two or more projects. The three basic strategies for sharing build locations between multiple projects are as follows:

  • Set the global build location to an absolute path and have all projects use the default location. This is ideal for reusing libraries and frameworks, and for sharing them between multiple projects or developers.

  • Set the global build location to use a project-relative build folder, and then override the build location specifically for the projects that need to share a build location. This is a good solution for sharing build products between a limited number of projects for a single user, without abandoning local build folders for your remaining projects.

  • Set the global build location to use a project-relative build folder and then share a single project folder. This is a handy trick for subdividing a single, self-contained, project into multiple projects while avoiding most of the build location issues inherent with the other two solutions.

The first solution is the simplest, and is probably the best choice when you're dealing with a large number of projects or developers. You'll have to decide what a "large number" is, but keep in mind that many professional software teams use a common build location to share built products. At the very least, maintenance is easier if your projects don't override the build location defined in the Xcode Preferences. Any change that needs to be made can be made in one place: the Xcode Preferences.

The second solution sets the custom build location only in those projects that need to share built products. Although this would appear to be the most concise solution, you are going to have problems sharing those projects with other developers. Project-specific custom build locations are absolute paths stored in the project document. Give that project to another developer, and the project won't build if the path to its build location doesn't exist on their system. More than likely, it won't — unless you've colluded with the other developer beforehand to ensure that it does. Using the single build location defined in the Xcode Preferences (the first strategy) works because the only information stored in each project document is a flag to use the global build location defined by the current user — a location that can be different for every developer. This is, in a fashion, similar to the philosophy of source trees described in Chapter 21 and requires only that all of the developers have a custom build location defined in their preferences.

On the other hand, defining a centralized build location for all projects prevents any project from using the project folder for its build location. After you set the Xcode Preferences to a custom build location, you lose the convenience of using the local build folder for all of your projects. If you have just a few projects that need to share built products, and you don't need to share those projects with other developers, consider setting the build location for those projects individually. The rest of your projects can continue to use their local build folder.

The third option is somewhat of a trick, but works well for small, self-contained, projects. When you place two or more projects in the same project folder, they all share the same local build folder without having to define a custom build location in Xcode or any of the projects. There's no configuration required and the projects build regardless of the current Xcode preferences.

When you're considering your options, think about why you need to break up your work into multiple projects. If the goal is to reuse libraries and frameworks or share projects with other developers, then one of the aforementioned solutions will meet your needs. However, if you are subdividing your project merely for the sake of organization, consider for a moment if you even need separate projects. You may be able to achieve the same goals using multiple targets, source groups, and build configuration files in a single project, eliminating all multi-project problems and complexities.

BUILD SETTINGS

Build settings have been mentioned numerous times, so you'll probably be glad to finally be getting around to finding out about them in detail. At the risk of sounding monotonous, build settings are a set of named values used to customize the build process.

So what are build settings used for? Build settings are used by targets to determine what and how to construct their product, by the compile phases to control various compiler options, and by Xcode itself to control where files are written. Build settings are passed to compile scripts and external build processes, so those scripts and tools can make decisions and alter their behavior based on those settings. You can define your own settings, passing those values to the compiler and your own custom build scripts. A better question might be "what are build settings not used for?"

Later sections enumerate some of the more important build settings and describe what they do. For now, all you need to know is that build variables are named values, usually written as SETTING_NAME = value — although it's unusual to actually write build settings yourself. To understand the interface for build settings, you need to understand how build settings are related to other build settings and how build configurations group them. The two key concepts to understand are:

  • Build settings are a hierarchy of named values collections

  • Build configurations are distinct sets of build settings

As you work through the next few sections, keep these core concepts in mind. Build settings and configurations are notorious for confounding new Xcode users. If you grasp these basic relationships, you'll be using them like a pro in no time.

Build settings form a layered hierarchy. Each layer has its own collection of build settings. A value in a higher layer overrides the value with the same name in lower layers. The layers, from top to bottom, are Command Line, Target, Target Configuration File, Project, Project Configuration File, Xcode Default, and Environment. Figure 17-14 shows the layers and their order.

FIGURE 17-14

Figure 17-14. FIGURE 17-14

The top layer is formed by the command-line parameters passed to the xcodebuild tool. This is significant only if you are building Xcode projects from the command line. When you're building from within the Xcode application, this layer does not exist and can be ignored. "The xcodebuild Tool" section, later in this chapter, explains how to override build settings using the command line.

The next layer is the build settings for the current target. Most targets have a set of build settings. Aggregate targets do not have any configurable build settings — it is assumed that an aggregate target doesn't actually build anything.

Every target with build settings can also inherit a set of build settings from an Xcode configuration file. An Xcode configuration file is just another set of build settings stored in a source file. Creating and adding configuration files to your project is covered a little later in the "Configuration Settings Files" section. If a target is based on a configuration file, the settings in that file form the next layer in the hierarchy. If the target is not based on a configuration file, this layer is ignored. Multiple targets can be based on the same configuration file.

The next layer is the project layer. The project build settings are set in the project's Info window. As the name implies, there is only one set of project build settings. Like a target, the project itself can be based on an Xcode configuration file. If used, this configuration file forms another layer below the project build settings.

Below the project layer is a fixed set of build settings provided by Xcode itself. These are the default values for all projects, and comprises most of what you see when you go to edit build settings. This layer also includes the build settings that Xcode generates dynamically, like the SRCROOT setting that contains the path of the project. At last count, there were more than 200 default build settings.

Finally, the bottom layer is the environment layer. These are values found in Xcode's or xcodebuild's process environment. You can set these in the shell or as explained later in the "Environment Settings" section. Environment variables are a way of passing build settings to many or all projects.

For the most part, the important layers — that is, the layers you will be working with on a daily basis — are the target and project layers. The remaining discussion often glosses over the other layers; just remember that if those layers are present, they behave just like any other layer.

The Scope of Build Settings

Each set of build settings has a scope, or lifetime, as described in the following table. Build settings that are out of scope when a particular target is being built are inaccessible and irrelevant.

BUILD SETTING LAYER

SCOPE

Command-Line

Present for the duration of the build started using the xcodebuild tool.

Target and Target Configuration File

Present during the build phases of the target.

Project and Project Configuration File

Present while building any target in the project.

Xcode Defaults and Environment

Always present.

Any build settings established using the command-line arguments passed to the xcodebuild tool exist for the duration of the build. This may span the building of many targets.

The build settings for a target only exist while files in that target are being processed. If dependencies cause another target to be built, the build settings used for the dependent target are the build settings belonging to that dependent target. Targets do not inherit, or in any way pass, their build settings to the build phases of other targets.

The project build settings exist whenever a target in that project is being built. If a dependency causes a cross-project target to be built, that target will be built using the project build setting belonging to the external project. Projects do not inherit or pass build settings to other projects.

Environment build settings are constant throughout a build. The environment settings used during a build are those that existed when Xcode or the xcodebuild tool was launched. When those build settings get created and their values are beyond Xcode's control.

Note

Build settings are passed to custom scripts and tools via the environment. Scripts and external build tools are free to alter any of the build settings that Xcode passes to them. However, changing them does not alter the build settings in the project. This is consistent with the UNIX model of shell variables: altering a variable in a sub-shell does not alter that value in its super-shell. External build tools can pass custom or modified build settings to other builds using the command-line and environment layers.

Build Setting Evaluation

Every named build setting used by a target, script, or tool forms, essentially, an expression that Xcode converts into a value. The rules for evaluating build setting expressions are pretty simple, and most of the time are trivial. For simple build settings — those that don't refer to other build settings — the rule is this:

  • The highest layer that contains a build setting defines its value

If more than one build setting layer contains a value with the same name, the value defined by the top layer is used. Take a look at the build settings shown in Figure 17-15 as an example.

FIGURE 17-15

Figure 17-15. FIGURE 17-15

The INSTALL_MODE_FLAG setting is used to set the access permissions of executable product files. The default value of a-w,a+rX gives all users read and execute rights to the file, which is appropriate for most applications. However, this application includes a self-installing helper tool — an executable that will be copied to another location and executed there. For security purposes, you don't want the program file in the application bundle to be executable, because it should never be launched from within the bundle. To accomplish this, the INSTALL_MODE_FLAG build setting is set to a-wX,a+r in the HelperTool target.

When the Application target is built, the four sets of build settings — Command-Line, Application Target, Project, and Environment — are assembled. Only the project layer defines an INSTALL_MODE_FLAG setting, so the value used when building the Application target is a-w,a+rX. When it comes time to build the HelperTool target, the build sets that are in scope — which this time includes the HelperTool target settings but not the Application target set — are assembled. This time, both the HelperTool target and the project define a setting named INSTALL_MODE_FLAG. The definition of INSTALL_MODE_FLAG in the target set is in a higher layer than the project, so the value from the HelperTool target is used. When it's all finished, the project produces an application that can be launched along with a BSD program file that can be read but not directly executed.

Build Setting Value Substitution

As you can see, the scope and precedence of build settings are pretty simple. That is, until build settings start referring to other build settings. This simultaneously makes build settings more powerful while significantly complicating how build settings are resolved.

The $(VAR_NAME) syntax enables a build setting to refer to any other build setting. For example, the Other C++ Flags (OTHER_CPLUSPLUSFLAGS) build setting is normally set to the value $(OTHER_CFLAGS). This build setting effectively sets the Other C++ Flags setting to match the Other C Flags setting, so that any extra compiler flags you set for C compiles will also be used when compiling C++ files. Any custom C flags, regardless of what layer they are defined in, are automatically passed to the C++ compiler as well.

Figure 17-16 illustrates the order and rules used to resolve build setting references.

FIGURE 17-16

Figure 17-16. FIGURE 17-16

This project produces three applications: Problem Grapher, Algebra Solver, and Calculus Solver. Each application includes a copyright statement. Sharp Pencils wrote Problem Grapher and Algebra Solver, and Math Whiz wrote Calculus Solver.

The project defines a COMPANY setting containing a company name and a YEARS setting defining a span of years. It also defines a COPYRIGHT_STATEMENT setting that forms a complete copyright statement using the values of the other two build settings.

When the Problem Grapher target is built, the value of the COPYRIGHT_STATEMENT setting is constructed by substituting the values of the YEARS and COMPANY settings where their references appear in the value, as illustrated in Figure 17-17. Ultimately, the value of COPYRIGHT_STATEMENT is Copyright 2003, Sharp Pencils.

FIGURE 17-17

Figure 17-17. FIGURE 17-17

When the Calculus Solver target is built, things get a little more interesting. When Xcode resolves the references to YEARS and COMPANY, it finds values set in the Calculus Solver target (which is now in scope) that override the values in the project, as shown in Figure 17-18. Using those values instead, the COPYRIGHT_STATEMENT setting now resolves to Copyright 2000-2003, Math Whiz. Notice how a value defined in a higher layer can alter a definition defined in a lower one.

FIGURE 17-18

Figure 17-18. FIGURE 17-18

Next is the Algebra Solver target. This target is interesting because the YEARS setting contains a self-referential value. That is, the value of YEARS refers to the value of the YEARS setting. Xcode resolves self-referential references by obtaining the value of the setting from a lower layer of build settings. When the COPYRIGHT_STATEMENT setting refers to the YEARS setting, Xcode finds it in the Algebra Solver target setting. When Xcode constructs the value for the YEARS setting for that target, it finds a reference to the YEARS setting. Xcode recursively searches for another definition of the YEARS setting, but ignores layers at or above the layer containing the reference, as shown in Figure 17-19. Ultimately, the $(YEARS) reference in the target's YEARS setting is replaced with the YEARS value set in the project, resulting in a value of 2003-2005.

FIGURE 17-19

Figure 17-19. FIGURE 17-19

Recursive references are particularly useful for amending Xcode build settings. For example, the OTHER_CFLAGS build setting defines additional arguments that are passed to the gcc compiler. If you defined just a set of flags in your target, it would override whatever the value of this setting might be in the project. Instead, you can define the value of this setting as $(OTHER_CFLAGS) -myflag in the target. The argument -myflag is merely appended to whatever the project or environment setting was, rather than replacing it. As described earlier, whatever your OTHER_CFLAGS ultimately resolved to would be transferred to OTHER_CPLUSPLUSFLAGS, even if the augmentation of OTHER_CFLAGS occurred in an higher layer.

Note

The special reference $ (inherited) is the same as $ (VAR), where VAR is self-referential, as in MY_ARGS=--verbose $(inherited).

If there were no lower layers that contained a YEARS setting, the reference $(YEARS) would be replaced with an empty string. In fact, any reference to an undefined or out-of-scope build setting is replaced with nothing. Referring to an undefined build setting does not cause a build error or produce any kind of warning.

References to environment variables are treated like references to any other build setting. However, references in environment variables are a special case: references in an environment variable cannot refer to any non-environment layer build setting. In this example, the COPYRIGHT_STATEMENT setting could not be defined solely as an environment setting. If it was, the $(YEARS) and $(COMPANY) references would only be substituted if there were YEAR and COMPANY settings in the environment layer as well. Any values for YEAR and COMPANY in any other layer would be ignored.

Conditional Build Settings

There's a special kind of build setting that creates an additional quasi-layer of settings: conditional build settings. A conditional build setting is keyed to some other combination of build settings. If those other build settings match a given pattern, it substitutes a different value for that setting. The general textual form for conditional build settings is:

BUILD_SETTING[condition=pattern] = value

This isn't a general-purpose mechanism. In fact, Xcode only recognizes three conditions and these conditions are only evaluated and passed to certain native build phases. The conditions that Xcode evaluates are:

  • arch (Processor Architecture)

  • sdk (Software Development Kit)

  • variant (Product Variant)

The pattern portion of the condition is the name of the architecture, sdk, or variant. The pattern can include a "*" wildcard character to match groups of possible condition values. A setting can have multiple conditionals, as in SOME_SETTING[sdk=iphonesimulator*][variant=debug] = YES.

Consider the following build setting and variant:

GCC_USE_INDIRECT_FUNCTION_CALLS = NO
GCC_USE_INDIRECT_FUNCTION_CALLS[arch=ppc*] = YES

When the target is being built for any non-PowerPC architectures (Intel, Arm, and so on) the conditional build setting doesn't match the pattern and is ignored; in these cases GCC_USE_INDIRECT_FUNCTION_CALLS evaluates to NO. Whenever the target is compiled for any PowerPC architecture (ppc, ppc64, ppc7400, ppc970, and so on) the condition matches the pattern (ppc*) and the build setting evaluates to YES.

Logically, conditional build settings create another layer, immediately above the current layer, with alternate build settings that are only in scope when their condition patterns are satisfied. You cannot refer to conditional build settings in references; they're simply alternate settings that supersede the base setting under certain circumstances.

Conditional build settings cannot be used by custom build rules or Run Script phases. Furthermore, only those build settings that apply to native compilation phases can be made conditional.

The possible values for each condition change from release to release, but the Xcode build settings editor knows what they are and will let you choose them from a menu. If you want to know what patterns are available, take a peek by creating a conditional build setting — described later in the "Create a Conditional Build Setting" section — then look at the resulting build setting statement by copying it to the clipboard.

Variable Build Settings

Variable build setting names are an alternative to conditional build settings. This works by using a build setting value as all, or part, of a build setting name. Consider the following build settings:

VALUE_FOR_COND_1 = YES
VALUE_FOR_COND_2 = NO
VALUE_FOR_COND_3 = MAYBE
MY_CONDITION = 2
MY_VALUE = $(VALUE_FOR_COND_$(MY_CONDITION))

Build setting values are evaluated recursively. The expression $(VALUE_FOR_COND_$(MY_CONDITION)) is first replaced with $(VALUE_FOR_COND_2), which then evaluates to NO. Thus, setting the MY_CONDITION setting to 2 ultimately causes MY_VALUE to be NO. Setting it to 3 would cause MY_VALUE to be MAYBE.

This isn't quite as flexible or sophisticated as using conditional build variables, but it works with all build settings. Using this technique, you can create a set of related build setting and then select one of them via the value of another setting.

BUILD CONFIGURATIONS

Build configurations are complete sets of build settings. If you imagine build settings forming a two-dimensional tree of build settings, each build configuration creates a new plane of build settings in a third dimension. Each named build configuration represents an independent collection of build settings for the project and all of its targets.

The previous example had a project for four sets of build settings: one set for the project and three sets for the targets. If that project had three build configurations — named Alpha, Beta, and Release — it would actually contain 12 complete sets of build settings, as shown in Figure 17-20.

FIGURE 17-20

Figure 17-20. FIGURE 17-20

While you are editing your project or target build settings, keep this in mind: every target and project has an independent set of build settings for each named build configuration.

Only the build settings for the active build configuration, which you choose using the Project

FIGURE 17-20

This lets you create build settings for a target or project that changes depending on which build configuration is active. If you create a new target, that target gets a set of build settings for each configuration in the project. If you create a new configuration, a new set of build settings is added to the project and every target. Think of build settings as values written on a sheet of paper. Every page is a build configuration. Add a configuration, and you create a completely new page of build settings for everything in your project. When you build, you choose which page of build settings to use.

Warning

If you have used Xcode or Project Builder in the distant past (prior to Xcode 2.1), read this section carefully. Older versions of Xcode used a system of build settings and build "styles." There was only one set of build settings for each target. Each build style could then selectively override specific build settings. Although the two systems are effectively similar, the interface and conceptual structure of build styles and build configurations are significantly different.

You might be worried at this point that a complex project with five targets and four build configurations would have an unmanageable number of build settings — at least 25 complete sets of build settings, in all. Don't worry. Xcode provides several tools for visualizing build settings as a whole, editing build settings in multiple configurations at once, and moving build settings between layers. Each of these are covered shortly.

The most common use of build configurations is to alter the compiler and linking options when producing an application for different purposes. For debugging, the application needs to be compiled with certain code optimizations turned off (code optimizations can interfere with source-level debugging) and with debug information included. Conversely, the released version of your application needs to be fully optimized, but does not need to include any debugger data — the end user doesn't need it and it significantly increases the size of the application. You may also need to produce an application that's between these two extremes for performance testing. For that, you'll want an application that is fully optimized (just like the final version), but also includes all of the information used by the debugger to identify functions and variables.

This use of build configurations is so common that these are exactly the build configurations provided by Xcode templates. All Xcode project templates include two configurations, named Debug and Release. The default values for the build configurations set the compiler and linking options to those you would typically want. In the Debug configuration, optimization is turned off, debugging symbols are enabled, as are useful debugging features like Fix and Continue. The Release configuration has just the opposite settings. Optimization and normal linking are turned on, and all of the debugging aides are disabled.

EDITING BUILD SETTINGS

Now that you understand the hierarchy of build settings and build configurations, you should now be able to make sense of the interface for editing build settings.

Select a project or target and open its Info window; the easiest way is to double-click the project or target icon. Switch to the Build tab and a list of build settings is displayed, as shown in Figure 17-21.

FIGURE 17-21

Figure 17-21. FIGURE 17-21

The name of each setting is in the Setting column and its value is listed in the Value column.

The Configurations pop-up menu selects which set of build settings you are seeing or editing. You can choose a specific build configuration, or whatever configuration is currently active.

The special All Configurations choice merges the build settings from all of your configurations into the single list. Changing a setting in this mode changes that setting in every build configuration. A setting with values that vary between configurations displays <Multiple values> for its value.

Filtering Build Settings

Build settings are organized into groups to make it easier to find the settings you're looking for. You can filter out uninteresting settings by name or value by typing something into the search field. By default, the search field will match any setting's name, title, value, definition, or description. Use the search field's menu to limit the scope of the search, if necessary. For example, type "gar" into the search field to quickly locate the Objective-C Garbage Collection settings.

The Show menu can be set to one of three choices:

  • All Settings

  • Settings Defined at This Level

  • User-Defined Settings

When All Settings is chosen, the list shows every build setting that Xcode knows about. This will be far more build settings than are set in the level (project or target) you are editing. Those actually defined at this level are displayed in bold. The settings in normal text are those inherited from lower levels, showing you all of the existing settings that you might want to redefine at this level.

To narrow your focus to just the build settings defined in this level, change the Show setting to Settings Defined at This Level. All of the inherited settings are hidden.

User-Defined Settings is the same as All Settings, but filters out all of the standard settings that Xcode knows about. The resulting display lists only custom build settings that you've defined. Again, the settings in bold are defined at this level and non-bold values are inherited from lower levels.

Viewing Names and Definitions

Every build setting has a name and an optional title. The name is the actual variable name defined in the collection, like OTHER_CFLAGS. Its title is a more human readable title supplied by Xcode, like "Other C Flags." Build settings that Xcode does not recognize are always displayed using their name, which naturally includes all user-defined settings.

You can have Xcode list build settings by name or by title. Right/Control+click any build setting — anywhere in the row, but it can't be an empty row. The pop-up menu has two commands:

  • Show Setting Names/Titles

  • Show Definitions/Values

The first command toggles the Title column between displaying the title of the setting and its name, both shown in Figure 17-22.

FIGURE 17-22

Figure 17-22. FIGURE 17-22

The second command toggles the Value column between displaying the resolved value for the setting and its actual definition, as shown in Figure 17-23.

FIGURE 17-23

Figure 17-23. FIGURE 17-23

Values are resolved using the current level and any lower (inherited) levels; build settings that refer to values in higher levels, like our YEAR example earlier, won't display the correct build time value in the Info window. This is rare, however. Most of the time, the values expressed in the Info window are exactly what they will be at build time. You can test references by editing other build setting layers and immediately see the results.

A Peek-A-Boo Build Script

When editing complex sets of interrelated build settings, it's sometimes difficult to tell what the end result will be. If you're wondering what value a particular build setting gets resolved to at build time, add a custom Run Script phase to your target, like this:

  1. In the target of interest, add a new Run Script build phase.

  2. Edit the phase's script so it's something like:

    echo 'The build settings containing TEST:'
    env | fgrep -i TEST | sort
    exit 0

When your target is built, it will run the script, dumping all of the environment variables that contain the word "test" to the build transcript, which you can examine in the build window.

This works because, before running an external script or tool, Xcode resolves every build setting that's currently in scope and converts each one into an environment variable. This environment is then passed to the child process.

If you already have a Run Script phase that's doing something, consider checking the Show Environment Variables in Build Log option of the build phase. This option dumps all of the environment variables (which includes the build settings) to the build transcript prior to running the script.

There are a million variations on these techniques. Just keep in mind that if you ever want to know exactly what a build setting's value is, dump it from a script.

Changing Build Setting Values

Editing build settings values depends somewhat on the display mode, as explained in the earlier section "Viewing Names and Definitions." When the values of settings are displayed, Xcode shows — whenever possible — an intelligent setting control. This is true for Boolean values, lists, and values that have a known set of acceptable values. All three are shown in Figure 17-24.

FIGURE 17-24

Figure 17-24. FIGURE 17-24

In Figure 17-24, the Build Active Architecture Only setting is a Boolean value that appears as a simple check box. Tick the box to set it to YES and untick it to set to NO.

Xcode recognizes that the Valid Architectures settings is a list. Double-clicking the value cell presents an editable list, as shown on the right in Figure 17-25. Add, remove, and edit members of the list in the dialog sheet. Xcode assembles the list into a single space-delimited value.

The Debug Information Format setting is known to have three valid settings, which Xcode presents as a pop-up menu, as shown on the left in Figure 17-25. Select the one you want and Xcode substitutes the correct value. Notice that the value is not the same as the description. Like build setting titles, Xcode has a known set of values for which it substitutes more easily read titles.

FIGURE 17-25

Figure 17-25. FIGURE 17-25

Under other circumstances, Xcode may simply present you with a free-form editing dialog, or let you edit the value directly in the value cell of the table. This can happen because you're displaying the definitions of the settings rather than their values, Xcode doesn't have a specialized editor for the value, you single-click a selected value rather than double-click, and so on. Either way, you're now editing the raw value, before any references have been resolved and sans any translation. Figure 17-26 shows the same three values in Figure 17-24 and Figure 17-25 being edited in their raw form.

FIGURE 17-26

Figure 17-26. FIGURE 17-26

Warning

Changing a build setting defines that build setting in the level where you edited it, even if you set it back to its inherited value. Once a build setting is defined, it remains defined at that level until you delete it (see the section "Deleting a Build Setting"). This is a problem when you change a build setting for a target, change it back to its default, and then edit the same build setting in the project build settings. You might think you are now changing that setting for all targets, but the target where the build setting is still defined won't change because its setting — with the old value — overrides the one in the project.

Finally, there's an Edit Definition At This Level command in the action pop-up menu in the lower-left corner of the Info window. It has the same effect as double-clicking a setting.

Creating a Conditional Build Setting

As mentioned earlier in the "Conditional Build Settings" section, certain build settings can be conditional. That is, they will take on different values under specific combinations of SDK and processor architecture.

To create a conditional build setting, select a build setting that's defined at this level and choose the Add Build Setting Condition command from the action menu. The variant appears underneath the existing setting, as shown in Figure 17-27.

FIGURE 17-27

Figure 17-27. FIGURE 17-27

The conditional setting is defined by two pop-up controls that let you choose the circumstances under which the conditional setting is used. Choose an SDK, processor architecture, or combination using the pop-up menus. The Xcode interface does not let you choose a variant condition, nor can you use wildcard conditions to match multiple conditions. To do that, you'll have to use a configuration settings file, described later in this chapter.

Creating a Custom Build Setting

To create a new build setting for your own purposes, simply choose the Add User-Defined Setting from the action menu at the bottom-left corner of the Info window. A new build setting is added to the table, and Xcode lets you edit its name and value, as shown on the left in Figure 17-28.

FIGURE 17-28

Figure 17-28. FIGURE 17-28

The name cannot duplicate any existing build setting, and once created you can't rename it. To rename a user-defined setting, delete the old setting and create a new one.

Build setting names must conform to the C macro naming convention and are traditionally all uppercase. If they don't, Xcode presents the warning dialog shown in Figure 17-29. Xcode will allow you to create multiple settings that differ only in case, but settings may be case-insensitive in some circumstances, so avoid doing that whenever possible.

FIGURE 17-29

Figure 17-29. FIGURE 17-29

Deleting a Build Setting

To delete a build setting, select the setting in the list and choose the Delete Definition At This Level command from the action menu, or simply press the Delete key.

Deleting a build setting does exactly what the command says: it deletes the definition of that build setting at this level. Build settings defined by Xcode or in other levels continue to exist. If you're showing all settings, the build setting will turn from a bold setting (one defined at this level) to a normal setting (one inherited from some lower level).

The only time deleting a build setting will make it totally disappear is when you're deleting the only definition of a user-defined setting. Naturally, if you have the Info window set to show only settings defined at this level it will also disappear, but the setting still exists elsewhere.

Switching Between Build Configurations

Most of what's been discussed so far about editing and creating build settings has assumed that that you only have one build configuration. A project with three build configurations means that there are three sets of build settings for each target.

As mentioned earlier, you select the build configuration you are editing using the Configuration pop-up menu at the top of the Build tab. To edit the build settings for a particular configuration, select that configuration from the list. You can also select the Active (name) item. The Info window always shows and edits whatever the active build configuration is. Changing the build configuration using Project

Switching Between Build Configurations

One of the most useful views is the All Configurations view. When you select this view, the Build tab shows a composite view of all of the settings from all configurations. It does this the same way items in a multi-item Info window are displayed. Settings with values that are different between configurations are displayed as <Multiple values>. Boolean options whose values are set with a check box show a hyphen.

You can quickly scan the list to see which settings differ between configurations. More importantly, when you are in this view, any change you make to a setting sets that value in every configuration of the target or project. This mode is extremely useful for setting project and target settings in multiple configurations simultaneously, but it also requires some care. You can easily overwrite settings that were created for a specific configuration. It is also easy to unintentionally create new build settings. In the All Configurations view, editing the value of a setting also creates that setting (with the same value) in every configuration that did not previously contain that setting. Similarly, deleting a setting in the All Configurations view deletes that setting from every configuration.

EDITING BUILD CONFIGURATIONS

You manage build configurations in the Configurations tab of the project's Info window, shown in Figure 17-30. The Edit Configuration List shows the build configurations defined in the project. You can get to this by opening the Info window for the project. You can also jump there by selecting the conveniently placed Edit Configurations item in the Configuration menu of any build settings editor.

FIGURE 17-30

Figure 17-30. FIGURE 17-30

You create a new configuration by selecting an existing configuration and clicking the Duplicate button at the bottom of the pane. Remember that a build configuration represents a complete set of build settings for every target and for the project itself — you really wouldn't want to create a completely empty set of build settings. Select the configuration that is closest to the settings you want for your new configuration, duplicate it, and then go fix the differences in the build settings of the project and each target.

To delete a build configuration, select it in the list and click the Delete button. A project must have at least one build configuration, so you can't delete them all. You can rename a build configuration using the Rename button or by double-clicking the configuration's name.

At the bottom of the pane is a default configuration selection, declared as the Command-Line Builds Use setting. Use this to select the default build configuration for the project. This setting may be significant when building cross-project targets or when you're building a project using the xcodebuild tool.

When you're building a project directly within the Xcode application, the active build configuration unambiguously determines the build configuration that will be used. However, subprojects and projects built with the xcodebuild tool are not always as definitive. When a cross-project dependency causes a target in another project to be built, Xcode tries to use the build configuration in the external project with the same name as the one it is using for the current target. What if a build configuration with that name doesn't exist in the other project? Likewise, when using the xcodebuild tool, you are not required to specify which build configuration you want to use, forcing Xcode to choose for you. In both of these situations, Xcode uses the default build configuration you've specified in your project. If the default configuration is set to "none," the default build configuration is undefined and unpredictable; fix this by choosing a configuration from the menu.

CONFIGURATION SETTINGS FILES

Target and project build settings can be based on a configuration settings file. A configuration settings file is nothing more than a specially formatted text file containing a collection of build settings. The following code demonstrates a configuration settings file that defines the same build settings used in an earlier example:

COMPANY = Sharp Pencils
YEARS = 2003
COPYRIGHT_STATEMENT = "Copyright $(YEARS), $(COMPANY)"

The format of the file is simple. Each line contains a build setting variable name, an equals sign (=), followed by the setting's value. Any amount of white space before or after the = and at the end of the line is ignored. Placing quotes around values with special characters is optional. Everything between the = and the end of the line, ignoring any leading or trailing white space, becomes the value for the setting.

The file cannot contain anything else, except blank lines and C++-style comments. There is no support for multi-line values, escaped characters, or any other syntax that you would normally associate with a property list or source file. If even a single line fails to conform to this simple format, the entire file is ignored. The encoding of a configuration file must be ASCII or UTF-8. UFT-8 allows configuration settings files to contain non-ASCII characters. You cannot localize configuration settings files.

A configuration settings file has an extension of .xcconfig and must be a source file in the project, although it should not be included in any targets. After you've added a configuration settings file to your project, you can set any target or project build settings to be based on that configuration settings file by selecting it in the Based On menu as shown in Figure 17-31.

FIGURE 17-31

Figure 17-31. FIGURE 17-31

The build settings in the configuration settings file form a layer of build settings immediately below the target or project layer you've adopted them in. The Based On option is build configuration specific, so you can use different configuration settings files for each configuration. A project or target that is based on a configuration settings file can still override any of the settings in the file by defining its own setting — exactly as it would override a setting from any lower layer of build settings.

Warning

The All Configurations view may not display a <multiple values> value for the configuration file of the target or project. Changing the Based On setting while you're in the All Configurations view dutifully sets the configuration file for all configurations to the new choice.

Adding a Configuration Settings File

Create an empty configuration settings file and add it to your project by choosing the File

Adding a Configuration Settings File

If you already have a configuration settings file that exists but hasn't been added to the project, simply add it to the project like any other source file. See Chapter 5 for a quick refresher on adding source files. Again, do not add the configuration settings file to any targets when adding it to the project. Configuration settings files are part of the build infrastructure; they are not the thing being built.

Using Configuration Settings Files

Use configuration settings files when you have a number of targets or projects that each need a uniform, or at least very similar, set of build settings. Configuration settings files are most useful when you have a large number of projects, targets, or build configurations, and maintaining common settings across all of those projects/targets/configurations becomes cumbersome.

Targets and projects can be based on a single configuration settings file. Configuration settings files cannot be linked to other configuration settings files, nested, or otherwise combined, so don't try to design a hierarchical structure of configuration settings files; it won't work. Configuration settings files are only an adjunct to the build settings layer hierarchy already defined by Xcode. Consider these best practices when creating configuration settings files:

  • Common build settings for similar product types. For example, you might want to create a configuration settings files for all your Cocoa applications.

  • Regularly used compiler or debug settings. All of your Debug build configurations in different projects could share a single MyFavoriteDebugSettings.xcconfig file.

  • Build settings that are maintained externally or that can be generated programmatically. Build settings containing things like company product codes could be generated or updated by an external process.

Keep in mind the project or target can override anything defined in the settings file on which it is based. Settings files don't have to contain exactly the values needed by all of the targets, projects, or configurations that are based on it. They only need to define the preferred values for the settings you regularly set. Think of them as your own layer of defaults, much like Xcode's default settings layer.

MOVING BUILD SETTINGS AROUND

Eventually, you'll discover that you have a build setting in a target that really needs to be in the project build settings or a build configuration file. Moving build settings around couldn't be easier, although it may not be immediately obvious as to how.

The trick is to use the clipboard. You can cut, copy, and paste build settings between build settings panes and configuration files. When Xcode copies a build setting to the clipboard, it places a textual representation of the build setting in the clipboard using the format required by configuration files. Because of this, you can copy build settings from a build settings pane and paste them into another build settings pane, a configuration settings file, or vice versa.

Pasting in a build settings pane replaces any other settings defined with the same name. Cutting a build setting is equivalent to copying the setting to the clipboard and then deleting the setting. Note that cutting an inherited setting results in a copy, because there's no setting to delete at this level. Copying a value in the All Configurations view may result in copying the value <Multiple values>, which you'll have to edit.

ENVIRONMENT SETTINGS

The environment layer of build settings must be set up outside of Xcode and they must be set before the Xcode application or xcodebuild tool are launched. Xcode uses any environment variable that conforms to the build settings naming convention. Specifically, a variable name must begin with a letter or underscore and contain only letters, numbers, or underscore characters. All letters should be uppercase.

How you set environment variables before launching the xcodebuild tool depends on the calling process. Shells such as bash and tcsh typically use some form of "export" command. For Perl, C, Java, or similar programming languages, environment variables are usually assembled into a collection that is passed to the function that launches the tool. Regardless of how it is accomplished, whatever environment values are passed to the xcodebuild tool will be accessible to the build phases of each target built.

Warning

The beginning of the "Build Settings" section stated that target and project build setting are never inherited or passed to other targets or projects. This may not always be true if your build involves shell scripts. Whenever Xcode starts an external process — a custom build script or external tool — all of the build settings for that target are resolved and passed to that process as environment variables. If that external process causes another Xcode target to be built using the xcodebuild tool, that build inherits all of the build settings as environment settings, regardless of their original scope. Thus, a setting that is defined as a target setting in one project can appear as an environment setting in a second if the second target was built by the first target using a custom build script or external build tool.

How you set environment variables for use with the Xcode application itself isn't immediately obvious. That's because you don't normally think of GUI applications of having an "environment" the way shell and BSD tools do. In fact, OS X provides a simple — albeit obscure — technique for defining whatever environment variables you want. These variables are available to all running applications. You can read more about it at http://developer.apple.com/mac/library/qa/qa2001/qa1067.html.

The magic file is named ~/.MacOSX/environment.plist. The .MacOSX folder is an invisible folder in your login account's home directory. The environment.plist file is an XML property list file containing a list of key/value pairs. Each pair defines an environment variable that gets defined when you log in. All applications you launch include these variables in their environment.

You can edit the environment.plist file using the Property List Editor application or any good text editor. However, you might prefer to use a little utility called RCEnvironment, shown in Figure 17-32, which is available free from Rubicode at http://www.rubicode.com/Software/RCEnvironment/. It's a System Preferences panel that lets you edit your environment.plist file very much like you would edit build settings in Xcode. Remember that changes only take effect when you log in. After making changes, remember to save the file, log out, and then log back in again.

FIGURE 17-32

Figure 17-32. FIGURE 17-32

CUSTOMIZING THE BUILD

Using build settings, and a few specialized Xcode settings, it's possible to customize hundreds of details about your build.

There are literally hundreds of build settings — and the number grows with each release of Xcode. Finding the build setting you're looking for can sometimes be a challenge. The build settings tab displays a description of the selected build setting, and is the first place to look when you're hunting for a build setting or wondering what a build setting does. You can also set the search field to search the descriptions of build settings, which might also help you find what you're looking for.

The next few sections cover many common ways of customizing your build process and products. A few are special features of the Xcode application, but most are configured using build settings.

The later sections cover some of the more important build settings, especially ones that control the build process itself and ones that might have non-obvious relationships. This book can't possibly explain them all. The following sections hit the highlights and point you toward the documentation for the rest.

Per-File Compiler Flags

The per-file compiler flags setting is a special place where the compilation of a single source file can be modified. These are literal command-line arguments, set for a particular source file and target, and passed to the compiler only when that source file is compiled. Each source file has a separate compiler flags setting for each target in the project, so you can specify one compiler flag when the file is being compiled for one target and a different compiler flag when it is compiled for another. There are no templates or documentation for these options in Xcode. You will need to consult the compiler's documentation to compose your argument list correctly.

Open the Info window for a source file. If the source belongs to the active target, a Build tab appears in the Info window, as shown in Figure 17-33. You can only edit the compiler flags for the active target. To edit the compiler flags for a different target, you must close the Info window, choose a new active target using the Project

Per-File Compiler Flags
FIGURE 17-33

Figure 17-33. FIGURE 17-33

Per-file compiler flags are like build settings in that they have a specific scope; they are only passed to the compiler when that specific file is being compiled for a specific target. In terms of customizing the build process to your needs, compiler flags can be thought of as the very highest layer of build settings, overriding even the compiler settings in the command-line layer. Just keep in mind that compiler flags settings are not part of the build settings architecture: they are not named variables, cannot refer to other build settings, are not added to the execution environment, and are not accessible to build scripts or external processes. They are a feature supplied by the Compile Sources phase as one more way of fine-tuning the build process.

Personally, I try to avoid per-file compiler flags when possible. It's an obscure feature that's difficult to document and correlate to the source file. These per-file compiler flags are stored in the project document as part of source item, which presents another potential problem; removing the source item or adding the file to another project will discard its settings.

Today, many compiler options can be specified in the source file itself using #pragma, __attribute__, and other compiler-specific syntax. My first choice would be set any module-specific compiler options in the source file, and use per-file compiler flags only as a last resort.

Cross-Development

In Xcode, cross-development refers to developing a program for use in one or more different versions of Mac OS X. It does not mean cross-platform development, or writing a program that runs on a multitude of different operating systems or architectures. Cross-development allows you to produce a program that runs on a specific range of operating system versions (Mac OS X 10.3.4 through Mac OS X 10.5.0, for example). You can also produce applications that run only on a specific version or an application that will run on any version that supports the features it requires.

Installing Cross-Development SDKs

Before you can even think about doing cross-development, you have to install the cross-development SDKs. The standard Xcode Developer Tools installation includes recent cross-development SDKs, but SDKs for older operating systems may be optional installs, as shown in Figure 17-34. If you did not install the SDKs when you installed Xcode, quit Xcode and run the latest Development Tools installer again. At the Custom Install screen, choose the optional Cross-Development support package or packages.

FIGURE 17-34

Figure 17-34. FIGURE 17-34

To use cross-development, you need to choose two boundaries: the earliest version of the operating system that your application can run on, and the latest version of the OS that it utilizes.

Choosing a Target SDK

The latest OS version that your project uses is called the Target SDK. For example, you might be writing and developing your application using Mac OS X 10.6, but your application only uses features and APIs that were present in Mac OS X 10.5, which should allow it run smoothly on both. In this situation, your target SDK should be set to Mac OS X 10.5. The Target SDK setting is set for the entire project in the project's Info window, as shown in Figure 17-35. You can set it using the Base SDK build setting for individual build configurations, or use the General tab to set it for all configurations, as shown at the bottom of Figure 17-35.

FIGURE 17-35

Figure 17-35. FIGURE 17-35

When you set the target SDK, the compiler and linker will fail if you refer to symbols, functions, or types that did not exist when that version of the operating system was released. Understand that this in no way prevents your application from running on later versions of the operating system.

It simply means that Xcode compiles your source code using the headers and frameworks defined by an older version of the OS. This ensures that you're unlikely to use any newer APIs or constants that might cause your application to fail when run on an older OS. There may be other reasons it won't run, but the Target SDK isn't one of them.

Warning

It should be noted that the iPhone provides two target SDKs for each major release of the iPhone OS: a native device SDK and a companion simulator SDK. When you build your iPhone or iPod Touch application for the simulator, you're building your application using a different set of frameworks than those used by the actual device. Be aware that there are some subtle differences between the two, and you should thoroughly test all aspects of your application on a real iPhone or iPod.

Choosing a Deployment Target

The other boundary is the deployment target, set using the Mac OS X Deployment Target (MACOSX_DEPLOYMENT_TARGET) or iPhone OS Deployment Target (IPHONEOS_DEPLOYMENT_TARGET) build setting, as shown in Figure 17-36. This sets the earliest version of the operating system your application will successfully run on. Whereas the Target SDK setting is purely a build time setting, the Deployment Target setting is both a development setting and a run time setting. At build time, this setting flags certain framework and library references as weak. A weak library reference lets your application link to a function that was introduced in a later OS, but still load on an earlier system that lacks that function. (That doesn't mean you can successfully call that function in the legacy environment, it just means the program will load and start running without it.) This setting is also included in the Info.plist of your application bundle and tells the operating system not to allow your application to load if the minimum operating system requirement is not met. This may not have anything to do with what features your application uses; maybe you have simply never tested your application on Mac OS X version 10.4 and you don't want anyone else trying.

FIGURE 17-36

Figure 17-36. FIGURE 17-36

Both of these boundaries have defaults that are set for new projects. The default for the Target SDK is Current OS. In other words, it compiles and links using the operating system frameworks and libraries currently installed on your development system. The default for the Deployment Target is Compiler Default, which really means "none." The operating system will do its best to load and link your application to the available APIs at run time. Your application will fail to load if it has "hard" links to APIs that don't exist.

Cross-Development Building

So how does this all work? When you installed the SDKs, you put a complete set of system frameworks for each major version of the operating system in the /Developers/SDKs folder. Each folder contains a complete copy of the headers, frameworks, and dynamic libraries that shipped with that version of the operating system, except that all of the executable code has been removed; so-called "stub" libraries.

When you choose a Target SDK in the project, Xcode sets the SDKROOT build settings. This is the path used by the compiler and linker to read all of the system headers and libraries your program links to. (I recommend not trying to change its value using a build setting.) When you set the Target SDK for iPhone OS 3.0, it is just as if you were writing and compiling your program on an iPhone running 3.0. The compilers and linkers know nothing about new features added in later versions of the OS, and will complain if you try to use them. This should prevent you from using any features unique to the iPhone OS version 3.1, which might make your app incompatible with 3.0.

Cross-Development Deployment

The Deployment Target is a little more complicated. The headers in the SDK use the MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET settings to define special macros. These macros identify API symbols that did not exist in earlier versions of the operating system. The value of the build setting determines which symbols are affected. For example, say your application refers to a function that was added in iPhone OS 3.0. If run under iPhone OS 2.2.1, that function isn't present. Normally this would cause your application to fail before it even started. By compiling your application with an iPhone OS deployment target of 2.2.1, it tells the compiler and linker to make a special weak reference to that symbol in the system framework. Your program will load and run on an iPhone running 2.2.1, even though that particular routine isn't present in the 2.2.1 frameworks.

Warning

Calling a missing function is still a very bad idea. You'll have to add code to your application to determine conditionally whether that function is available — hint, a weak reference to a missing symbol will be NULL — and avoid calling it when it's not.

There are a number of limitations to using the deployment target. Here are a few:

  • Cross-development is only supported for native targets.

  • Weak linking only works in Mac OS X 10.2 and later, and even then not all cross-development features are available in 10.2.

  • You cannot use the system's umbrella header file as your program's prefix file. That is, you can't set your project's prefix file to /System/Library/Frameworks/Carbon.framework/Headers/Carbon.h. That's because this isn't the correct header if you've chosen a different SDK. Create your own header that does nothing but include the current framework header, as follows, which will automatically include the Carbon.h header from whatever SDK you have selected:

#include <Carbon/Carbon.h>

A number of other, more obscure limitations and caveats exist. To find out about them, refer to the Cross-Development Programming Guide included with the Xcode documentation, or online at http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/cross_development/. Also check out the SDKExample project. This demonstrates how to use weak linking for functions in a newer version of the OS, and then check to see if those functions are available at run time.

Building Universal Binaries

Prior to 2004, Xcode only produced PowerPC executable binaries. That's because this was the only processor architecture that Mac OS X supported. Since then, Apple Computer has added two new architectures to its OS pantheon (64-bit PowerPC, Intel 32- and 62-bit), along with new processors (ARM) for its consumer lines of iPhone and iPod Touch products. Xcode can compile your program for any or all of these architectures when you build your project. It does so by repeatedly compiling your application, once for each architecture, and then storing all of the resulting versions in a single multi-architecture binary (MAB) file — a file format that Mac OS X has supported for a long time. Binaries that contain executable code for multiple architectures are referred to as Universal Binaries.

Choosing the Architecture Set

To determine which architectures you want to build, set the Architectures (ARCHS) build setting; you will find it in the Architectures group. When you click the setting name, an architectures pop-up menu appears. Select the architecture, or architecture set, that you want to build.

The Architectures (ARCHS) setting is a space-delimited list of architectures to be built. Xcode supplies a number of build settings that contain predefined sets of useful architecture lists, such as ARCHS_STANDARD_32BIT, which will build only the 32-bit variants of the processors that Mac OS X deploys on (that is, PowerPC and Intel). The pop-up menu simply defines the ARCHS setting to equal one of these built-in settings, that is, ARCHS = $(ARCHS_STANDARD_32_BIT). The standard architecture macros supplied by Xcode are listed in the following table:

BUILD SETTING

DESCRIPTION

ARCHS

The list of architectures to build

ARCHS_STANDARD_32_64_BIT

Standard architectures for mixed 32-/64-bit deployment

ARCHS_STANDARD_32_BIT

32-bit only architectures

ARCHS_STANDARD_64_BIT

64-bit only architectures

When you're building your project for release, ARCHS should define the list of architectures your application supports.

For development, however, building multiple architectures is a waste of time; you typically test on the system that you're developing on, and you can only run and test code compatible with the architecture of your development system. That's why the ARCHS build setting for the Debug build configuration is normally set to $(NATIVE_ARCH), which is described next.

Your Native Architecture

The NATIVE_ARCH build setting is the name of the architecture of the machine Xcode is currently running on. Setting ARCHS to $(NATIVE_ARCH) causes Xcode to only build the single, native architecture when compiling applications and is intended for debugging. A number of variations of this build setting are listed in the following table:

BUILD SETTING

DESCRIPTION

NATIVE_ARCH

Generic architecture of your development system

NATIVE_ARCH_32_BIT

Development architecture in 32-bit mode

NATIVE_ARCH_64_BIT

Development architecture in 64-bit mode, if available

NATIVE_ARCH_ACTUAL

The specific architecture currently running

For example, on the development system I'm using right now, NATIVE_ARCH is i386 (Intel), and NATIVE_ARCH_ACTUAL is x86_64 (because I'm running on a 64-bit capable system).

The Valid Architectures

The ARCHS setting is always tempered by the VALID_ARCHS build setting. This setting does not appear in the Xcode interface, but defaults to the list of architectures that Xcode knows how to build. Xcode only builds the architectures listed in this setting. If you redefined VALID_ARCHS to ppc ppc64 it would limit the project to producing only 32-bit and 64-bit PowerPC binaries, even if other project settings requested other architectures.

Note

If you're trying to create a conditional build setting and don't know what value to use in the arch= statement, use the shell script trick described in the "A Peek-A-Boo Build Script" section to dump all of ARCH variables. There you will find the exact architecture names that Xcode recognizes.

Finally, recompiling your program for another architecture is no guarantee that it will work. Subtle differences in pointer sizes and byte order can cause your application to fail. If you need to build a specific architecture for debugging and testing, set ARCHS to that specific architecture. Refer to the "Universal Binary Programming Guidelines" and the "64-Bit Transition Guide" in the Xcode documentation for additional details.

Selected Build Settings in Detail

Build settings, like so many other details in software development, are easy to find — as long as you already know where to look. The catch-22 occurs when you're trying to find something and don't know what it is or where to find it. The following sections highlight hand-selected build settings that you should be familiar with, or are notoriously difficult to find in the documentation.

When listing Xcode-defined build settings, this book uses the form "Full Title (NAME)" to describe each setting. Use its title when you're looking for a setting in the Xcode documentation. Use its name when referring to build settings in scripts or in build-setting value expressions. Remember that copying a build setting will place its definition (NAME=value) on the clipboard.

Warning

Build settings fall roughly into two categories: modifiable build settings that alter the behavior of the build process and informational build settings created by Xcode. The latter are not intended to be changed. They are for use in other build setting values, custom scripts, and external processes and provide you with information about what is being built and how. Changing an informational build setting can lead to undesirable results.

Browsing the build settings in the Build tab of the target or project can be very instructional. The major build settings are described here. If you see a build setting that's not covered in this chapter, search the Xcode documentation for its name. The Xcode release notes cover most new and existing build settings. There is also a Build Setting Reference document included in the Xcode documentation that describes many of these same settings.

Products

The Product Name (PRODUCT_NAME) setting is, quit literally, the name of the product produced by the target. To change the name of your target's product, edit this build setting. Note that the final product name is actually a little more complicated if it includes an extension or is in a wrapper (bundle), but these are tacked on by other build settings.

Info.plist Files

These settings control how the Info.plist file is generated for targets that produce bundles, as described in the following table.

BUILD SETTING

DESCRIPTION

Info.plist File (INFOPLIST_FILE)

This is the file in your project that will become the Info.plist file for your product.

Preprocess Info.plist File (INFOPLIST_PREPROCESS)

If this flag is set, then INFOPLIST_FILE is run through the gcc preprocessor. This allows you to use preprocessing macros and #if statements in your source Info.plist file.

Info.plist Preprocessor Prefix File (INFOPLIST_PREFIX_HEADER)

If your Info.plist file is preprocessed, this prefix file is read by the compiler first.

Info.plist Preprocessor Definitions (INFOPLIST_PREPROCESSOR_DEFINITIONS)

Space-separated list of macro definitions passed to the compiler when preprocessing the Info.plist file. Use this as an alternative to, or as an adjunct to, using a prefix file.

Search Paths

The search path settings determine where compilers and linkers look for headers and other files referred to only by their name or partial path. Each build setting is a space-separated list of paths. If a path itself contains a space or some other special character, it must be quoted in the list.

Each path specifies a folder to search. If the path ends in **, Xcode also searches any subfolders for the file it is looking for. Xcode always searches each folder for the file first, before looking in any subfolders.

Many of the paths in these settings refer to headers and libraries in the system framework folders. These would be paths that start with /System/Library/Frameworks. When you're building using a Target SDK, Xcode automatically prefixes any system framework path with $(SDKROOT) so that it correctly refers to the corresponding folder in the current SDK.

BUILD SETTING

DESCRIPTION

Header Search Paths (HEADER_SEARCH_PATHS)

The paths where the gcc compiler and other tools will look for included files. System paths are prefixed with $(SDKROOT).

Library Search Paths (LIBRARY_SEARCH_PATHS)

The folders where the linker will look for libraries. System paths are prefixed with $(SDKROOT).

Framework Search Paths (FRAMEWORK_SEARCH_PATHS)

Paths for frameworks, used mostly to locate framework headers. System paths are prefixed with $(SDKROOT).

Rez Search Paths (REZ_SEARCH_PATHS)

Paths for the Rez resource compiler

Always Search User Paths (ALWAYS_SEARCH_USER_PATHS)

In C, the directives #include "file.h" and #include <file.h> use different search paths to locate the file, distinguishing "user" from "system" headers. Making this build setting YES causes both directives to use the same search path.

Precompiled Headers and Prefix Headers

Precompiled headers are a saved compiler state containing all of the definitions defined in some source headers. It takes quite a bit of time to interpret and construct the type, class, and constants defined in a large group of headers, yet most headers do not change at all between builds. By saving the compiled form of a commonly used set of headers, the compiler avoids the need to repeat that work for every source file in your project.

You begin by creating what's called a prefix header with an extension of .pch. This is a source file that does nothing but include (#include) the headers to which you want access in all of the source files in a target. A typical prefix header is shown in the following code:

#ifdef __OBJC__
 #import <Cocoa/Cocoa.h>
#endif

You can also include other global defines or headers that you expect every source file to need and you do not expect to change often, if ever. Xcode compiles this file first, and then automatically prefixes it to every source file it compiles. It is just as if you manually inserted #include "MyPrefixHeader.h" as the first line of every source file in your project. Most application project templates already include a prefix header, so look in your project before creating a new one.

BUILD SETTING

DESCRIPTION

Prefix Header (GCC_PREFIX_HEADER)

The header to include at the beginning of every source file.

Precompile Prefix Header (GCC_PRECOMPILE_PREFIX_HEADER)

When set to YES, this causes the prefix header to be precompiled and saved between builds. If you use prefix headers, this should be turned on.

C Compiler

The gcc compiler is by far the largest consumer of build settings. Most apply to specific settings for the gcc compiler. You can browse them in the build settings editor under the GNU C/C++ Compiler category. Most are self-explanatory. You can refer to the gcc man page or the gcc manual at http://gcc.gnu.org/onlinedocs/ for more in-depth description of the various options and switches.

The following table describes some of the more commonly customized C compiler build settings.

BUILD SETTING

DESCRIPTION

Preprocessor Macros (GCC_PREPROCESSOR_DEFINITIONS)

A space-separated list of macro definitions that will be predefined by gcc before each source file is compiled. Identical to inserting a #define MACRO value statement at the beginning of each file. The form for each definition in the list is either MACRO or MACRO=value. If the definition contains special characters, it needs to be surrounded by quotes.

Preprocessor Macros Not Used in Precompiled Headers (GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPILED_HEADERS)

Just like Preprocessor Macros, but these are defined after the prefix file is included. If your prefixed headers do not need the definitions defined on the gcc command line, they should be in this build setting. Otherwise, Xcode must recompile your prefix headers whenever these values change.

GCC_VERSION

Selects the version of the gcc compiler to use (GCC 4.x, LLVM, Clang). This setting was deprecated for a while, but is back in vogue again. Be aware that the effects of this setting can be overridden by build rules.

Other C Flags (OTHER_CFLAGS), Other C++ Flags (OTHER_CPLUSPLUSFLAGS)

These are open-ended build settings that let you pass additional command-line arguments to the gcc compiler. The Other C Flags are passed to the compiler when compiling C and Objective-C source. The Other C++ Flags are passed when compiling C++ and Objective-C++ source.

It should be noted that the default setting for OTHER_CPLUSPLUSFLAGS is $(OTHER_CFLAGS), so if you want to add arguments to C and Objective-C compiles that you do not want passed to the C++ compiler, you'll need to edit both settings.

Other Compilers

Other compilers also use build settings. The two described in the following table let you pass arguments to the lex and yacc compilers.

BUILD SETTING

DESCRIPTION

LEXFLAGS

Command arguments passed to the lex compiler.

YACCFLAGS

Command arguments passed to the yacc compiler.

Linker Settings

Linker settings control the ld linker, invoked for any compiler that produces object code files that need to be linked to create a binary executable. The following table describes these settings.

BUILD SETTING

DESCRIPTION

Library Search Paths (LIBRARY_SEARCH_PATHS)

See the earlier "Search Paths" section.

Other Linker Flags (OTHER_LDFLAGS)

Like the "other" compiler flags setting, this set of settings let you pass whatever additional command-line arguments you need to the linker.

Kernel Modules

If you're producing a Kernel module, you'll probably need to use some of the settings described in the following table:

BUILD SETTING

DESCRIPTION

Module Version (MODULE_VERSION)

The version declared in the module's stub.

Module Identifier (MODULE_NAME)

The module's unique identifier.

Module Start Routine (MODULE_START), Module Stop Routine (MODULE_START)

The names of the module's start and stop functions.

Deployment

Deployment settings control the deployment phase of a build. This is the final phase, where the finished products are cleaned up, polished, shrink-wrapped, and generally made ready to ship.

Deployment post-processing is performed whenever the DEPLOYMENT_POSTPROCESSING build setting is set to YES. This setting is also set to YES if you build a project using the xcodebuild tool and pass it the install argument. Deployment post-processing consists of:

  • Stripping the binary of debugger symbols and unnecessary linkage information.

  • Running any copy files or script phases that have the "only run when installing" flag set. (See Chapter 16 for more about copy file and script phases.)

  • The ownership and permissions of the final product are set.

The following table describes the deployment settings:

BUILD SETTING

DESCRIPTION

Deployment Postprocessing (DEPLOYMENT_POSTPROCESSING)

If set to YES, deployment post-processing is performed.

Deployment Location (DEPLOYMENT_LOCATION)

If this is set to YES — note that this is a Boolean flag, not a path — the products are built in the deployment location instead of the normal build location. This setting is also YES if xcodebuild is run with the install command. See the INSTALL_PATH and related build settings to control where the deployment location is.

Installation Directory(INSTALL_PATH)

The path where the products for this target should be placed. This path is relative to $(DSTROOT). For example, the install path for a BSD tool might be /usr/bin. The install path for a framework would be /Library/Frameworks.

Strip Debug Symbols from Binary Files (COPY_PHASE_STRIP)

If this is set, the executable binaries are stripped of debugger information when they are copied to their deployment folder. Normally you don't have to set this, because stripping of deployed products should happen automatically. Set this if you are including code built by some external process or outside of Xcode altogether.

Strip Linked Product (STRIP_INSTALLED_PRODUCT)

If YES, the normal product stripping performed by post-processing is, instead, not performed.

Skip Install (SKIP_INSTALL)

If this and Deployment Location are both set, products are deployed instead to $(TARGET_TEMP_DIR)/Uninstalled Products. Use this for targets that generate products that are used by, but not included with, the final deployed products. This could include, for example, a static library.

Installation Build Products Location (DSTROOT)

The destination folder for installed products. Products are "installed" within this folder using relative paths to their final location. For example, a BSD tool that installs a tool might be installed in $(DSTROOT)/bin. You might think that the normal value for DSTROOT would be /, but you'd be wrong for two reasons. It would be very surprising to novice Xcode users if in the process of building a project they started overwriting installed system components. Also, most of the locations in / are not writable unless root privileges are obtained, and Xcode does not normally run as root. Instead, this folder is a "picture" of what the final installation should look like. For normal builds, this is a temporary location or a folder within the build folder. To build and install a product directly in the system, set DSTROOT to / and run the xcodebuild tool as root.

Install Owner (INSTALL_OWNER) (INSTALL_GROUP) (INSTALL_MODE_FLAG)

When DEPLOYMENT_POSTPROCESSING is on, these Install Group settings determine the owner, group, and UNIX Install Permissions access privileges of the deployed product. These default to $(USER), $(GROUP), and a-w,a+rX, respectively.

Most of these settings are enabled, or only control steps that are performed, when DEPLOYMENT_POSTPROCESSING is on. If changing a deployment or installation build setting doesn't have the desired effect, check to see if it is dependent on DEPLOYMENT_POSTPROCESSING.

Build Information

The rest of the build settings covered here are informational. That is, you shouldn't try to set these in the build settings in an attempt to influence how Xcode builds your product. Instead, most of these are build settings that are set by Xcode based on its environment, other information you have already configured in the project, or reflect specifically what Xcode is doing. For example, Xcode sets the TARGET_NAME build setting to the name of the target currently being built. You can use this information in custom scripts or external build tools, or refer to it in other build settings. What you shouldn't do is try to redefine it.

Because of this, most informational build settings do not show up in the Build tab where project and target build settings are edited. The following table describes the informational build settings. (Also refer to Chapter 17 about the build settings that are defined when custom scripts or build rule scripts are executed.)

BUILD SETTING

DESCRIPTION

ACTION

This setting will be either build or clean, depending on what kind of build Xcode is performing.

PROJECT_NAME

The name of the project being built.

CONFIGURATION

The name of the build configuration that is active.

TARGET_NAME

The name of the target being built.

TARGET_BUILD_DIR

The path in the build folder where the products of this target should be written.

TARGET_TEMP_DIR

The path used for temporary files while building a target. Custom build scripts should write any temporary files they generate into this directory.

PROJECT_TEMP_DIR

A temporary folder for use by any build process in the project.

SRCROOT, or PROJECT_DIR

The project folder.

SDKROOT

Described earlier in the "Cross-Development" section.

OBJROOT

The top folder where intermediate object files are written.

SYMROOT

The "symbol-rich" product location. This is where products are written before they are stripped.

Tools

To avoid having to hard-code the path of various build tools and to have the ability of redefining which tool to use for all phases of a build, the following build settings are defined:

ASM

GATHERHEADERDOC

MKDIR

REZ

CC

HEADERDOC2HTML

MV

RM

CD

JAR

NMEDIT

RPCGEN

CHMOD

JAVA_COMPILER

OSAC

SED

CHOWN

JAVACONFIG

OSAL

SH

CP

LD

OSAS

STRIP

DITTO

LEX

PBXCP

TOUCH

ECHO

LIBTOOL

RANLIB

UNZIP

EGREP

LN

REGGEN

XARGS

FIXPRECOMPS

MAKEPSEUDOLIB

RESMERGER

YACC

FIND

MERGEINFO

RESOURCE_PRESERVING_CP

ZIP

Each of these settings contains a path to the executable tool of the same name. Thus, if you wanted to invoke the Java compiler in a build script, use the statement ${JAVA_COMPILER} instead of /usr/bin/javac. If at some point you decide to use a different Java compiler, both your scripts and Xcode will still be using the same one.

Standard System Locations

The build settings described in the following table may be useful for defining installation locations and for locating tools, plug-ins, templates, or other resources in your build scripts. Each gets defined with a path to one of the standard locations defined by the system or the current installation of the Xcode tools. If you've installed Xcode in some directory other than /Developer, these paths will be adjusted accordingly. There are actually more settings than are listed, but these are the major ones.

BUILD SETTING

PATH

SYSTEM_APPS_DIR

/Applications

SYSTEM_ADMIN_APPS_DIR

/Applications/Utilities

DEVELOPER_DIR

/Developer

DEVELOPER_APPLICATIONS_DIR

/Developer/Applications

DEVELOPER_BIN_DIR

/Developer/usr/bin

DEVELOPER_TOOLS_DIR

/Developer/Tools

SYSTEM_LIBRARY_DIR

/System/Library

LOCAL_LIBRARY_DIR

/Library

USER_LIBRARY_DIR

~/Library

XCODE_APP_SUPPORT_DIR

/Library/Application Support/Apple/Developer Tools

THE XCODEBUILD TOOL

The development tools include an xcodebuild command-line tool for building Xcode projects. The xcodebuild tool is installed in your /usr/bin directory by the developer tools installer, so you do not have to add the /Developer/Tools directory to your shell path to use it. The installer also installs a man page for xcodebuild.

Having the ability to build Xcode projects via a command-line tool provides a great deal of flexibility in your development workflow. You can build complex shell scripts to build different product configurations automatically. You could schedule nightly builds of large projects. You can integrate Xcode projects into other make tools, like gnumake or Ant. It's also used to define custom build commands in the Organizer (see Chapter 22). Besides being able to drive the build process externally, you can also use xcodebuild to add a layer of intelligence inside Xcode. Using custom build scripts and external build targets, you can invoke scripts that make decisions, and then build another target or project using xcodebuild. Here's an example: one limitation of Xcode targets is that you can't change the input files to a target based on a build configuration. That is, you can't have a target that links to one library when built using one build configuration and a different library for another. You could easily create two targets: MyApp-Release and MyApp-Debug. A custom script can examine the build settings and build the appropriate target using something like xcodebuild -target MyApp-${CONFIGURATION}. The possibilities are almost limitless.

Using the xcodebuild Tool

To use the xcodebuild tool, the working directory must be set to the project folder. The tool does not accept a path to a project folder or document elsewhere. When you execute xcodebuild, you can optionally specify the name of the project, the target, and the build configuration to be built as arguments. If any are omitted, xcodebuild will choose a project, target, and build configuration for you.

Warning

xcodebuild reads and respects the Xcode preferences you've defined. However, preferences are stored on a per-user basis. If you run xcodebuild under a different user ID, namely root, the Xcode preferences used will be those of that other user. Unless you've run and configured the Xcode application while logged in as that user, there will be no Xcode preferences file, and xcodebuild will use the defaults for all settings.

A project name can be specified using the -project projectname argument. This name is the complete filename of the project document, including its extension. If this argument is absent, xcodebuild finds and builds the one and only project document in the folder. If there is more than one project, xcodebuild throws an error and stops. This argument is only needed for project folders that have multiple project documents.

You can choose a target using the -target targetname argument. If this argument is omitted, the first target defined in the project is built. For projects you intend to build using xcodebuild, arrange your targets so that your top-level aggregate target is the first target in the Targets group. That way, you don't have to specify a target for your most common builds. Alternatively, you can use either the -activetarget or -alltargets switch. The -activetarget switch builds the last active target set in the Xcode application. The -alltargets switch builds all of the targets in your project; something you can't do in Xcode, except for clean builds.

The -configuration configurationname switch selects a build configuration to use. You can specify the build configuration or use the -activeconfiguration switch instead. These switches select either the named build configuration or the last active build configuration set in the Xcode application. If both are omitted, the default build configuration is used. Go to the Configurations tab of the project's Info window to set the default build configuration for your project.

Two additional arguments are used to modify the build. The first is the build action. This can be one of the values described in the following table.

COMMAND

DESCRIPTION

build

Builds the target or targets.

clean

Runs a clean build on the target or targets.

install

Performs a build, enabling all deployment postprocessing phases. This option sets the DEPLOYMENT_POSTPROCESSING build setting. You should define the DSTROOT location if you want the final products installed someplace other than the build folder.

installsrc

Copies the source of the project to SRCROOT. Rarely used.

If you don't specify any action, build is assumed. You can specify more than one action. The actions will be executed in order, just as if you had invoked the xcodebuild tool multiple times. For example, xcodebuild clean build first runs a clean build followed by a normal build.

You can also pass build settings to the xcodebuild tool using the following guidelines:

  • Build settings passed as arguments to xcodebuild supersede any other build settings defined elsewhere. See "The Scope of Build Settings," earlier in this chapter.

  • The syntax for a build setting is SETTING_NAME=value.

  • Each setting is a separate argument.

  • The shell may require you to quote the contents of some build settings.

  • You can include as many build settings as will fit on the command line.

The following listing shows xcodebuild being passed two build settings: DSTROOT and DEPLOYMENT_LOCATION:

xcodebuild DSTROOT=/ DEPLOYMENT_LOCATION=YES install

There are many other miscellaneous xcodebuild options. Three you might be interested in are listed in the following table:

OPTION

DESCRIPTION

-version

Outputs the version of the xcodebuild tool to stdout.

-list

List the names of the targets and the build configurations defined in the project. The active target and both the active and default build configurations are all noted. No build is performed.

-help

Outputs a concise summary of xcodebuild's argument syntax.

Compatibility

xcodebuild is capable of building .xcodeproj (Xcode 2.1 and later) documents as well as earlier .xcode project documents. If you run xcodebuild without specifying a project document name, it first searches for an .xcodeproj document and reads that if found. If there are no .xcodeproj documents present, it looks for an .xcode document. In the latter case, xcodebuild internally upgrades the .xcode document, turning it into an .xcodeproj document, and then builds using that .xcodeproj document. The intermediate .xcodeproj document exists only in memory, and is discarded once the build is complete.

XCODE AUTOMATOR ACTIONS

In addition to the xcodebuild tool, the Xcode Development Tools also install a suite of Automator actions, shown in Figure 17-37.

FIGURE 17-37

Figure 17-37. FIGURE 17-37

There are actions to perform CVS source control actions (see Chapter 21), create installation package, and perform builds. The Build Xcode Project Action is just a wrapper that ultimately invokes the xcodebuild tool to perform the build, but the Automator action interface makes it far easier to configure and integrate the build with a larger workflow.

The Build Xcode Project action expects an Xcode project document as its input. The action options let you choose the action (clean, build, and so on), specify a target, choose a build configuration, and supply an arbitrary set of build settings.

DISTRIBUTED BUILDS

One of the more amazing features of Xcode is distributed builds. It's not so much the technology that performs it, which is sophisticated to be sure, but how incredibly easy it is to set up and use.

Distributed builds allow the compilation of source files to be distributed among a group of computers, where they can be compiled in parallel. Every build can call upon the resources of two or — if you have them — more than a dozen computers to simultaneously compile the files in your project. This allows a single developer to harness the power of other (probably) idle machines on his network, such as file servers. Teams of users can share and make more effective use of their resources. It's also a great equalizer. A team member developing programs on a single-core MacMini can harness nearly the same power for his builds as the next developer, who's using a multi-processor, multi-core system.

Here are a few prerequisites and limitations to using distributed builds:

  • All machines must be accessible via TCP/IP.

  • All systems must be running the exact same version of the operating system and compiler. When you're upgrading your operating system or Xcode, perform the upgrade on all of your development machines simultaneously. This ensures that there is no difference between compilers and the system frameworks between distributed machines.

  • All computers must be of the same architecture. Intel computers can only distribute builds to other Intel-based systems.

  • Distributed building only distributes the Compile Sources phase of native targets for C language files. This includes C, C++, and Objective-C. Java, AppleScript, Link, Copy Files, custom scripts, and Jam-based targets can't be parallelized. Precompiling headers, linking, and product packaging are all performed on the local machine.

  • To be effective, you need a fairly high-speed network. 100MB Ethernet is considered a minimum, with 1GB Ethernet or better preferred. You won't get much benefit from distributed builds over a wireless network. Remember too that FireWire can be daisy-chained to create a very high-speed TCP/IP network.

  • Firewalls can block distributed builds. Computers employing firewalls must allow traffic on ports 3632 and 7264.

Using distributed builds couldn't be easier. Every machine with Xcode installed can be a provider (will compile files for other developers), a client (will distribute builds to other providers), or both. Each client can also be selective about machines to which it distributes builds.

Open the Distributed Builds pane of the Xcode Preferences of each development machine on the network. The Distributed Builds pane is shown in Figure 17-38.

FIGURE 17-38

Figure 17-38. FIGURE 17-38

Sharing Your System with Others

In order to share your computer — offer to compile files for other developers — you must first unlock the padlock in the lower-left corner. You are asked to supply an administrator username and password. Authenticating as an administrator allows Xcode to install the background services that provide distributed building.

Check the box next to the Share My Computer for Shared Workgroup Builds option to make this computer available on the network to perform builds for other developers. The pop-up menu next to the option allows you to choose a process priority for the distributed build process. If you regularly perform time-sensitive, CPU-intensive, tasks such as multi-media processing, you might consider setting this to medium or low priority. Lowering the priority also gives local builds an edge over builds for other developers. Remember that process priority only comes into play when two or more processes are competing to use the CPU. If the computer is idle, it doesn't matter what the priority is; the build will use all of the available CPU time.

Note

Xcode uses the distcc tool and distccd daemon to perform distributed builds. When you share your system with a workgroup, Xcode starts up a distccd daemon for each processor core in your CPU. These daemons run all the time; you don't have to be running the Xcode application in order to build products for other workgroup members.

Distributing Your Builds to the Workgroup

In the lower portion of the pane is a list of computers you can distribute builds to. Available computers are organized into sets, listed on the left. The Bonjour set is a smart set that lists all active build providers on the local subnet. This set is assembled using the Bonjour (ZeroConfig) protocol, and automatically adjusts to reflect the available build providers on the local subnet. For most installations, this is the only set you will need.

The computers in the list display their status and suitability. The Host column contains the IP address of the system. The OS and Resources columns list the versions of the provider's operating system and compilers. You can only distribute a build to a computer with the same version of OS and compiler. The compiler in question will be the compiler required by the target being built. In the example in Figure 17-38, the computer marchhare.local has a compatible version of gcc 4.0.1, but an incompatible version of gcc 4.2.1. This computer could accept builds for targets that use the gcc 4.0.1 compiler, but not ones that required gcc 4.2.1. The computer mini.local, on the other hand, is running an older operating system and cannot accept any builds. Incompatible computers, tools, and Xcode installations are listed in red.

If you want to limit the distribution of builds to a specific subset of local computers, or if you want to add computers that do not appear in the Bonjour list, you need to create a custom set. Click the + button below the list of sets to create a new set, and then give the set a name. You can also duplicate an existing set. Selecting a set, or sets, lists only the computers in those sets. The list is always a union of the sets selected, so computers in multiple sets are listed only once. To delete a set, select it and click the – button. You cannot delete the Bonjour set.

To add a computer to a custom set, either drag a computer from the list into the set, or click the + button below the list with that set selected. Enter the address of the new system, using either a domain name or a numeric address. Xcode adds the new system to every set currently selected and automatically queries the system to discover its status and suitability. To remove a computer from a set, select it in the list and click the – button. You cannot add or remove computers from the Bonjour set. Consequently, having the Bonjour set selected disables both the add and remove buttons for all sets. To add or remove computers from the list, select only custom sets.

To distribute your builds to other computers, check the box next to Distribute Building Via Shared Workgroup Builds, and then check the box next to each set that you want Xcode to include in distributed builds. The computers in all of the checked sets will be considered when Xcode distributes builds to other computers.

That's all there is to it. If you've elected to distribute your builds with other computers, your next build will employ distributed building. Figure 17-39 shows the build of a large project on a laptop computer. Normally, it would only compile one or two files at a time, but with distributed building, it can now compile a score of files simultaneously by exploiting the other computer systems in its workgroup.

FIGURE 17-39

Figure 17-39. FIGURE 17-39

SUMMARY

Controlling the build process is a critical step in any successful development project. You should now be able to start and stop builds at will, examine the results of the build, and locate errors that occurred while building. Using build settings and build configurations, you can customize many features of the compiler, linker, and Xcode itself. Using build setting layers and build configurations, you can create complex sets of build settings, allowing you to customize specific features of specific targets for specific variations.

Just as important as control is the speed of your development. By learning to enable such features as prefix headers and distributed builds, you can radically reduce the amount of time it takes to build and test your application.

Even after building your project successfully, you're still not quite done. The next chapter shows you how to run and test your application from within Xcode.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset