Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2002-908
$eventId
ID of event: wwdc2002
$eventContentId
ID of session without event part: 908
$eventShortId
Shortened ID of event: wwdc02
$year
Year of session: 2002
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC02 • Session 908

Delivering with Project Builder

Tools • 43:21

The Project Builder IDE has many features designed to facilitate and enhance productivity. This in-depth presentation shows developers how to use these features effectively. Application delivery and the use of disk images and Installer packages will also be highlighted in this session.

Speakers: Anders Bertelrud, Christian Molick

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Ladies and gentlemen, please welcome Technology Manager for Development Tools, Godfrey DiGiorgi. Good afternoon. I hope you've all had a good lunch. How was it this week? Did we serve you good food? Fantastic. Continuing in our theme today of driving into the details of development tools, I would like to introduce Anders Bertelrud, the engineer on Project Builder to do the build system.

Good afternoon. So hopefully a lot of you in the 903 session saw some of the new features in Project Builder and as well as an introduction to Project Builder. Something, some of the topics covered were the build system and how to set up your project. So in this session we sort of assumed that you have a project to build. So this is really the next step after that.

So you have a project that you got to build and then, you know, you got your sources fine. And what do you do now? Well, so one of the things we're going to talk about is how to streamline the build process, speed up the builds, how to take advantage of some of the features Project Builder has for that.

Talk about polishing the product, things like adding a version number, things like that. Building for deployment as opposed to development. For development you often want to do testing. For deployment you sort of want a different situation. You want to optimize, you want to strip out debug symbols, things like that.

We're going to talk about packaging your product. And as you know, on Mac, we try for drag and drop install experience. You just take the app and just drop it onto the -- into a folder and not have to run an installer. Sometimes you do. We'll talk about that.

The third -- the last thing is ship it. And that's up to you guys. So we talk about the rest, and then you deal with it. What you learn in here in this session is to use the IDE effectively, in particular speeding up GCC3 compilation, which John talked about in the session this morning on GCC3.1. Talk about adding finishing touches, building for deployment, and also specifically disk images and installer packages. So to start off, we'll talk about using the IDE.

So one of the things the IDE lets you do is to customize your build using what we call build styles. So if you have a target that builds a product, you can set up multiple build styles to build the product in different ways. We'll get into that in a second.

Another thing you can do to take advantage of that is to set up a shared product directory. And this does two primary things. It lets one project access another project's product. So you can split up your development if you have a large source base. The other thing it does is keep your binaries separate from source code. So if you have your source on network, you can keep your binaries local for speed.

The IDE also has something called executables. And this lets you set up different execution contexts. So you may want to test your app in four different ways with four different test cases. You may have a test tool that takes different-- or you may have a Unix tool that takes different command line options. You can set up different test cases for each of those situations. and quickly switch between them.

So build styles in-depth. Where does a target kind of define what you build? A build style defines different ways of building a target. I'm sure you've all heard this before. Many of you have heard this before. But this really is kind of quite powerful because instead of having to copy the target to set it up to build your app in different ways, you just have one target, you have many build styles, any changes you make to the target, you don't have to update multiple copies. The build style just dynamically overrides it. So some examples of what you can use this for is to turn debug symbols on or off, to enable or disable assertions, et cetera.

Actually, in the 903 session on Wednesday, there was a question about, well, what if I want to build deployment versus development, and we have the object files. Project Builder doesn't keep track of the separate object files. It actually turns out you can set one of the build settings is where Project Builder is stored, the object files.

If you set that differently in the different build styles, Project Builder will actually write the object files in different places. So that's actually a way you can work around Project Builder's current lack of knowledge of that, just by defining that build setting. That build setting is objroot, by the way.

So, build settings dynamically modify the target settings. And there are two ways they can do this. You can either override a target setting completely, and then the setting in the target will be completely ignored. This is something that some people run into currently when they set up a project.

They'll configure a target, they'll turn on a certain optimization level in the target, and then the build style will come along and override it and say, why isn't my optimization level being used? So, if your configuration in the target is not being used, check to see that a build style isn't overriding it. And we have some thoughts on how to add UI to indicate that target settings are being shadowed. But the Jaguar version does not do that yet.

So target settings can also refer back to build style settings. So this can be quite powerful, because you can not only override or add to, actually, is the other way, to add to a target setting, but you can actually have a target setting that includes $FU, where FU is defined in the build style. You just have to avoid circular references, right? You can't define X in terms of itself. That doesn't mean anything.

