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: wwdc2001-703
$eventId
ID of event: wwdc2001
$eventContentId
ID of session without event part: 703
$eventShortId
Shortened ID of event: wwdc01
$year
Year of session: 2001
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC01 • Session 703

Project Builder In-Depth

Development Tools • 48:49

Project Builder is a rich integrated development environment for Mac OS X. This session covers the extensive capabilities of Project Builder, including advanced project editing, handling special build needs, and importing projects from alternative build systems.

Speakers: Mike Ferris, Anders Bertelrud, Christian Molick, Dave Ewing

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 Godfrey DiGiorgi. Good morning. I'm glad to see so many people were able to get out of bed on this third day of WWDC. How's the show for you? Doing good? Fantastic. OK, so this morning, this is the Project Builder In-Depth session, where we're going to take you into some of the more curious details of Project Builder and show you how to get things done. And to that effect, I'll introduce right away Mike Ferris, the manager of the Project Builder IDE development team.

Hello. So we have a lot of stuff to cover today. And so I'm going to go ahead and dive right in. Basically, we're going to try to focus today on some of the more advanced features in Project Builder, and we're going to concentrate on features of the build system. Project Builder does pretty automatic support for most of your needs in terms of the building of your project.

Every project, every real project is probably going to have a few things that fall a little bit outside the scope of what PBE handles really automatically. And so what we want to do today is talk about what features are there in Project Builder to let you do the kind of things that we haven't possibly anticipated or that aren't directly supported and automatic in Project Builder.

So small projects may be very simple. You create a project template. It builds. Everything works fine. But large projects often get more complicated. And an IDE has to be able to build your projects. The project templates get you started. You're going to add a bunch of stuff to that. We have to support you adding all that. And we also have to be prepared to let you get stuff done that we don't even know about right now. So there may be some new requirement that comes up in six months.

And if you can't get Project Builder to satisfy that requirement, you're kind of stuck. And when it comes to this future extensibility, the most important part is the build system because If Project Builder can't build your project, it doesn't matter what other features it has. So again, we're going to concentrate on the build system today.

This is basically what we're going to go through today. We'll start with importing projects and source code into Project Builder. This will give us a project that we can then use throughout the rest of the session to show you some of the more advanced features. Once we get the project up and running, we're going to talk a little bit about targets, and then start talking about some of the specific features that go along with targets in Project Builder.

Build styles, which let you modify the way that a particular target gets built. So if you want to have a target that builds your application, but sometimes you'd like to build it for debugging, and sometimes you'd like to build it for profiling, and sometimes you'd like to build it to put it on a CD and ship to your customers, you would use build styles to customize the way that the target gets built.

Build phases are sort of the basic building blocks of a target. So a target is basically a sequence of build phases. And build phases do different things to the files that they contain. And we'll talk a little bit about what that means. And then at the end, we're going to talk a little bit about legacy targets. And a legacy target is a special kind of target in Project Builder which basically circumvents Project Builder's build system altogether.

And so one common use for a legacy target would be if you have a project that's, say, an open source project and it has a make file, you can set up a legacy target that will invoke make to build the project instead of using Project Builder's built-in system.

All right, so let's get started on importing our source code. Basically, you have a few different ways to get started with Project Builder. If you're starting a brand new project, okay, great. You just pick a project template that's closest to whatever, you know, you want to end up building. And you start with that and you just start adding your code and writing it. And eventually you will be done.

But a lot of you all have existing source code. And so then the question becomes, how do I get all this code I already have into Project Builder and building? And we provide a couple different ways to do that. We can directly import projects from two different IDEs, from Code Warrior and from the old version of Project Builder called Project Builder WO these days.

The third way to get source into your project is that you can just directly import whole trees, folders full of source code, into Project Builder in a fairly automated way. And we'll show a little bit of that, too. So today what we're going to do is we're going to start by importing a Code Warrior project.

And to import a project from Code Warrior, you start in Code Warrior because you're going to have to basically export your project as an XML file, and then Project Builder can read in the XML file. Before you export the project as XML, it's important to set in your project settings for Code Warrior the little checkbox that says save project entries as relative paths. PB can import this stuff a lot better if it has the relative paths to the files. Thank you.

Once you import the project, Project Builder will automatically get from this XML the whole group structure of the Code Warrior project. It will bring over any targets that are in the Code Warrior project and convert them into Project Builder targets. Once it's all in there, you're almost certainly going to have to do a little bit of hand tuning of the resulting project before it is complete and buildable in Project Builder.

