Apple Developer Tools • 1:02:13
This session highlights improvements in Apple's IDE that bring you significant advantages for Carbon development. We demonstrate the improved importer and compiler compatibility and how it makes it easy to import existing projects. We show you how to work with existing source frameworks and resources, and how to optimize your project for build speed and turnaround time. Topics such as Mach-O and system libraries are addressed. We also show you how Interface Builder can be used to create state-of-the-art user interfaces for Carbon applications and to set up Carbon Events.
Speakers: Chris Espinosa, Scott Tooker
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Good morning everybody, this is session 307, Apple Tools for Carbon Development. I'm Chris Espinosa. I've been with the Development Tools team working on Xcode specifically for the last six months or so. I've been working with Development Tools in specific since...
[Transcript missing]
There we go. Okay. What we're going to cover this morning is an overview of Apple Tools. You've probably seen three or four of these overviews of Apple Tools, but we're going to do it from a Carbon perspective this morning. We're only going to be talking about Carbon applications. The process of bringing a project, whether it be a project builder project or a Code Warrior project, into Xcode. Getting your code to build with the Xcode IDE and with the GCC compiler.
Some hints and tips for optimizing the build time and the turnaround time, how you can take advantage of the Xcode features. A little bit about Xcode support for Mac resources, if you have resource-based Carbon projects, which most of you do. And just a little bit about designing Carbon interfaces with Interface Builder. There are other sessions on Interface Builder, and there's a really great session on building a modern Mac application, which we'll cover using NIBS and Interface Builders later on that I'll point you to, but I'm just going to do a brief overview of that.
Now, I want to do the standard disclaimer here. I am talking about Xcode, and I am talking about Carbon. The fact that I'm talking about those two things does not mean that we are killing everything else that I'm not talking about. We are not killing Cocoa Development. We are not killing Objective-C. We are not killing AppleScript. We are not killing Java or EOF or anything like that. The fact that I fail to talk about something does not signal its imminent demise. I just want to make that clear.
So the tools you've already seen in a couple of sessions, the Xcode integrated development environment, and you've seen a lot of the great features of that, the CodeSense feature, the great indexing, the great workflow and navigation. It's a project manager and build system. It's got an integrated code editor and an integrated debugger. The debugger I'm going to show you tomorrow. We're just going to build today.
Interface Builder is another key tool. It's primarily a Cocoa development tool, but we are moving more and more to using Interface Builder as the principal design tool for Carbon. And if you want to get at certain new Aqua elements through the Carbon toolbox, the best way to do them, in some ways the only way to do that, is to use Interface Builder to design nibs in order to get at those objects.
And then there are some performance tools, and all these performance tools work with your Carbon applications. The Sampler Performance Analysis Tools, the malloc Debug Memory Analyzer, the Object Alloc Object Analyzer, that is primarily for Objective-C, and then the Chud Low-Level Machine Tools will analyze anything as long as it's expressed in bytes.
[Transcript missing]
Xcode loves Carbon. We are working very, very hard to make Xcode a great development environment for your application. We're making it easy to import Carbon projects wherever they come from, Project Builder or Code Warrior. It compiles Mac resource files, whether they be .r or .rsrc files, ties in with existing resource editors in a seamless way. It supports building nib files if you are moving to nib files in Interface Builder.
It's the best way to use the new HI elements and the best way to use Carbon Events. And it supports combining Carbon and Cocoa in the same application. There are a lot of new APIs that we have that are Cocoa only, and you can get to them from Carbon using Objective-C++. And if you want to take your existing Carbon app and start using some of the unique and interesting Cocoa features, Xcode is the best way to start doing that.
So let's look at bringing a project into Xcode. There are a few simple steps. First, you need to make sure you have a Carbon application. If you have a Mac OS 9 application that's still based on Interface Lab, first thing you've got to do is Carbonize it before you can bring it into Xcode. Because Mac OS X applications must be Carbon to run in Mac OS X native. And if you've got a 9 application, Carbonize it on 9 first, and then you can bring it into Xcode on Mac OS X.
Then you need to bring it into Maco. Maco is the code format for Mac OS X. See the description for the Mac OS X application. The "CFM" is for Mac OS 9 and for Classic. If you're going to be building a Mac OS X application, we really strongly recommend you move it into the Maco format to take most advantage of Mac OS X and to take most advantage of Xcode. Most of the rapid turnaround features like Fix and Continue and Zero Link only work in the Maco format.
Then you need to adjust your build settings to get your project to build. Build settings are always very fussy, and working in Xcode is no exception. So if you move a project either from Project Builder or from Code Warrior into Xcode, you're going to be spending most of your time tweaking your build settings, making sure that you're building what you want to build when.
And then the last step is when you finally get your project building, you're going to have to look at your source code because the GCC 3.3 compiler has some differences from GCC 3.1, which Project Builder used, and it has some differences from the Code Warrior MWCC compiler, and you're going to need to make some changes in your source code in order to cope with that. In the demo we're going to do today, we're going to make exactly four changes in the source code to bring a large Code Warrior project over into Xcode.
So first step, carbonizing your application. I really shouldn't have to say this. We've been talking about this for three or four years now. Just the quick steps you should have done this years ago if you've still got a Mac OS 9 only, Interface Live only application. You isolate your Mac OS usage to just the subset supported by CarbonLib. You modernize it to use new APIs. You remove the linkages to Interface Live and start using CarbonLib or its stub instead.
We still have posted this tool that will look at your application and tell you what Carbon APIs you are using and not using that will help you make this transition. If you haven't done that now, do that now, and then come back at the end of the session and we'll talk.
The next thing is converting to Mach-O. If you have a project builder application, it's already Mach-O. If you have a CodeWarrior application, I recommend the best thing to do is to change your project from CFM to Mach-O in the CodeWarrior environment where it's familiar, where you've got more control over things, where you don't have to be changing three variables at the same time.
CodeWarrior does a good job of building Mach-O applications, so if you just go into the target settings panel and change the linker setting to Mac OS X PowerPC Mach-O, that will get you a Mach-O application, and that will start bringing in all of the changes you need to make in order to make a Mach-O application. If you have a very simple application that doesn't load shared libraries, it doesn't bring in static libraries, it doesn't call plugins, basically all it does is hit main and then run. There's very, very little to do.
It's just a binary loader format. If you happen to have something that uses a plugin architecture, if you do some dynamic loading, you'll have to migrate the APIs that you call in order to load those plugins from CodeFragment Manager APIs to the Mach-O APIs. What we recommend is to use the CFPlugin architecture in Core Foundation. CFPlugin is a way to dynamically load plugins that could be either CFM.
Or Mach-O, and what that allows you to do is maintain compatibility with existing CFM plugins, but also support Mach-O plugins as well. The only hard part is that if those plugins, the CFM plugins, happen to call back into your application and expect you to be a CFM application, that's a particularly difficult case.
If you want to come to one of the feedback forums or down to the porting lab or catch me afterwards, we have some techniques to deal with that. They just involve making a lot of... ...a lot of CFM glue that looks like a CFM link library in your application that calls in to the Mach-O. It's a tough problem, but a lot of people don't have it.
[Transcript missing]
The second thing you do is after you import is that you need to move from the Code Warrior style precompiled header mechanism to the Xcode style precompiled header mechanism. The two compilers have somewhat different mechanisms, and you're going to get no joy in anything until you deal with the headers. Because until you get your precompiled headers right, you won't get the speed advantages of Xcode, and you're going to get a lot of build failures, and it's not going to be fun.
The third thing is if you happen to be using the Power Plant application framework, there are a small number of changes you need to make in Power Plant for Power Plant to be compiled by the GCC 3.3 compiler and build against the Apple standard libraries. A very small number of changes. The Power Plant sources are really very clean, and the GCC compiler is really quite compatible. There are just a couple of changes you need to make, and we'll show you.
Then the fourth thing is you need to fix your target settings to get rid of some link errors and make sure that Xcode is building your project properly. And then once you build, then you need to make a couple of changes in the resource files in order to work with the developer release version of Xcode. We're going to get these worked out by the time Xcode 1.0 ships, but right now there are some things you have to do to the resource files to bring them in.
And then you get to work on warnings and errors, real differences between the compilers. Usually these are things that MetroWorks was lenient about, that GCC is stricter about. Sometimes it's things that MetroWorks supported or used in a different way that GCC interprets in a different way, often gray areas in the standards. For most mainstream standards-compliant C and C++ code, you can compile tens of thousands of lines without seeing an error.
So to do this demo, I'm going to bring up the useful and lovely Scott Tooker, who has put together-- An example of, he did the importer that imports Code Warrior projects, and he's going to take an example of a fairly interesting Code Warrior project. Thanks, Chris. It's a little bit of a misnomer to say I did the importer. I basically took an old version of the importer and made it work a lot better.
So, what I'm going to show you here today is we wanted to find a project that we would bring over and just show the whole import process, from importing to then going through and fixing all the problems to actually running the application. And so we picked Appearance Demo, which is a common Power Plant example.
And so just for those of you who have never seen it, which is probably not very many, this is Appearance Demo. So it's basically a showcase for all of the Power Plant widgets. And we thought this was a good example because it's small, but it also uses Power Plant, like many of you.
And we wanted to show that Xcode can work with Power Plant. You can run Power Plant, and it just runs and works. So let me put that. So the first thing we're going to do is launch Xcode. We're going to import the project. So you just say import code where your project.
Let me choose . And so you see here I have a path to-- unlike Project Builder, we take the actual Code Warrior project file. And also, you can change them if you want, although by default it's just the same. We also have this import global source trees. We support source trees now. So if you have source trees in Code Warrior, we can pull them over at the per app level. In fact, the importer creates a source tree to deal with the compiler relative paths you may have in your Code Warrior project.
So what we're doing here is we are using Apple Script to launch Code Warrior and then ask it, okay, I want an XML version of the project. Then we take that XML and we go scanning through it and find all your files. And because Project Builder likes to have all the headers in the project, it likes to be very explicit, we actually then -- wow. Sorry, I've never actually done it on a fast machine.
I thought I'd have more time. But CX code's really fast. But anyway, just to finish up, we actually bring in all that stuff. So by this time, what we're asking you is, OK, we want to know your encoding. I recommend that for the older project, especially older projects, that you just go ahead with the Mac OS Roman encoding.
Because that's probably what CodeWarrior was-- when you created the files, that's what CodeWarrior was using. So let's go ahead and start with the target. You'll notice that you get a native target. So we're not using the old project builder targets here. We're using the new native Xcode targets.
And the first thing we're going to want to do is set up the prefix header. As Chris mentioned, the precompiled support right now is a bit different from CodeWarrior. So there's some things you need to do to make it work well. So the first thing we're going to do is we're just going to double check and see what the prefix file is. Oops.
Of course, if Scott could type, life would be better. So as you can see, we bring over the prefix. header So it's appearance demo Mach prefix. And we actually add this to your target. So let me just move this out of the-- let's close this for a second.
And let me just find the prefix. So there it is. And so you can see it's right here. But if we go and try to build-- I'm not even going to try to build it, because what's going to happen, it's going to fail, because it's going to bring in MSL.
The importer by default doesn't bring over MSL stuff. So what we need to do is we need to replace this prefix file with one that doesn't use MSL. We want to use the system libraries instead. So what I'm going to do is trick-- is I'm going to fake out-- I'm going to fake out Xcode. Okay. And while Scott's doing that, if we could go back to the slides. Yeah.
[Transcript missing]
Let me talk about pre-compiled headers while Scott's putting that together. Code Warrior has a concept that they will pre-compile anything, a .h file, a .pch file. They'll even pre-compile C and C++ files. Anything you can throw at the compiler, they will pre-compile for you, either from a menu item or from a directive inside a file or from a special pre-compiled header target in a project.
What you usually end up doing if you want to have a different phase to pre-pre-compile your headers is you have like a library target that builds a null library with a name like "throw me away" later. And in the course of doing that, it pre-compiles your headers and deposits them in a certain location where other targets expect them. Well, Xcode works in a completely different way. It's really much simpler. You take your prefix file, and every target has a prefix file.
And if you check a checkbox, it pre-compiles that prefix file when it needs to for that target. That's all you need to do, really. You don't have to set up special targets and special projects to build it. The build system manages when your .pch file needs to be rebuilt.
If it needs to be rebuilt, it rebuilds it. If it doesn't, it doesn't. So it's pretty simple. All you need to do is figure out the content you need to have in your prefix file, put it in a prefix file. Put that prefix file into your settings, and then check the checkbox, and you've got pre-compiled headers automatically.
So if we can go back to the-- MALE SPEAKER: Yeah, so-- OK. Finder's being a little flaky, so we'll move on. So what I wanted to go over now is, actually, because this is a preview, we haven't had a chance to completely move over to all the new build settings. So I just wanted to go through a couple things that you're going to need to do manually that when we were doing this, we ran into and wanted to make sure you understand. The first one is the C language standard.
By default, currently it comes up as C99. Well, for older projects, we recommend that you set it to compiler default, especially if you're using C++. You'll get all these errors and warnings about, oh, well, C99 doesn't make any sense for C++. Another thing is that, for example, in this particular case, Code Warrior will force C++. Well, the importer interprets that as saying, oh, use dash XC++, which will force C++. But it turned out that they were all C++ files, so you can just get rid of that in many cases.
Also, the F exceptions and F RTTI options in the other C flags. They're just not needed because we turn those things on by default. And then finally, there is one kind of thing we're going to fix, but you have to fix now yourself, which is if you go To get your precompiled header to build properly, if you're only using C++, currently what we've found is that you're going to need to tell Xcode that you only want a C++ dialect. It actually turns out with our precompiled technology, because we have under the covers multiple different compilers, we have to say which dialects you want to. For the final one, we'll take care of this automatically.
For the majority of cases right now, you have to set it. And then finally, one of the new features you've been hearing about is Zero Link. Well, unfortunately, the importer didn't quite get the ability to set that for you automatically, but it's really simple. So I'm going to go through that now. If we just go to the project inspector and go to styles, so we just want to add one.
thing, which is let me find ZeroLink. It's under the standard build settings. You can just type in zero. There it is. And you just want to check that on. And notice I'm doing this in the development build style. If you haven't heard, we have these build styles that overlay our targets. The idea here is we only want to use ZeroLink when you're doing your debugging and you're developing.
When you actually go to make a deployment build, you want to make sure ZeroLink is off because we don't want you shipping apps that are not properly linked. So let me go ahead and we will build. So just to give a more detailed-- oh, the build failed. Why? Oh, of course. This is part of the demo. We expected a failure at this point. Yes. We expected a failure? We didn't expect this failure. Okay.
[Chris Espinosa]
[Chris Espinosa]
Yeah. So what we expected to be able to show you was that Power Plant isn't quite happy with... Let me try one thing real quick here. Let's just try to clean it. You're right. Why is it trying to do this now?
[Chris Espinosa]
[Chris Espinosa]
[Chris Espinosa]
Yes. So this is a power plant application, and the failure you were supposed to see was not the failure that we're going to address in three slides. Oh, go back, go back, go back, go back. This is the failure you're supposed to see. So what you'll notice here is we have a bunch of failures that are in Lstream. This is inside of Power Plant.
This is not any of our code in the example. And so what we're going to have to do is now Chris can take, while I switch the new Power Plant stuff into place, Chris can go through the changes you'll have to make to Power Plant, which are really minor. Okay. Back to the slides.
So the errors you saw up there the second time when we got the correct errors on the screen were some differences between the GCC compiler's interpretation of the power plant source code and the MetaWorks compiler's interpretation of the power plant source code, especially when it relates to how they use system headers.
Since what we've done for you is migrate you from the MSL Mach-O headers to the actual Apple standard library headers, there are a couple of library differences that make a difference when using power plant, and there's one thing where GCC interprets what you do differently. What we document in the transition book, which I'll tell you about later, and what you need to do to your power plant sources is you need to make four clean, compatible changes to your power plant sources.
And then GCC can compile any power plant application. There are some changes to the LException class, which subclasses the system exception class, and the system exception class has throw specializers on its destructor and its what method. So you need to add those to the power plant LException class so that it will match the underlying system exception class.
There's a place in lgatabscontrolimp.cp where it uses multiple instances of a local declaration inside cases of a switch statement, and GCC doesn't like the way the code works there, and it requests that you move the local declaration outside the individual cases, so that's fairly easy to do. And in lstream.h, the streaming operators for long double and short double are already declared elsewhere in the Apple headers, so you get a multiple definition if they're re-declared in the power plant headers. So you need to just case those out, and usually we do a pound if not GNU C, then include those, so that your power plant sources can be compiled and built.
And then, of course, we have the power plant source, which is the source that's being built by Code Warrior still, even when you're also building them with GCC. So this is pretty much all the source changes we have to do, and they're all in power plant to make the appearance demo run.
So what Scott's doing is he's actually switching over to a fixed version of power plant, and then he's going to rebuild. Which I have already done. And now he's rebuilt, and all of those compiler errors have gone away, and now he gets the errors we saw before, which are resource errors. Right. At the bottom, it says, "Error. File. Res merger. C failed to open source file -39." So if we can go back to the slides now.
Skip that and come back, because he says we're going to see this later. So this is the error we're seeing now. There is a bug in the res merger tool, which if you ask it to generate data fork resource files and you provide heterogeneous input that's mixed data force and resource fork resource files, it gets confused and fails.
And we will fix that by Xcode 1.0 by Panther. But for now, if you're bringing a project in that has resource files and the fork in which the resource files originate is different from the fork in which you want the resource files to go, and to build a Mac OS X package application, you generally want your resources to go in the data fork of the resource files in the resource folder. Then you're going to have to do some massaging of your resources.
In order to get them to build with Xcode. And what we did here was we basically took all the .rsrc and .ppob files both in the appearance demo itself and in Power Plant itself, and we just derezzed them into .rs and brought them in. And that has some extra advantages because then the indexer in Xcode can search them and you can have them in text form and you can check them in more easily to Perforce or CVS, which are not really resource fork aware.
And what we've done here is we've moved all those .rsrc files into .r files to get around the resource error. Now we're going to go back to get past the resource error. Right, in fact. This time you can watch it build. So if you notice really fast there, we did the resing, and so now it's going and merging the resources.
See, this is where we have the time to now talk. Right? And so you'll notice as we come in, just like Code Warrior, we have this little code column so you can see the code and you can sort by that while we're going on. We also provide these check marks to indicate what needs to be built. To the right of the code here, you'll notice we have errors and warnings on a per-file basis. So this is a substantial amount of Code Warrior code, both the appearance demo itself and the entire Power Plant framework that's compiling without error in GCC with very few changes.
So our challenges so far have been get the header files right, and we've done that. Get the sources right, and we've done that. And get the resources right, and we've done that. And once we have all of the binaries in place, then the linker kicks in. And getting the linker right is the last phase before you have a running application and can debug. So now we're linking, and we will see the build succeeded. But it lies. And it lies because we turned zero link on. Zero link defers link errors to execution time. So now if you try to run it. Thanks, thanks. And then-- oh, no, didn't run.
[Scott Tooker]
[Chris Espinosa]
So what you'll see is you'll see this unknown symbol and then some bizarre name. Really what it comes down to is currently in the prerelease, when you use ZeroLink in your C++ application, you have to link against the standard C++ library. For the final release, we should be able to take care of this automatically. But for now, you're going to need to set this in other linker flags. So I'll take you through that right now.
If we go back here, what I can do is let's just bring up the standard build settings. We'll look for link. Oops, not link, link. Let's see. So I will be brave. One other thing you will have to do is usually you have to touch a file. There's a few dependency cases that we don't deal with in the preview. Let me try it now.
Build succeeded again, and now we can run. And it launches. There we go. And lest you say, "Oh, but Scott, but Scott, this was built with Xcode. Oh, it must look different." "Yeah." "Oh, you swapped the power plant. Yeah." "Yeah. So that's why I decided it's too good for my-- yeah. So--" "Back to the slides. Back to the slides."
Just one clarification there. What it was running into there did not have to do with the changes we made to Power Plant. It's with some other issues that we know about. So in linking, the last step is that the importer maps your key target settings. It tries to read as much as it can from your project builder project file and translate it into the linker flags that you need to set in your Xcode file. There are some things we need, right now you need to include dash else std c++ in your linker flags. We'll take care of that for you in the 1.0 version.
An important thing is that often the importer, if you've built a Mach-O project and you've left .a files sitting around, the importer will bring in a lot of Code Warrior .a files. And if those have been linked with the Code Warrior linker, then the Apple Mach-O linker is not necessarily going to like them.
So you need to throw out the .a files that have been imported, and if they're built by subprojects, then you need to re-add those into your project. So that's what I was talking about before. If you're building from the bottom up, you need to rewire all of the subsidiary parts back into your project as you built it.
In the 1.0 version, we expect to have much better inter-target dependencies and inter-project dependencies. Do more of that for you automatically, but with the disks you have in hand, that work you need to do manually. And then the main thing is you notice that the first time we built it, it said build succeeded, it linked, it tried to launch and then got a run failure.
You're going to see that a lot if you have zero link turned on. So what we recommend doing is if you have a build succeed using zero link, what we recommend you do is that you switch over to the deployment build style, which turns off zero link, try building again, and then you'll see your real link errors.
You want to know about those link errors because they are link errors. They are things that will happen at runtime, either early or late, depending upon what they are. But don't take build succeeded as a failure. As everything is fixed. Always go to the deployment style and try a build there just to make sure it works.
Okay? Development and deployment styles are really, really powerful, and they'll make it a lot easier for you to work with multiple targets in Xcode than you've had it before in Code Warrior. Development and deployment styles, as Anders explained yesterday, are extra sets of flags that override other settings in your target. And what that lets you do is it lets you have a debug version, a profile version, a beta test version, and a final version of your application with the same target, without having to have four separate targets.
And what that means is if you need to change a target setting or if you need to add a file to a target, you don't need to change it in four separate places. You just change it in your one target, and then that is layered on top. And that's what we're going to do. We're going to do a lot of the same things on top of by the four different build styles. It really makes it a lot easier to manage your target.
So we recommend that instead of, you know, when we import your Code Warrior projects, we're going to import all of your targets, even if there's a debug version and a production version. What we recommend you do is that you essentially delete the debug target from your Xcode project.
Just use the production one, and then set all of your debug settings in the development and deployment styles. And that's what we're going to do. We're going to use the development build style of the production target. And that way you'll only have one target to manage, much less complexity, and you'll have much better control over what you want in your debug targets.
[Transcript missing]
There are some other differences, and these are a little more serious. If you've been using Code Warrior for a long time, you probably have put C++ code into .c files, because Code Warrior doesn't care. Now, GCC does care, and GCC, in its native state, will tell you if you use C++-isms, that is, things that are specifically C++ and not just C99 extensions to C to make it look more like C++, it will warn you if you try to declare a class in a .c file.
It will give an error if you try to declare a class in a .c file. Once again, you can cheat and turn on .xc++, and GCC will happily... interpret all your .c files as C++, but the rest of Xcode, which doesn't get information on the compiler from which language semantics you used for which specific file, may get confused. For example, the debugger applies debugging semantics to your source code based on its extension.
And so if you have a class declared in a .c file, the debugger is not necessarily going to see that well or clearly. So I really recommend that if you have C++, you change it to .cp files, and if you have just straight C code, you can leave that in .c files. That's probably the number one thing we see in projects moving over from Code Warrior, is C++ code in C files. GCC differs where the standards are undefined.
The order of calling C++ static initializers, especially if you're moving from CFM to Maco, where the order of library initialization may also be different, is that if your code relies on a specific order of initialization of static initializers, there will probably be problems, and you'll need to work those out and debug those very carefully. You can have some fine-grained control over it by link order, but it's something that you need to expect, is that your static initializers may not be called in the deterministic order you saw, mainly because Maco loads modules lazily and dynamically, whereas CFM did everything all up front.
The second thing is that there's some disagreement on how you pass structs and unions that are packed into quantities smaller than four bytes. There are some differences there. Most of these differences are not clearly documented either in the Code Warrior documentation or the GCC documentation. You can join some of the Apple mailing lists or look on Usenet for either of the Code Warrior groups, codewarrior.mac or compsys, mac, programming, codewarrior. Both of those have pretty long discussions of the differences between GCC and the Code Warrior compiler in these respects.
And finally, GCC uses the C and C++, in fact it supplies the C and C++ standard libraries that ship with Mac OS X in both static and dynamic form, and codewarrior supplies its own libraries, the MetroWorks standard libraries, or MSL, that go with the compiler and heretofore have been statically linked into your applications.
When you move from Codewarrior to GCC, you are moving from the MSL standard libraries to the Apple standard libraries, and there are some big differences there you need to know about. The good news is that if you're building for Maco, the MSL standard libraries are essentially a thin layer on the Apple standard libraries. So most of the behavior is the same except for a small layer of differences.
The other good news is that MSL has been supporting WHRT and WString, a wide character support in C and C++, for many years, but they couldn't supply it in their Maco libraries because it wasn't in the underlying Apple libraries as of Jaguar. It's now there in Panther, so if you have programs that have relied on WHR and WString support in MSL, and you couldn't go to Maco because of that, you can do that now in Panther. Because that supports in the underlying library, and it's taken advantage of by the MSL standard libraries. And this is a good implementation of WHR and WString. It's the Citrus project. It's been heavily tested in NetBSD. It's not something we invented ourself. It's really good code.
Another thing you'll run into is that Apple libraries tend to use the global namespace, not the STD namespace, for many things. Many things that MetroWorks standard libraries put in the STD namespace. This may mean that you need to make some changes to your code if you're expecting things to be in the STD namespace.
It may mean that you need to change some conflicts where things that you have in your code will conflict with things that are now in the global namespace. If you're using the standard template libraries, MetroWorks STL has some very useful functions for debugging that you invoke if you set a macro. Setting that macro is innocent in Apple's STL. It does nothing. You lose that debugging capability, but it causes no harm.
And then Apple libraries don't have certain MetroWorks extensions that they've added over the years. For example, FS-Spec versions of the POSIX file system calls. Since we're an underlying Unix operating system, we really do expect you to start using some of the underlying file calls or use Carbon. You know, use all Carbon or all Unix and not necessarily this strange mix of making a POSIX call with an FS-Spec as your file reference.
We've added some compatibility features to make it easier to bring large quantities of code over from Code Warrior to GCC. One of them is we've added some pragma support, not a lot, but it's getting better. We've added MetroWorks-style inline assembly. If you happen to have the inline PowerPC assembler code, you can bring that in from your Code Warrior project to your Xcode project.
We've brought several large projects over, one of them the Mac MAME video game environment, which is tens, hundreds of thousands of lines of inline assembly, and we compile that. So if you've got a lot of inline assembly, don't worry about bringing that over from Code Warrior. We can read it.
Now once you're in Xcode, you want to take advantage of the Xcode features. The reason to bring your project over is not because you're bored with Code Warrior, but because we've shown you some compelling things in Xcode, such as the zero link, the predictive compilation, the fix and continue, the debugging things I'll show you tomorrow that you really want to take advantage of.
How do you turn those on? Well, it's really pretty simple. The prerequisites are you have to use native projects, which are done by default when you bring it in with the importer. If you're bringing in a project builder project, you have to upgrade your targets from Jam-based targets to native targets.
And to get most of these features, you have to move to the GCC 3.3 compiler, which you can use in the project settings dialog is just change your compiler to system default or GCC 3.3. Once you're there, You move to the GCC style precompiled headers to get GCC's performance. If you don't move to the precompiled headers, the compiler is really slow. It's just as slow as turning off precompiled headers in MetroWorks.
The other thing is that using precompiled headers just from frameworks gets you a lot, but the more of your project headers you can precompile, the better. Really, the more headers you precompile, the faster it is. You can enable predictive compilation, and that means we will fire up the compiler in the background while you type, and that will really get you a speed benefit.
As I said the other day, when you include Carbon, Carbon.h in any source file, the headers that are brought in are three and a half megabytes of source. Now, most of you don't have anywhere near that in an individual C file, so the ratio of headers to source in a given compilation unit, it's huge. And the more of that we can do ahead of time, the faster the couple hundred... couple thousand lines of actual C, C++ we need to compile will go.
So predictive compilation will really speed up your turnaround time by doing most of the work in the background while you're typing. Zero link speeds up your fix, build, link, relaunch cycle by not having to relink all of those modules that haven't changed. It's really a lot faster. I mean, it can cut a 30-second link down to 10 seconds.
Fix and continue can cut that down to zero seconds by actually not having to have you stop the application in the debugger, quit it, fix it, and relaunch it. If you can fix something without quitting, then that saves both the quit time and the relaunch time and all the time it takes to get back to that point in your program where you're doing your diagnostics.
And then if you happen to have C++ projects and big C++ projects, distributed builds can really help you with your large world builds. It's not necessarily good for incremental compilations. It's not that great for C code because C is not computationally intensive to compile, and sometimes the network transfer time will exceed that.
But if you have big, big C++ files that take a long time for the compiler to work on, if you can send those out to multiple compilers, then that's a great way to get back to the core. And if you have multiple compilers in parallel, you can see some quantum increases in your build time by turning on distributed builds.
Let me talk a little bit about packaging and localization, because it's the last thing you need to do. If you're bringing a project over, a Carbon project over to Xcode, you may also be making the transition from a two-fork resource-based file to a packaged file. Let me walk through a little bit of that.
When you package your target, you pick what you're going to be doing, an application, a plug-in, a shared library, a framework, a tool. In Xcode, you pick that up front. Right now, we don't have the capability to change the target style once you've built the target. So you need to know what you're doing up front, and it's kind of hard to change from a static library to a shared library. And right now, we don't have a capability of cloning targets. So just make sure to know what you're doing ahead of time.
Most targets are packages. Almost everything except a static link library and a Unix tool will not create a single file, but will create a folder with a bunch of files in it. And the trick in packaging is figuring out what files to put where in that package. Tech Note 2015 explains all about the various package styles and what they are. If you don't know what I'm talking about, read that Tech Note first.
Xcode puts things where they belong in your package automatically. Right now it doesn't have a copy files build phase like Project Builder did that lets you do manual overrides. We will add that by the 1.0. But right now if you put a resource file, if you put a header file, if you put compiled code into your project, Xcode will put it into the right place in your package automatically because it knows the rules by which packages should be built. It takes all the target settings from the target settings and the project settings, it builds those into the Info.plist file, it puts the Info.plist file where it belongs. It really takes a lot of the manual effort out of that.
Working with resources. As I said, we read .R files and we read .RCRC files. We also will read PPoB files and merge them into your resources file. And we interact with resourcer, constructor, and interface builder. If you're localizing your resources, localizing resources in a packaged application is different than what you used to do in CFM.
In CFM, what you used to do was you'd have one two-fork file with all of your code and then the resources for one language, and then you'd produce another file with the same code and the resources for a different language, and then you'd produce another file with the same code and the resources for a third language.
Well, the way you do it on Mac OS X is that you have one folder hierarchy called a package, and it has one copy of the code over here, and then it has different folders called .lproj folders for your different languages. And your resources, your nibs, your strings, anything language-dependent goes in the .lproj folders. Okay? It's a different way of thinking. You deliver one binary that's multilingual rather than localizing.
You're binaries. Mac OS X apps are multilingual by default, and the way you make them multilingual is you take a file that has language-dependent constructs in it, like a strings file or a nib file or a resource file, you go to its inspector, and you look at this thing called localization variance.
And you can add a locale, and it makes a clone of that file that you then localize, and then it puts each of those into the right .lproj folders. So Xcode does this for you automatically. It will manage your hierarchy of localized versions. You can start with English and then localize from there.
Let me talk briefly about Interface Builder for Carbon. Eric did a great demo of the new stuff in Interface Builder. Interface Builder is the Aqua design tool. The Aqua design tool. And as we evolve Aqua for both Carbon and Cocoa, we evolve Interface Builder to give you access to those. And there's going to be more on Interface Builder and Carbon in the Building a Modern Mac Application session, which I'll tell you about in a minute.
But I just want to retouch on some of the things that Eric talked about. New in Interface Builder for Carbon is support for new Carbon controls like the HI image view, the HI search field, the HI scroll view, and the HI text view. You can drop these into your nib files directly from Interface Builder for your Carbon application.
We've also added the tiny controls if you're building very small pallets. We're going to start using these in the Panther version of Xcode because they're very, very useful for things like inspector panels where you want to pack a lot of buttons into a small space. These are now on the pallet for Interface Builder for your Carbon applications.
and new are control properties. This is static information that you can enter into Interface Builder that lives behind an object that when you load that object from the nib, these constants are already set in that object. So your APIs can query that object that it loaded from the nib and get these constant values from it.
So if you want to parameterize things or if you want to preset titles or if you want to have alternates or anything your API wants to do with information that you would normally put in a resource fork, you can put them behind the objects in your nib file. And this is a very powerful thing that will give you back in nibs some of the things that you used to have in resources.
And finally, because we've changed the format of the nib file for Panther, there's some fairly strong nib file compatibility checking that you can do in Interface Builder itself, that you can tell when you're building it whether you're using Panther-specific functions, whether you're using Jaguar-specific functions, and how backwards compatible your nib will be. So you can be careful about not accidentally constructing an application where all your code might run fine on Jaguar, but it loads a nib that happens to exploit Panther-specific functionality, so your application will fail when it runs on Panther.
Okay, just about right on time, going to wrap up. Hope you've learned from this session that we've given a lot of thought in Xcode to your Carbon applications, especially bringing your Carbon applications over from where they exist now, which is most likely in Code Warrior. We build C++ code really well. We adhere to the standards, we build it fast, we build good code.
We build good applications that adhere to the Mach OS X standards. We build packages, we use resources, we use NIBs. You're going to find that Xcode is the best way to build your Carbon applications on Mach OS X. There's a lot more you need to learn than just listening to my presentation.
There's a lot of documentation in the Xcode tool package. There's a lot of documentation in the system overview. For the CVS and Perforce integration, there are, you can go to the CVS and Perforce sites for those. The most important book to cover, what I've been talking about today, is this Moving Projects from Code Warrior to Project Builder.
It's not on your distribution, but it's in your ADC account. Log into your ADC account and you can download it from the Downloads folder. You can also get hard copies of it down in our porting lab, which is, it's called the Mach OS X Laboratory, down on the second floor, down on the first floor.
Integrating Carbon and Cocoa in your application is a really interesting book if you want to start learning how to take advantage of some of the Cocoa functions from your Carbon application. And then, of course, the definitive guide to the Mach-O runtime architecture and the GNU C C++ Objective-C compiler.
If you're moving to Mach-O and GCC for the first time, those are going to be indispensable resources. Of course, there are Xcode Interface Builder release notes on the distribution you have. And there are some places to go for tech notes, tech Q&As, and sample code. They're all on the ADC homepage.
Godfrey de Georgie is the champion for this technology. Contact him if you have questions. We have the Development Tools Engineering Feedback, which is at [email protected]. Please post bug reports. We want to make this a great Carbon development environment, and if there is something that we're being bonehead about or we've forgotten about in Carbon development, please let us know. We'll try to get it in by the 1-0.
And look at the mailing lists on lists.apple.com or the Usenets groups. I'm going to be living on CompSys Mac Programmer for the next few weeks, listening to what you have to say about it if you happen to be on Usenet. Here are some great sessions to go to. Feedback Forum 9 today, 2:00.
Let us know how we're doing. Debugging services for Mac OS X. This is the overview of Xcode and GDB. It's today at 3:30. That's not going to be a Carbon-oriented session. That's going to be a GDB-oriented session. Debugging and tuning Carbon applications. I'll be in the big room tomorrow morning, 9:00, and we're going to show you some great debugging features for Carbon applications using Xcode. Software testing tools. There's some fun stuff going on there for automated testing of your Carbon application using Apple tools and using third-party applications.
That's tomorrow at 10:30. And the session I was referring to before, how to write a modern Carbon application. If you've been using basic, modern, modern applications, basically the same APIs and resources for the past nine years, and you don't know what NIBs are and you don't know what HIView is, there's a completely different way to write a great Carbon application, and you should learn about that. 2:00 tomorrow afternoon.