So when the build settings are evaluated, there's a hierarchy. There's a precedence ordering, as you might expect. And at the very bottom level, you have access to all the environment variables, but anything you define can override those. But that can be useful for accessing a build setting such as dollar home, for example.

Next, we have the static settings. These are the Project Builder defaults. These are things like the default optimization level. These are things like where Project Builder by default, like the default extension for an application package is .app, for example. Then come the target settings that are in your actual target. This is what you see in the target editor. That's the purple box right there. And then the build style settings. These are the things that go above that. So again, reflecting that anything defined in a build style will shadow what's in the target.

And at the very top, if you're building from PBX build, anything you pass on the command line in PBX build goes on top of that. So that overrides anything. This is just like in Make. In fact, PBX build was the command line interface that was designed to be compatible with Make.

And in the IDE, there's always one active build style. And normally, there's a pop-up in the toolbar. And if you don't see that, you can customize the toolbar and drag the pop-up into it. And you can choose the active build style in that pop-up. PBX Build, the tool, allows you much greater flexibility. You can, for example, build without any build style, or you can build with a particular name.

So much for build styles. So the other thing you can do, one other way you can take advantage of the IDE is to set up a shared product directory. I mentioned this in the intro. The reason you may want to do this is that if you have a framework built by one project and an app built by another project, if you set up a shared framework directory, then both those products will get put into the same directory.

Project Builder has an extra feature that lets it look in that shared build directory. So if you set up a shared product directory, it will look in there first when it goes to link against a library or a framework. So this is a very convenient way of letting all of your target's products go into the same place. You can refer to them at build time. The other reason, of course, is speed.

If you booted off NFS, if you have your source code on NFS, sorry, if your home directory is on NFS, you may have your source code there. You certainly don't want to be shipping binaries. You can set the build directory to a place under your local hard disk and speed up your builds quite significantly.

And the way to do this is to specify a directory in the preference panel. And the rule is, everything, all generated binaries will be put there, unless you do special things in a build style, override the special variables. The other thing that happens is that the runtime is set up automatically. So when you run your app from Project Builder, not only will the build find it, but at runtime, the framework will be found as well. So this is an added bonus there.

So we talked a little bit about using the IDE effectively. One of the other things I want to talk about is speed up GCC3 compilation. And you saw some of this, for those of you who were in the compiler talk this morning, you saw actually screenshots of how to configure this.

But the basic idea is to define GCC as your default compiler, and this is the default on Jaguar in the prerelease seed that you have. On the April tool CD, because it's not a beta, the GCC295 is the default compiler, but the 3 compiler is there as well. So you can say use GCC3, yes, if you're older than on Jaguar. If newer, then you don't have to do that.

What you need to do in order to take advantage of this is to define a prefix file. So basically what we're doing here is we're setting up a prefix file, we're precompiling all the stuff in it once, and then every time after that, GCC can reuse the information in that, and thus saving a lot of time, right? It doesn't have to read and parse all your headers again. So we need to define a prefix file, include your common system headers there that you're using, maybe some pound defines, and check a box that we'll see that tells Project Builder to precompile that prefix file.

And the third step in the current seed is to set the use GCC3 PFE support setting to yes. And you can do this in your target. You can set both of these in your target if you want. You can set them in a build style because, remember, we're asking not to deploy with GCC3 until we ship Jaguar.

So if you go ahead and set this in a build style, you can actually test, just by changing the build style, you can test your entire project with 295 versus 3. And we will be adding user interface for configuring this. So remember, GC3 is still pre-release in the CDs that you have, so I know you heard this before, but don't ship anything built with it until Jaguar.

So Project Builder also has some features that are not as well known, but they let you add finishing touches. One of those is versioning. You can add automatic version numbers to your products, like an application. And we have built-in support for something called Apple Generic Versioning. And this is what we use internally, but you guys can use it as well. And the way you do this, this is all documented in the release notes.

But the way you do this is to set up the versioning system to be Apple Generic and to set a couple of special build settings that are, if you go to the Help menu and you go to the release notes, there is optional integration with CVS. There is a tool on the system called AGV Tool that will let you automatically bump the version number and check in the project file with the updated changes, et cetera. Kind of handy.