So the other thing that we're going to talk about a little bit today is importing just folders full of source code. You can just drag a folder into Project Builder from Finder, and Project Builder will offer to recursively import all the stuff inside the folder. When you're going to do that, it's usually the best thing to create the target that you want to use to build that source code first, because as Project Builder is importing all this stuff, it can automatically add it to a target. So if the target already exists, you can say, OK, add it to my new target. And as it's processing all the files, it'll figure out which build phase each file belongs in and put it in there automatically.

Once it's all in there, you probably have some more configuration to do on the target before it actually builds. So all right, let's get started with the demo. And to help me with the demo, we'll bring Anders Bertelrud onto the stage. Anders is a member of the Project Builder team.

So let's get started by importing our Code Warrior project. So the first thing we're going to do is fire up Code Warrior and open up this project. This is a sample project that you can get off of Apple's website. It's provided by the developer, tech services people, and it's a simple little application.

It actually ships with both a Code Warrior version and a Project Builder version. We've thrown away the Project Builder version so that we can show you how to do the importing. So first of all, let's go ahead and make sure that the checkbox is checked for the relative paths.

and once we know that that's all done, we can go ahead and from the File menu, just choose Export Project. And this is going to save an XML file. And we'll go ahead and put it in the actual folder that the project is in. So now we've generated this XML file. Okay, now we're done with Code Warrior.

So let's go ahead and get out of Code Warrior and go to Project Builder. and we can choose Import Project. And you get a choice of what kind of project to import, so we're going to import a Code Warrior project. And then we just have to point it at this XML file.

Okay, and now we're done. We can just go ahead and let the import happen. You'll notice that it imports and we get all the groups, so we can go ahead and check out and make sure all the files got in there. Okay. Now actually I'm a little bit lost on the demo script here, so let me... So now, when Code Warrior builds this thing, it's going to build a pef binary, and so it links against the CarbonLib libraries.

And we're going to build a Mac O binary, so we're going to go ahead and get rid of the libraries that came over from Code Warrior. And we'll add in the frameworks we need in a moment. But first, let's go ahead and look at the target that got imported. And you'll notice that in Code Warrior, this target was called something kind of funky, so maybe we should rename it to be something a little bit more reasonable.

And also, if you go to the Build Settings tab, the application that Code Warrior was generating has this weird PPC in parentheses after it. We don't really need that, so let's get rid of that. And okay, now let's actually go back to the files tab here and make sure that we are linking against the frameworks that we need. So first, okay, we have this Mac libraries group. Let's go ahead and rename that to be frameworks.

And then from the project menu, you can choose Add Frameworks. And we'll go ahead and find the two that we need. And this example uses Carbon and QuickTime. So we'll get the Carbon framework and the QuickTime framework and add them in there. make sure that they get added to the target.

And you'll notice that they appear there in the Framework and Libraries build phase of the target. So for this example, this is actually all we have to do. Now we're ready to actually build the thing. So let's go ahead and build it and make sure that it actually works.

Okay, there's Build. Go ahead and run it just to make sure. So this example, all it does is it takes a screenshot of the screen, it lets you scale it, and it actually lets you save it, which we'll show a little bit more of later. In fact, when you save it, it saves as a picked file.

and Interesting. So-- - Can also-- - That was not part of the demo script. - If that happens to you, you can actually kill it with a stop button. - Right, so. As shipped from Apple, this thing saves screenshots as picked files. And we thought, well, maybe it'd be nice to be able to save as a TIFF file. So in order to do that, first we're going to need some TIFF handling code.

So what I did is I went out to SGI's website, and I downloaded the free TIFF library that Sam Leffler wrote, which is sort of the standard implementation of the TIFF library. And what we're going to do now is actually import that TIFF library into this project so that we can build a library that handles TIFF, and then we'll make the app link against it.

So again, to get started when you're going to import a bunch of raw source code, it's best to create the target that you want first. So let's go ahead and create a new target. We're going to build a static library here, so we'll create a library target. Let's call it libhiff.a.

Now when the target gets created, why don't you go ahead and close the Build tab up there too so that we can see more. It has no files in it, but that's okay because we're going to add the files right now. Actually, before we add the files, let's go ahead and look at the Build Settings tab of the target.

and make sure that everything is okay there. So the thing is going to be named libhift.a. And actually, let's go ahead and set it to install in /applications. Not the library. You know what? You're right. and Never mind. So, did we skip that step? Let's go back to the snapshot target actually and do that.

So this illustrates that even if you make a mistake when you first start, you can always go back and change it. So, all right, there we go. We're gonna install the application in /applications. And, okay, so now let's go back to the TIFF target so that we can see all the files as they get imported.

And we'll switch to the File tab, and then go to Finder. and Let's group those together. That's a good idea. So we'll go ahead and put all the source code for the snapshot stuff into its own group so that it doesn't get confused with the TIFF source code.

Now we have a library, or we have the folder with all the source code here in Finder, and we can just drag that in. You get a few options here. Let's go ahead and have it copy that source code into our project and we'll tell it to recursively import all the contents of that folder.

and we'll add it to the lib tiff target that we just created. So all that stuff comes in and you can see that it's all been added to the build phases here. We have actually made some minor modifications to the source code we got from SGI. The only thing that we've done is we removed some files which are used only for other platforms, just to avoid having to get rid of them once we've imported it here. Now we have a target that builds the TIFF library. And let's go ahead and build it, just to make sure.

So we make the active target be the new TIFF target and go ahead and build. Now this is actually going to take a moment because this library has a lot of files in it. We'll see that it does have some warnings. If we were going to be conscientious about things, we might go in and fix those warnings, but we'll let that be for now.

So, still building. If you did want to fix the warnings, of course, you can just click on the lines and go to the code and figure out what's wrong. So the build's done? The build is done. So, okay, let's go ahead and close up that build tab. The last thing I'd like to show in this segment of the demo is we'd like for the Super Snapshot application to link against this TIFF library. So, to do that, we can go back to the target for Super Snapshot.

If we go back to the file space again, the products group is sort of special. That has a reference in it to each thing that is built by your project. So every target you add will typically cause something to be added to that products group. And you can see that we have two things in there, the application and the library that we're building with the lib tiff target.

So one of the reasons why this is available is so that you can actually establish linkage between the different target products. So to link against the lib tiff target, we can just set the active target to be the snapshot target and then click in that left hand column. And that library will be added to the snapshot target in the frameworks and libraries phase. And when we build the snapshot target the next time, it will link against the library.

Now one more thing that we actually should do just to be clear. And be complete. Is in the targets tab, we can establish a target dependency so that every time we build the snapshot target, we'll make sure to first build the tiff library. So in case we didn't build the tiff library first, we can still link against it because it will get built automatically. So now we have a complete project here, and we'll use this as the starting point for the rest of the demos in the session. But now, let's have Anders talk a little bit about build styles. Okay. So let's go back to the slides. Thank you, Mike.

So if we could have the slides back on the screen, please. I'm going to move the mouse pointer a little bit here. Okay, so now we have a project that's had the sources imported into it, and so we can build it. And what I'm going to talk about now is a feature we call Build Styles. And this is a feature that we added to help you maintain your project in the long run.

So what is build style? Okay, so the basics of a build style is that it allows you to build a single target or a set of targets in many different ways. So if you have one logical product that you want to build, let's say one application, but you might want to build it for profiling, for debugging, you might want to try it out using a hash table or a linked list algorithm, whatever. You wouldn't want to set up lots of different targets and have all the same source files in all those targets because then as you maintain them, if you add a source file, you have to remember to add it to each of those targets.

If you change the build setting, that should not change between the targets, you've got to make the change to all of them. So a build style is just like a filter that gets applied on top of the target settings in build time. So here are some examples of that. You can enable, disable features, experiment with different algorithms, different optimization levels, etc. Okay.

Okay, so how does this actually affect the build? Well, the basics is that a build style, it changes the settings of the target dynamically. So it doesn't actually modify the target, it just allows you to pick a different set of settings to apply on top of them at build time.

And a target's build settings, like optimization level and what flags to pass to the preprocessor, that's just really a dictionary of settings. And so even if you check a checkbox or choose a menu item from a pop-up in the target editor, what you're really doing is just changing the contents of that dictionary.

So a build style just selectively replaces or appends to some of those entries. So we see an example here, debugging symbols equals no, that would replace the setting that was defined in the target. If a build style has a plus equals, that means that it actually just appends to the value of the setting in the target. And one very useful thing is that one build setting can refer to another one, and that's a very useful thing. So a build style can refer to another one, and using syntax that's fairly, should be fairly familiar to those who have experience with make.