Another thing that we don't have direct support for but that is easily accomplishable is to run the GenStrings tool. GenStrings is a tool that's installed with the developer release, and it regenerates your localizable strings. So if you make changes to your localizable content, you want to rerun this tool. And you can actually set up a legacy makefile target, a legacy target to do this. And instead of make, you just have it invoke GenStrings, or you have it invoke a script that runs GenStrings on your project.

A third topic that I'm not going to get into in great detail, but it's also documented in the developer documentation, is scatter loading. I just want to kind of point it out so you're aware of it. There are facilities to reorder the code, the order in which the code is in your executable, in order to make it as efficient as possible at runtime. So the idea is that you put code with related functionality together so that you make use of VM pages in a good way. Bye.

And Project Builder has some support for this also in the docs. And another thing that comes up a lot is embedding of frameworks. So if you ship an application, you may not want to have-- and you rely on some frameworks. You may not want to have to install those frameworks onto your system because that can make things fragile. So one reason is simpler packaging.

So the user buys your software, inserts the CD, and gets one app icon that he can drag onto his desktop, he or she, and doesn't have to install, you know, 50 different frameworks in 50 different places. So the idea here is to take the framework and actually put it inside of the app wrapper. The second--one second benefit of this is, of course, robustness, that if the user moves the application or copies it over to a different volume or whatever, the frameworks automatically come with it, and they don't have to be handled separately. So just a nice user experience.

Of course, there are alternatives to this. One is shared source code. And the reason you may want and may not want to do that is because then you have to recompile the source code every time. If you have 40 frameworks, you make a change to one of the frameworks, you don't have to recompile the other stuff. You just work on it separately. The other thing is that you can group related functionality together and increase code reuse.

It has to do with how you layer your app, but often what you want to do is, if you have plug-ins, is to expose certain API, and it's very convenient then to use a framework to expose that API to have your plug-in link against the framework, and your app also links against that framework. And one other reason is that if you do it this way, you can separate out your products into more logical components. Of course, frameworks also let you package headers and resources and even documentation in a much nicer way than a static library does, so that's really encouraged.

So how do we do this? Well, to do this, currently what you need to do is you need to tell the application that instead of looking for the framework in a specific place in the file system, you have to tell it to look relative to the executable. And the way this is done under the covers is using a special path, at executable under our path. And you see the at executable path dot dot frameworks there. So the dot dot is to get out of the Mac OS folder that's part of an application package. You don't really need to know the details of that, but this is the form the path will take.

And frameworks is then the subfolder of your application where the framework is put. We also need to set skip install equals yes. And what that does is to prevent Project Builder from actually trying to install that onto your system because you have now an installation path. We are working on making this a little bit easier to do and to have this be set up automatically.

The second step after the framework is set up is to set up the application. So now we set up the framework so that it knows how to tell the application to look relative to the application. Now we set up the application so that it actually copies in the framework after it's been built.

And to do that, you use a copy files build phase. It's a fairly generic build phase that you can add to your target. And in this case, we're using it for a framework. At this point, I'd like to bring Christian Molick up to help me with a demo.

So we have here a simple application that I wrote this morning, actually. It's an app and a framework in the same project. And it's a very simple app that just has a button that shows the path of the framework. So what we're doing first is we're just going to build and run this and just see what it does here. Gratuitous use of metal.

Don't do this. So here we just show the -- we ask the -- we have code to ask the framework for where it lives. So in this case, it lives in our shared products directory. We set up a shared products directory to volumes, to WWC demos symbols, right? So that's where all the products go. So just go ahead and quit that. And then what we're going to do now is to set up the framework to prepare it for being embedded into the application. So let's go to the framework target.

and if we go into the target editor, under the build settings, we see it's set up not to install at all. So what we want to do in this case, though, is we want to install it, but we want to put it inside of the app, not in the system path. So we're going to go to enter executable_path/... to get us out of the Mac OS subfolder, and then into the frameworks subfolder, which is inside of the app bundle.

And if we just do this, Project Builder will try to create this path in the file system. So what we do is to scroll down and to set a expert build setting. Skip install equals yes. And again, we're working on making this a bit simpler. So now we set--it's pretty simple still, though. Now we've set up the framework.

That's all we have to do. Now the framework is set up to be launched-- or to be found from the application relative to the application. But we also have to tell the app to embed the framework. So Christian's gone to the app target here. We add a copy file build phase. Thank you.