So you can say A equals dollar B, for example, right, to refer to the value of the build setting called B. Now, obviously the build style can refer to the target settings, but also the target settings can refer back up to the build styles. So it's actually fairly flexible, and it's possible to configure your settings to do a variety of interesting things. The one thing that's not permitted is circular reference.

So if you're using a building setting, you're going to have to do a lot of circular references, right? You can't define a build setting in terms of itself, because So since we have these different layers of settings, the targets, the build styles, we need a precedent for that.

So here's a summary of the precedents. The very highest level are the settings passed to the PBX build command line build tool. Now if you're running the IDE, there are no PBX build settings, so that part just goes away. But this is also intuitive to those using Make. Anything you pass on the command line to your invocation will override anything else.

Anything that's not defined there, the build system looks in the build style that's in effect. And if it's not there, it goes on to the target settings, etc. So by using this precedence, you can set up some really interesting configurations that let you just switch the build style and give very interesting behavior changes.

And, okay, great. So now we've configured the build styles, but how do we actually use them? Well, currently the IDE has a pop-up that you can put in your toolbar using the customized toolbar command. And that's a pop-up that's very similar to the target selection pop-up, the one that chooses the active target.

This one sets the active build style, and the IDE currently always has one build style active. So you can pick any one you want, say development or deployment, and just when you click on the hammer, that's the build style that gets used. You saw that in the demo.

Actually, sorry, you saw that for the target, but it works the same way for the build style. You'll see that in the next demo. Now, the PBX build command line tool is a little bit more flexible than that. If you don't specify any build style, then none of the build styles have any effect, and the settings defined in the target are the ones that get used. But as we see in the second example here, you can build for install, for example, and you can specify by name the deployment build style. Now, you can call that anything you want.

So you could add as many of the build styles that you want. And the last example here just shows that the active build style that was set in the target, in the project, is a per user setting. And so you have access to that from the command line if you use PBX build. So you can just say, the last one says, use whatever build style was active in the IDE when I edited this project. Can be handy.

And by default, new projects get two build styles just to start you off. There's deployment and the development build styles. And so development is by default set up to enable debugging symbols and to let you basically have a debuggable build. The deployment one is when you want to build it for putting on a CD, for example. So that would turn off debugging symbols, have a higher optimization, et cetera.

But you can add any number of build styles to your project. So you could just define anything you want to. We're going to see in the demo definition of preprocessor macros. Alright, so I'd like to invite Christian Molick up onto the stage and we're going to do a little demo. Hopefully I'll remember the script.

Okay, great. So first of all, what we're going to do is we're going to configure the targets that we have, the two targets, Super Snapshot and LibTIF, to turn off debugging symbols because we want the default case to be built for CD in this case. So Christian's going to open up both of the targets here and we just uncheck the generate debug symbols checkbox for each of those.

So now if we build without any build style at all, then we're just going to build for putting on a CD. So now in order to be able to set the active build style, we actually want to customize the toolbar here. So we want to go ahead and do that.

Just go ahead and control click on that, say Customize Toolbar, and just drag up the Build Style. Active Build Style pop-up, just drop it in there, and click Done. We don't put it in there by default because we want to keep the UI and the concepts a little bit simple when you first start out. So, it says no Build Style since we don't have any defined yet, so let's define some Build Styles. So, let's go ahead and go down to, yeah, Build Styles and create a new Build Style. Let's call this Development.

and if we click on that, the development build style, we can edit it. Now right now we don't have any graphical UI for any of the settings. We're planning on adding that, but this gives you control over the exact dictionary of settings that are available. Let's go ahead and add one that's called Debugging Underbar Symbols. And so you just click in there and hit return and that adds a new one.

and you just tab between the fields. So debugging symbols, let's set that to yes, because we're doing development. And let's add another one. And this one is going to be other C flags, which is just a bucket where we can put any other C flag we want to pass to the compiler. Actually, C flags. Other C flags. Yeah.

Yeah, so just double click on that. Right. I got it. Others and bugs. And we can set the value to be -D Debug. So this is just going to define the debug preprocessor macro. So now if we click on the equals sign there, you'll see it turn into a plus equals. Maybe you don't see that, but it's a little bit small, but you see that when you sit in front of the screen. And what that means is we're just going to append the value to the end of the value that was defined by the target.

Okay, great. So now we have the development build style set up. Let's go ahead and create a deployment build style. And to start off, we're just going to select all these settings here. Just select them both, and we're just going to copy them. So you can actually copy and paste these settings between the different build styles. Let's go ahead and create a new build style called deployment.

Actually, I take that back. Let's call that Save as TIFF because we imported the libTIFF library. And so one of the things we want to demonstrate here is defining a preprocessor macro that causes the source code to use the TIFF library. I've actually modified this Super Snapshot project to do that. So let's go ahead and paste in the settings from the other build style. And all we want to do now is just add to the value of other C flags, dash capital D, save as tiff.

Okay, so now we have defined our two build styles. We can see that they showed up in the pop-up menu up in the toolbar. So we can set which one is active. So let's go ahead and set the development one to be active. Go ahead and go to the files menu or files tab and click on supersnapchat.c. So this is the file in which we've added some pound if defs for save as tiff and for debug.

So debug causes it to print out some of the files. Save as tiff causes it to use the tiff library when you choose save. Let's go ahead and just save this file, make sure it's dirty, and hit build. So now we're building using the development build styles so the debug preprocessor macro is in effect. And so if you run this, and if we choose Save, then we should see some debug output.

So just go ahead and save that. And we see that it's writing a pic file. OK, great. So let's quit that. And then we're going to go ahead and choose the other active-- the other build style from the pop-up menu. So now we want to build this using the algorithm that uses the lib tiff library. So we just go ahead and build again.

Okay. So it looks like this machine is not configured exactly the way the other one was configured. Okay, we can either spend a lot of time and install libraries here, or we can say, trust us. So you see the, if not defined, save as TIFF there. What's happening is that we're apparently using a quick drop call that is not in the public headers. That's my fault. So the point is, though, that because we got this error this time, you're seeing that the different build styles are in effect. And in fact... Right?

Which was the point of the demo. So, successful demo. OK, at this point, I'd like to invite Christian to talk some more about the build phases. Here you go, Christian. Which is another feature of the build system. Can I have slides, please? So what I'd like to talk to you a bit is about how Project Builder organizes builds of individual targets into build phases to make it easy to see and modify what's actually going to happen during a build.

So they seem a little bit complicated at first. They're pretty simple actually, though some fairly difficult and dangerous things can be done with them. Basic idea is that a target is built in a series of phases that do happen one after the other. New phases can be added or deleted to tune exactly what's gonna happen during a project build.

New files, when they're added to a project, to a target, get added to the correct phase automatically. So phases don't, you don't need to be conscious of them normally. You can just see your files where you expect them and if you need to tune a build process, you can go and touch them in their phases. So files can be added to or removed from individual phases, moved between phases, or within a phase to different locations. So the files will be processed in the order they appear in that phase, as well as the phases themselves happening in order.

So standard build phases that you see in target templates or in distributed examples are a headers build phase, which is used for copying headers that are part of a distributed project into place. Currently, some extra work is done during headers build phase to make sure that those headers are available to other targets that you might be building or other targets in other projects that you might be building simultaneously.

Next is the bundle resources phase. In this phase, all of your bundle resource files get copied into their appropriate localized locations, as well as files that Project Builder is responsible for generating, such as the Info.plist property settings file and the package info file that goes in the bundle, all get generated and copied into place during this phase. During the sources phase is where the bulk of the work happens. This is where new sources are derived from given source derivation and all your sources that are already present and the derived sources actually get compiled and put in order.

Then during the Java Archive phase, a hierarchy is constructed, which has all of your compiled class files as well as extra resources that need to be in any Java archives that get constructed. Following that is a Frameworks and Libraries phase. This is where the libraries that actually get linked to by a product actually are all listed, and this phase actually builds the final executable. Finally, the Resource Manager phase will actually go and add resource manager resources to a product, potentially on a resource fork.

So that's a good basis to start with, but it's often not enough. There are a bunch of custom phases that can allow you to tune the process in a bunch of different ways, the most basic being the copy files phase. This allows you to copy special product contents like readmes and other such into a product.

It also is the primary model that we use for product inclusion. So the way that a product that includes another product, such as an application that has plug-ins, works is that you add a copy files phase that refers to that product reference in the product section and brings it into the actual built product.

Finally, there's the script phase. This is the most general mechanism where, by default, shell is run, but really any utility can be run during a build. So this can be used, by default, shell is invoked, but C-Shell, Perl, AppleScript can all be used to do various things during a build. So those are build phases. It might be interesting to actually see these. And if I can get Dave Ewing to help me work a little more with this project.