we're gonna set this subfolder to be the Frameworks folder. And then we're just gonna find under the Files and Groups tab, there's a product for every target that generates a product. And they show up in red 'cause we haven't built it yet, so just gonna drag the framework in, and that's it. It's clipped here 'cause the font's a bit big, but, um, that's it. So now we need to make sure that the application indeed depends on the framework. It already did, because that's how the app was set up. And we can go ahead and build again.

And this time, the framework's built separately, the application's built separately, and then the application copies the framework into itself. So now we see that the products have been built, and we can actually-- we have a context menu that has a Reveal in Finder item, and we can actually use that to take a look at this to see if the framework actually got copied inside. So we're gonna do that. One moment.

There we go. And we see, okay, so let's open up the application and show the package contents. And we see that under frameworks, the framework is actually copied now. So now if we run this, we can run it right here from the finder. And we click the button this time. We see that now it picked up the framework from inside of the application's contents frameworks directory. So nice way of embedding frameworks inside applications. Okay. Thanks, Christian. You can have the slide, please.

So at this point, I'm going to ask Christian to come up and continue with the next part of the preso. Thanks, Anders. So now that we've added some finishing touches, let's talk about building the product. Now, development builds are a bit different from deployment builds, and I'd like to go through a bunch of why that is. We could go into a lot of detail. I'll just be humming right through this.

First of all, compile optimization and macros are going to be very different. Usually when you're developing, you want to avoid optimization or have minimal optimization so that your debugging experience doesn't get messed up and so that you can see as much of your code as possible. You may also be defining your code such that there are macros that define what actually gets built. You may have extra debugging code, or you may have extra code that gets built only for your deployment product. You want to make sure that this is dealt with when you compile for deployment.

In addition, you want to pay attention to symbol editing and stripping. By default, you're going to get a whole bunch of symbols in your binaries, and very often you don't need any of these symbols or just not most of them. So you want to be careful to trim down the symbols in the binaries that you deliver to the minimal possible level.

primarily this is for application developers so that you don't actually vend more functionality than you intended to and get yourself into a trap. But it's also a very important performance point because all the symbols actually enlarge the executable and particularly for dynamic libraries, all of the symbols are going to be shifted around and loaded when they may not even be necessary.

And of course stripping is very important. Having extra symbols, debug symbols in the binaries you ship is no good. You want to make sure to avoid non-deployment files. There are a bunch of settings that affect Project Builder builds. Many of them can cause intermediate files or stuff you just don't want to appear in your deployment builds, and you want to make sure that none of that is actually getting shipped out to customers.

You also want to be careful of ownership and file modes. We've got the power of Unix now in OS X, and that means that there's a lot of file ownership and mode settings that you can give to files that will make them unusable or unaccessible in ways that aren't immediately clear when you're first testing them. So you want to be very careful that you've got a standard set of ownership and file modes for your deployed products.

Finally, you want to pay attention to your distribution folder layout. Now, ideally, in the cases we're showing, you've got a package and an application inside it. It's all very simple. But for more complex products, you may have a layout with various resources, alternatives of the application, and you want to be very sure that these get in the right folders and are all making sense in the final thing that gets shipped out. So talking about these in some detail, first of all, the compile optimization.

It's very important that it can interfere with debugging. So if you're getting very strange results while debugging, you're having trouble stepping around, check your optimization settings to see if you may have optimized your code to a level where you can't really debug it anymore. Now, when you're deploying, you want to make sure to be using optimization, because if you don't compile with optimization, your code could be very slow. Currently, we're recommending for people who are using GCC to use OS, which optimizes for size.

The actual size of the binary is one of the biggest variables in terms of determining its performance. If you can save a few pages, even if the code is a little less efficient, you may actually have much better performance. Similarly, you can have your other macros in here that define crash risk or alternative algorithms or such.

So with editing exported symbols, you're going to want to do that. You're also going to want to make sure that your symbols are stripped from all your products, and in particular where this gets interesting is when you have embedded products. So what we're demonstrating here is an application with a framework inside of it.

We want to make sure that that framework gets stripped. This is an interesting point because the semantics for doing this have actually changed with Project Builder recently. In the past what we did was we assumed that during a build, all the products that are being built are just being built raw, and so when embedding actually takes place, we have to search through every embedded content, look for any files that are binaries, and make sure that they're stripped then.