So the first thing that I'd like to do is show you the actual phases that are in this downloaded example. You could open up the snapshot target and go to the files and build phases tab. So there they all are. One thing about this is we're not building this with a bunch of other targets, and the header isn't all that interesting for the application itself.

So let's try just deleting that phase to clarify what's happening during the build. That's better. So, more important is getting extra stuff into the build. Simple thing to start with first is adding this, a readme to this application, and I think it actually came with one that we could add to the project. - Okay, well.

Level up, oh, there it is. And yeah, we're gonna add this to no target to begin with. So what we want is a copy files phase added to this. Easiest thing to do would be to select the last phase and add a copy files phase from the project menu.

Then drag that readme into the file section. And we'd like to have this happen every time, so copy when installing isn't necessary. And that should go into the wrapper of the application. So if someone actually looks into this built application, the first thing they'll see, hopefully, is this readme.

Okay, so there's a simple copy files phase. Let's try something a little bit trickier. What might be interesting for this example is to actually distribute this custom TIFF library that we built so maybe someone else can get at saving his TIFF. So let's make another copy files phase.

and drag the lib tiff product reference into it. This isn't really useful to us when we're just doing normal development builds, so we're gonna do this only when installing, and we're gonna give this an absolute location. Because it's a library, we're gonna put it in user local lib, standard library distribution place. For a technical issue, this means we're building a route for distribution where we're gonna have user local lib and slash applications rather than just the drag and drop install application.

Presumably because we're including the library, it's for developers anyway. And actually, it would be nice to have the readme in any case, even if a build fails partway along the way. So why don't you drag that phase to be the first thing that happens? So even if the compilations don't go well, we're going to have a readme in whatever we end up with. So copy files phases are one thing, but more interesting are these script phases that are completely general. So let's add one to the end of the... Actually, it's added to the end. Thank you.

We've actually got a few scripts ready to go and some stickies, I think. The first one we're going to put on is an accumulating log, which will put in an entry for any given build that we do, saying exactly what got build and I believe what style was used for the build. This is going to use shell for this. And it's going to run with every build. Now let's try something a little bit trickier even still. Add another shell script phase.

And this one, what we're going to do is, on the case of install builds, when we're doing final builds for distribution, what we'd like to do is see them in the finder so that we can go and immediately check them out and see what the user would see just to make sure that they're right. So this is going to use shell to invoke an Apple script that will raise the install builds location in the finder for us so that we can go and take a look at this.

And because this is really only interesting when we're doing full builds, we're going to make this happen only when installing. So there's a bunch of custom stuff. Let's do a normal build in the PBUI of the application target Let's change our build style. Oh, right. Yeah, you're going to have to change the build style that works.

Now if we can show that in the finder. So what are we looking for? Let's see. There they are. Oh, there's the build log. Oh! So we created a build log. We did get a build log. Interesting. That's a start. Perhaps more interesting would be to actually take a look at a final deployment build, which will invoke all of these build phases.

So if you could bring up the terminal window. Ooh, and crank up the font. Oh, man. Big enough? Bigger? Big enough? There we go. All right, enough. - And I believe that's in the project directory, so if you do a pbx build install with dstroot set to slash install, slash build, whichever exists.

So this will do a deployment build in that slash install location. You can see those build phases sort of happening quickly in the background. And the finder did raise with a copy of our route. Inside the applications folder, you should see the actual built application. And if you use Control-Click to look inside that wrapper, we should be able to see that. Read me. There it is.

and David Farnes. With that, I'm going to turn this over to Dave, who's going to show us a bit about how to do legacy targets. Back to the slides. OK, well you might wonder why the Java debugger engineer is talking about legacy targets and you know what, I don't really know. But it turns out it's kind of fun because I get to show you how to package your final application the way we want you to package the application and that's in a disk image.

Okay, Legacy Target. Well, the basics of a Legacy Target are that they are used to invoke custom command line tools. As Mike said earlier in the talk, the most common thing you would do probably is use it to call out to make or something, maybe for an open source project.

But there's lots of other things you can do with it. There's lots of other build tools out there. being one of them. Well, you can also use them to create, to generate source files that are used in other targets, or to do some pre or post processing on targets.