Now the new model which Project Builder is using is that when you're building for deployment, binaries are stripped right away, as soon as they're produced. So we don't need to actually strip embedded content over again. We've got a different set of settings that apply to that. So it's really important to pay attention to this step and make sure that your embedded content also gets stripped.

Non-deployment files, there's a bunch of different kinds. Intermediates are the most common that can poke into products. I'd like to highlight also the development property list. Project Builder writes a PB development plist to keep track of what's going on with the product. The idea is to enhance the debugging experience by allowing PB to know where the product came from, exactly what project produced it, and so forth. It's very important to avoid having this plist in your deployed products if you can avoid it.

And some procedures for doing this. These are very basic, but it's clear looking around there that not all developers are doing this. You definitely want to clean your builds before you do deployment builds, and you want to check your build results all the time, because there could be files which got in that last build which you really don't want to ship to customers. I want to review standard file ownership and permission settings that we're recommending for Project Builder are root and wheel for system content, root and admin for non-system content.

Very basic. You want to make sure that you don't ship things that aren't actually readable by your customers, aren't executable by them, and you want to make sure that files that aren't meant to be written can't be written so that you don't end up with accidental destruction of a product that you've shipped.

And finally, just to highlight the distribution folder layout, in general you may have a structure. In particular, distribution routes often have a structure where the route of the distribution route represents the system route. So if you've got something installed in user local, you'd have a user local in your distribution route with the content in there, and that allows you to specify exactly where in the installed file system files need to go.

So how does this get done? There's a few steps to it. One is the build actions, which we're calling out. This is something of a deep subject. I'm only going to touch on a few bits of it. But when you're building, we're not always just building from the IDE. You can see we're building and we're cleaning. We can also install and do a number of other things. These are build actions.

Now, primarily what these controls, they determine the default values for build settings, a whole range of settings. In fact, the entire build system is really doing much more than processing settings. All the paths that point out files in a project are just settings. And so how these default values change can be very interesting.

At this time, it's the case that with PBX build install, you're actually going to get some significantly different default values for settings than you get with a build, PBX build build, or a build from the IDE, and recommending that for when you're deploying targets, what you want to do is actually build them as root from PBX build with PBX build install, because that will give you all around your best deployment set of default values.

It also determines the build process. This is again a tricky bit because the semantics in PBF changed here recently. It used to be the case that the build model was that a build would happen, and then to get a deployment, you would do an install of that build, which would copy it to its installed location and do post-processing: stripping, setting the owner, the mode, and so on.

This model is good for some cases, but it tends to break down. In particular, we just noticed that the compile options you're going to want to use are different for deployment and development builds. So in this case, for a deployment build, you can build it and copy it over to its location, but because that build for deployment isn't really built the same way that you want your development builds built, there's not really a whole lot of reason to build it first and then copy it.

So what's happening now in Project Builder by default with Jaguar is that products will get built for deployment directly into their install locations and will be immediately stripped, have owner and mode set. So the process has really changed here. And it's worth calling out that the Actions Clean and Install Source, which are supported now, are very special cases. In particular, they don't have build phases like the other builds do, or at least not yet.

So how do you do this? It's with build styles for deployment. Anders really described this in most of its detail, but build styles determine how targets get built rather than what a target is building. And build style settings override target settings. So we could just see that. I'd like to get Anders to show one. If I could get the demo screen, please.

So every project that you make with Project Builder comes with a couple of default build styles. We're going to take a look at the default deployment style. Now, the first thing that we want to add is the setting deployment post-processing, yes. This is a sort of master trigger. It's going to cause the products to be built directly into their install locations. It's going to cause the ownership and mode to be set. It'll cause the stripping to be activated.

This is sort of a master switch for all of these variables. Now, currently, this has a hold over here. The copy phase strip is from the old process where we could never count on products having been stripped initially. So every time we embedded a target, we had to look for binaries in there and strip it. Now, this isn't a very efficient process, and with the new model, you can expect that all of the targets you're building are going to be stripped as soon as they're built. So we can actually delete this setting now.

You want to be careful. If you are including binaries that are built from other projects, you may need that setting when you're building your target. But if you're just using Project Builder now, you should have targets stripped automatically as soon as they're built. Additionally, we'd like to make sure that the optimization is good, so we're going to add optimization in C flags set to -OS so that we're optimizing for size of the resulting binary.