and of course you can run anything from a legacy makefile target, so to do just about anything. An example of some of those other things you might want to do well, package disk images. That's what we're going to do in this demo. You can also do build statistics, you know, log statistics at the end of builds. Or send out notifications after a build, like sending an email or something like that. Let's see, and with that, actually, we're going to bring Mike back up here and just show this. Okay, so we have the demo machine. Great.

Well, the first thing we're going to do is bring up the shell script that we built up for this that does the creation of the disk image. Go ahead and find that out in the finder and bring it into the target. We don't need to add it to any target.

Bring it into the project, but don't add it to a target. If you take a quick look at that. Why don't you close up the panel. No? So I don't want to go into detail in here. There's a few commands that are sort of interesting. You can find documentation on the system for, with man, I believe. Man pages.

But HDI Util and HDID. And there's also makefs underscore HFS that actually creates the HFS volume inside of the disk image. There's an article on how to do a lot of this stuff on Stepwise, which I recommend. OK, so let's go ahead and create a new target, a legacy makefile target.

and we'll give it a nice name so that we know what it is. And let's go ahead and put this at the top. This is actually going to be the main target for the project because it does the final processing that's involved in building this little demo here. And go ahead and make the other targets depend on it. So. So now when we actually build that target, it'll make sure all the other targets are built first.

Okay, well now let's do the real work. Actually, the real work was in the shell script. So let's change the build tool here to actually be bin SH so that it does run a shell script. And we'll go over to our stickies and drag in the command line. Well, we're copying and pasting it.

And this command line, all it does is it's creating an 8 megabyte disk image. I was a little lazy writing the shell script, so I didn't actually compute how much space it would take. And it's going to name the disk image snapshot and copy in the application itself. So I think that's it. Shall we build it? Let's build it. You'll see down here that it's actually echoing some stuff about what it's doing to create this disk image.

Copy files. It actually compresses the disk image too, so you don't really have to worry about creating a disk image that's too large. Because the final disk image will be quite small. So we'll go actually to the project directory. Because that's where we decided to put the disk image.

And there should be snapshot.dmd. And double click on it. and it's mounting in disk copy. No surprises there. And look, there we have a disk image and an application inside it that you can just launch and run. And with that, back to Mike. OK. So let's have the slides back for a moment here.

All right, so we've covered a few things today. And I just want to sum up. Basically, Project Builder provides a number of ways to import code into Project Builder so that you can begin using it. If you already have an existing project in Code Warrior or in the old Project Builder, you can bring those in directly. And as we saw, it's pretty easy just to import a whole lot of source code that you got from wherever.

You know, the build system, we've tried to make it flexible. We've tried to give you all ways to customize the build process to do things that we didn't necessarily anticipate and to give you basically ways to solve problems that we haven't solved yet. Now, this is not to say that we're not planning on solving a lot of these problems. Eventually, it'd be nice if you didn't have to write some gnarly shell script and set up all this legacy target just to build a disk image, and I think we can expect to see Project Builder do a lot of these things more automatically.

The point is that until we get around to doing this, you're not totally stuck. So, that was the main point of the session today. And at this point, I'll ask Godfrey to come back on stage. And we'll go through a couple of these. These info slides and have a little Q&A. Thank you, Mike.

Pretty amazing stuff. I think we're going to get a lot of use out of Project Builder with you guys. Can we have the house lights up? We're going to start a little Q&A session while I talk over the information slides. These are our information addresses. The top one is our tools page. We list all Mac OS X tools available there. We have a special page for Project Builder. Project Builder pages include updates.

So as new things happen, as new details occur, as press events and other things come to the public, we put them onto that page. We also have a series of mailing lists that we host. The URL there is the master mailing list page. And the three Project Builder users, Cocoa Developer and Carbon Developer, are mailing lists that are in heavy use by our community. Can we have all the Q&A presenters up on stage, please?

This is the roadmap for sessions through the rest of the week. Starting at 10:30, we're talking about Java development tools over in room A1. And tomorrow, we do compiler technologies and Apple performances tools in this room. I hope to see a lot of you there again. And then through the week, debugging on Mac OS X Friday morning, very important. Our C++ frameworks group and our feedback forum on Friday. Hope to see a lot of you there.

And if you need to contact me or the engineering team, here's two addresses. My address, I'm the technology manager for development tools. Always interested to hear your feedback, always interested to hear what your needs are, what your product needs might be that need interaction with the team. And the Mac OS X tools feedback mailing list is a place where you can send product enhancement ideas, general questions that you want to go to the engineering team itself.