And that's really all it takes. That's a fully usable deployment build setting. Let's see if we can get a test build with that. And I'm not going to go ahead and run this. You won't see much of a difference in this application because it's so simple. But it is interesting that you can see it was going and recompiling all the sources there.

Thanks, Anders. If I could go back to slides. So there's building your product for deployment. But now that you've got that, you've got to get it out to customers. So let's see creating disk images and Installer packages. Packaging for distribution is a large area. There's a bunch of third-party tools that are available. And we strongly encourage anyone who's shipping a product to think about what's out there and their install process and how to make it most accessible for customers.

Primarily what we're recommending is disk images. Why? Primarily, they're compact and they're very accessible. With a disk image, you can take a very complex product that may be using resource forks and other HFS+ technology, and you can put it all in a single file, and it'll be represented accurately there. It'll also be compressed very efficiently. They're also very accessible. There's no need to get Installer technology or a new version of disk copy because all this is built into Mac OS X. You just double-click on a disk image and it gets mounted and you can see it.

Another big plus of disk images is that they can do simple installation processing. Currently, a lot of people who are shipping code need to have their users agree to a software license agreement. With the disk images, you can have the software license agreement displayed and force them to agree to it before the disk image will actually be mounted and available to them.

Additionally, coming up in Jaguar, for the full release of Jaguar, there's a bunch of other simple installation processing that will be possible with disk images, such as removing the disk image after it's been used to actually install the product, to run the installer on a package that's inside the disk image, and a variety of other things like that.

I just mentioned Installer packages. There are some good reasons to use those, but it's mostly if you have special cases, in particular if you've got scattered files, files that need to get in particular parts of the file system in order for your application to work properly. It's really a pain to give users all those to drag around, and you can't rely on them to get it right, so the Installer packages will let you get scattered files all over the file system where they need to be. And also, if you need to do various open-ended installation processing, either prep the file system before you lay your application down or do something with it to make sure it's ready to run, Installer packages have the most open-ended support for that.

And I'd like to note here that you can do installation processing with both disk images and the packages. And so it's careful to think about what you're doing and why. It can happen that if you've got a software license agreement, you may accidentally cause the user to agree to it twice, which can be a negative experience.

So you should try to choose which ones you need and either put your post-processing on the disk image or in the Installer package or wherever it goes if it's not particularly visible to the user. So how are these things made? It's not entirely straightforward, but there are a few commands that get it done. First of all, the disk images are created with HDIutil. This will actually make a file which represents a disk, an actual device.

Then you have to make a file system on that disk image in order to store stuff there. And there are some variables for that. We can decide how big the file system is initially, what kind of compression we have on it, its organization. Once we've got a disk image with a file system on it, we mount it with HDID, very similar as to what's happening when you double-click on a disk image from the Finder.

You can populate it using any commands. This is a big advantage, too, because there are a lot of different commands for copying. Depending on how you have your build process set up, you may have a clear and easy choice. You may want to use an archiving copy command. You may want to use Ditto, which is a maximally preserving directory-to-directory copy that's on the system.

Our example will be using CP, because it's very simple and accessible. Then finally, when you're all finished, you're going to want to call hdiutil again to get some compression on that image so that it's nice and tight. : And again, I'd like to -- it's going to be automated in a number of ways.

In general, your best bet is going to be using an alternate target because we can plug that into the dependents for the other targets in the project however we want. Another option is to use a script phase so that every time a target is built during that section of the build, the packaging will take place. We're going to be demonstrating an alternate target.

Get -- Demo screen. Thanks. So we defined a deployment build style last time. Now what we're going to do is set up the packaging. We're going to need a script to do this. So we're going to make a new file in this project and not add it to any targets.

And we have one created in the background. Anders is going to type this up magically for you. First up, we're going to actually define some variables that define what the image name is going to be and what its full location will be. Now we remove any previous image that might be in place. You can't create a disk image on top of another image, so this is an important step.

HDIUtil is used to create the image itself. Here we're giving it an initial size, which isn't very important. The disk will actually contain what is put in it, so you're not creating a maximum size for the image here. Or you're creating a maximum size, but not the true size of the image.

Here we're getting the device of that so that we can then go and create a file system on it using a Nufis call. This will actually build an HFS+ file system on the disk image. Now we eject it, that unmounts it, so what we have is a file all contained by itself, which represents a disk with an HFS+ file system on it. Now we go and mount that writably, much like the Finder would do as if we'd clicked it. Wait for four seconds just to make sure it gets mounted.

And now we can copy our product onto it. This is a simple CPRP that we're doing. This should preserve just enough that the framework inside there lives. And now we eject it again. That'll unmount the copy. And now that it's all finished, we're going to copy it aside and do compression on it. And that's it.

So saving that, to get it active, what we're going to do is make a legacy Makefile target. But instead of calling Make, we're going to actually just call the shell script. We're going to give it a name. Because we're using the product name as the disk image name, we need to give it a name that's a reasonable name for the distribution.

And as an argument, we're going to give the name of the file. So there it's set up. Now what we need to do is make sure that the target is properly placed. The first target in the list is the one that's going to be built when we build the project from PBX build externally from the command line. So we're going to make that the first target so that if this is built from the command line, what we're going to do is we're going to get the fully packaged application.

To make sure that happens, we're going to actually have to drag the application target up to the product image target to make sure that gets built so that we have something to put in the image. Now if we make that target active and go and build it, we're also going to want to make the deployments build style active as well.

Note that. This should give us a full-blown deployment build of our demo app. So now it's built the app. It's creating the disk image now. The file system is copying and the compression goes very fast. So now if we can go and look at the build directory where that will have shown up.

So you can see it popping up on the desktop there. And there's the application, which can in fact be run directly from that compressed image. So now you can see that the framework that we're getting is in fact the framework from the application inside the compressed image. And of course to install it, all you have to do is drag that application to wherever it belongs. Great. Thanks Anders.

[Transcript missing]

I wanted to leave a little time for Q&A here for PB, but to recap some of the things we talked about in this session, we've seen some ways in which we can streamline the build process. You can set up a PFE file to make GCC3 build faster. You can use build styles in order to customize the build, both in terms of what gets built, where it gets built. You can try out new algorithms, things like that.

You can set up execution contexts to pass different parameters to your program. You can, even if you have a plug-in that could be loaded that conforms to some standard plug-in API that could be loaded by three different apps, you could set up three different execution contexts, one for each app, and test your plug-in with that. So it's fairly flexible.

We've seen some ways of polishing the product. You can add versioning to it. You can embed frameworks inside of applications, and this is something we encourage you to do if your app is one that lends itself to drag-and-drop installation. This is really something we encourage because users often don't want to have to deal with installers and having to figure out where all the different files get placed. If you have a single app that can be drag-and-dropped into the applications folder, that's a very useful thing. We have seen a little bit about how you can build for deployment and take advantage of, especially taking advantage of build styles for that.

talked a little bit about packaging the product. In this example, we used the command line tool for creating a disk image. You can, of course, also do that using disk copy itself, but that's a manual process. And so you can fit this into like a nightly build that produces a disk image in the morning that's ready for--that has the latest build of your product ready for installation.

And so now we've talked about some of these things, and so hopefully this will help you to ship it. So again, keeping in mind not to use GCC3 until we ship Jaguar. So what I'd like to do now is to ask Advoji Georgi, the technology manager for developer tools, to come back on stage and help us with the roadmap and the Q&A. Thanks.

Thank you, Anders and Christian. Great stuff. More information. You've seen these slides many times during the conference before. The Apple Developer Connection Tools page for extended information about all the tools available. The specific Project Builder page. And the Apple Connection Downloads for where you can get updated versions as we release the tools on a quarterly cycle. We also have the bug reporting page listed because we do want to hear your bugs. We do want to see your experiences with Project Builder and all the tools so that we can address them.

Roadmap, we're getting close to the end. The session immediately following this one is the feedback forum for development tools in room J1. And then the final session of the week, debugging in Mac OS X back here in this hall. And with that, if I can ask the Q&A team to start coming up to the stage. Contacts for tools, contacts for Project Builder. I'm always available to talk to you about opportunities and issues with Project Builder, how it will affect your development.

We have the mailing lists, lists at apple.com, where we have mailing lists for Project Builder, Carbon development, et cetera. Project Builder users is the one that's specific to the Project Builder use. And, of course, the development tools engineering feedback mailing address. I hope you've copied that down now through the many sessions I've showed it to you. That talks to the internal people at Apple in charge of the team.