Configure player

Close

WWDC Index does not host video files

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

URL pattern

preview

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

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

WWDC02 • Session 901

Command-Line Development Tools

Tools • 1:10:25

Investigate the command-line development services available in Mac OS X with the installation of the Mac OS X Dev Tool package. We discuss and demonstrate how to use the Terminal and GNU tools for compilation and debugging. Differences and similarities to other UNIX-derived systems as well as specific Mac OS X development concepts will also be presented. Developers should complete this session with a working understanding of the command line tool environment in Mac OS X.

Speakers: Stan Shebs, Sean Eric Fagan

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it may have transcription errors.

Ladies and gentlemen, please welcome technology manager development tools, Godfrey DiGiorgi. Good afternoon. It's good to see so many of you here today. I hope the show has been running well for you so far. Yesterday in our development tools overview, we talked about the fact that we build on standard technology and standards. And many people new to Mac OS X have been encountering the command line tool set of Unix for the first time. Just out of curiosity, let's use the applause meter.

How many people here are coming to Mac OS X from a Unix environment? It's about there. How many people are investigating the Unix tools from a Mac OS environment? about there. That's about what I expected. So without further ado, let me introduce Stan Shebs, our senior engineer in core tools. And he's well known in the open source community.

Hello everybody. Does anybody hear me? OK. I wanted to start off by going through the basic thing we're going to be talking about today, which is the fact that Mac OS X has a full set of command line tools. We use these tools to speed our OS X ports, especially coming from Unix. And what it does is it gives us, the command line tools also give us a familiar place for Unix applications, both for compiling them and then for running them once we've compiled them.

So the specific topics, I'm going to go over how to build and debug using command line tools, talk something about what the tools are available on a standard system with the developer tools installed, talk about some of the unique features of the command line tools, go a little bit into porting issues, although not in great depth because there's another session for that, and then also to talk something about the documentation resources that are available.

So it's actually kind of an interesting thing to have command line tools on Macs. I started at Apple in 1988, and they had just barely gotten AUX. How many people here remember AUX? Wow. Okay. Anyway, AUX never made the transition from 68,000 to a power PC. So most of the people at Apple were used to not using command line stuff. and coming from a university research background, this was somewhat painful. And I said as much to Larry Tesler, who was in charge of ATG at the time, and he says, oh, all you research guys, it takes you six months to get used to it. And he was actually right. Part of my getting used to it was to use MPW a lot. How many people use MPW? Okay. But it's always been a little bit difficult on Macs not having that. It's a higher commitment to get a program running. It's like you don't have a place to send standard out, things like that. You have to build a totally self-contained application just to get started. So it's been a really nice thing for me to come back to Apple. I worked at Cygnus, the GNU folks, for a while.

And to have essentially now an OS in which the Unix stuff is all underneath for the first time, it's actually an integral part of the system. And as part of that, you have all the traditional powers of Unix available to us. So one of the things about Unix is that its obsoleteness has been predicted for many years now, but it's actually still going strong after 30 years. The original Bell Labs guys were pretty smart guys, and they knew a lot about how to put system together. One of the things that they have that's the traditional strength of Unix is its composability of tools, which is kind of a fancy way to say that you can take the different tools that are essentially, if things are text-oriented, you can glue them together in creative ways. And so I picked an example that all the other guys at Apple rolled their eyes at, but this kind of stuff happens in real life, where we have two versions of a a C++ file, we call them old.cc and new.cc, and we can take the difference up. We are looking for things that change between the two versions of the file, let's say. In particular, we are looking for references to a couple of functions, one called foo fun, one called fop fun. There may be thousands of references to these functions in the file, so just grepping for all of them is not particularly useful. But you can take the diff, you can pass that to just find the references to it that are in the changes between the two files, and that allows you to zero in on something that you're specifically interested in. It's a weird example, but that's exactly what composability means. You can come up with ways to glue the tools together that no one has ever thought of before. MPW guys know about all this. They've been doing that for many years also.

Another thing that having the command line available on Macs now is that it gives us a lot of leverage. 30 years of development on Unix, from everything from servers to scientific applications to educational things and so forth, there's actually an amazing number of tools that have been developed and delivered, both large and small. And so a lot of that stuff will simply just work on Mac OS and Mac OS X. And this is actually the first time that things just worked on Mac OS X.

So to get started with all that, we have a terminal program. And this is an application. If you go to applications, utilities, there's a terminal icon in there. It's also located at slash application slash utility slash terminal dot app. But, of course, that doesn't really do you much good because that's the command line path. And you can't type open slash application slash whatever until you have a terminal window. So anyway, so that's just to show you where it is, and you can actually CD down to that and just see what the terminal program's made up of. So terminal--how many people here have not seen terminal or not used terminal, let me ask? How many people have not used terminal?

Okay, good. So everybody's actually seen all this, and this is all redundant. Anyway, in case you didn't know it, you can open up multiple windows. Each window runs a separate instance of the shell, and I'll talk about the shell more in a moment. It gives you lots of preferences, and it is available on all systems. So you can go to somebody's strange OS X system, whether or not it has the dev tools installed, and Terminal will be there. So now Sean Fagan is going to give us a demo of the terminal program. Not that anybody needs it, but Sean has a few tricks up his sleeve. Okay.

Oh, I can hear that. Okay. I had hoped that there would be fewer people who didn't know the terminal application. I'd give a spiffy demo of it, but you all know about it, so... Here's where you get to it. It's under Utilities, Terminal, and everyone knows about Console too, right?

All right. Let's make the font larger. I'm going to be using this later, so I have to set that up anyway. The display, set font to something larger. Let's go 14 point. How's that? Can everyone see it, except for the windows in front? Great. The other thing I was going to do, there is, as Stan alluded, there is the open command, which is kind of like double-clicking something. You do that, Finder brings up the root directory.

And the other thing I was going to show is people get a big kick out of setting the terminal transparency to, well, something semi-transparent. terminal opaque S 0.25 and voila, we have a transparent terminal and the value of 0.25 is really not a good one if you want to be able to use it. On the other hand, I actually have used higher around 0.5 or 0.75 and it's actually fairly nice if you've got a limited screen space in a lot of windows and you want to be doing something in one window while something's running in another. And since you all know about terminal, that's really it. Back to Stan. Thank you.

Okay, so let us all recite the catechism. We say emacs foo.c. We cat it out just so you can see what you did. We say cc. We do add a dash g because we're gonna run the debugger in a moment. We say a.out, 'cause by default the name of the executable is a.out. We put dot slash because we wanna run the one in our current directory and not some other a.out that might be somewhere out in the system that our search path is gonna find us.

It prints out hello, that's good. But we like the debugger so much, we're going to run it anyway. So we start up the debugger. We say gdb on a.out. We say break main, set a break point at the main program, beginning of the main program. We say run. It stops, shows us the one line of the program.

And that's pretty much all you need. I mean, that's the command line tools. So now we're done, and you can all go out in the halls now and tell everybody about the amazingly short command line tool session. Thank you. Okay, but nobody's getting up, so I'll go into a little bit more detail on some of the things. So the shells, the shell is basically a command interpreter.

It's just a traditional Unix-y term. One of the curiosities of Unix, shall we say, is that there are a number of different shells that have been developed over the years. Since a shell is just a normal Unix program, it's actually possible to have many different shells running at the same time on a Unix system. and so people take advantage of that and they invent shells. There are shells written in scheme. There are shells that use funny syntaxes.

But there's two main families of shells that you'll find, and both of these are installed by default. The original family is called the Born Shell after the Bell Labs guy that originally put it together, and it has a specific syntax that you'll hear referred to as the Born Shell syntax. Since it was installed as binSH, you'll also see it referred to as just binSH. Now, it turns out we have a couple implementations of that. One's called ZSH. That's the default for 10.1 and earlier. For 10.2 and later, for Jaguar, excuse me, Jaguar and later, we have BASH. BASH is the GNU project's reimplementation of the born shell. That's short for the born again shell.

Anyway, among other nice properties, it's quite a bit faster than the ZSH. The syntax, though, is not necessarily to everybody's taste. And there's another family of shells that people have used, which is called the C shell. It originally comes from Berkeley Unix. And the incarnation that we use on OS X is called TCSH. And it's the one I personally prefer. In general, the commands that so far look the same between the two. So in some ways, it's a matter of taste. such as how do you like to do loops, and how do you like to quote things, and so forth. So you have to be kind of an aficionado maybe to decide which one you really prefer. Usually most people, it's good enough just to pick whatever you get by default.

Okay, moving on to editors. Since I'm up here and I had to put together the slides, I got to decide which one was going to be the one true editor. laughter So we'll talk about Emacs first. Emacs is an editor that's been around for a very long time, since actually long before Unix, well, not long before Unix is, but somewhat before Unix existed. And it was actually originally developed on ITS machines at MIT. That's how old it is. It's highly customizable.

It actually has a Lisp-like language inside that you use to program its behavior. People have used that over the years to build in quite a lot of good features. For instance, Emacs's knowledge of C syntax is actually pretty good. If you hit a tab to go to a new line and the new line doesn't jump over to where you think it should, you've probably made a mistake in your code somewhere up front. It's best to, instead of arguing with Emacs, to go back and find out where you typed the extra brace or forgot to close a comment or what have you.

So on 10.1, we have the standard version is 20.7. And I believe it's something like a 20.8 or something like that for Jaguar. This is a single window editor, so it just sits inside a terminal window. It doesn't open up multiple windows of its own. There's an X11 version that's downloadable also, but you have to, of course, be running an X server for that.

So because we value diversity, we also provide VI. You know, that's interesting. There wasn't any applause for Emacs. Thank you. This is bad. Okay, so I've got a tough audience here. Okay, well, okay, so I have a good story to tell about VI. Okay. I actually used VI full-time for about a year, about 20 years ago. And then I switched over to Emacs and been using it ever since. But coming back to Apple, every so often I get stuck using VI for whatever reason. And after 20 years, I still remember all the VI commands. So... So that's a good thing about VI. The commands are easy to learn.

Things are fairly straightforward. It doesn't have all the flexibility. Now, a couple of people at Apple said, well, what about Vim? Okay, there is an improved version of VI called Vim. It has a lot of this customizability, but you have to get it by downloading. It's not in Jaguar. Thank you.

Other than completed, I mentioned we have things like Pico that's also installed in the system. Again, there are literally dozens of editors available for the download if there's something else you prefer. Sean has a demo of Emacs. This is just a quick and simple setup. It is a Unix system. Write a file. Use real paths.

Everyone knows this program. And unlike Stan's, I have a proper return value. So that's because those of us who use VI know to follow standards. There's the compiler. It's awfully quick on this machine. Head on out. And for people who like this. And we can say -- Come on, where's the applause?

So there's Emacs, and again with compiler, and for those of you like that, voila. And all of the utilities that you would expect really are there. There's Make, there's two versions of Make on the system. The default is GNU Make, then there's BSD Make for people who like that, but I don't have a Makefile. Voila. There's also an Aqua version of Emacs, which was done from the Next Step version. Unfortunately, I didn't bring it, so I can't show that.

Thanks, Sean. So if you send your email address to Sean, he will personally send you a copy of this cool Emacs that I was hoping you would demo. This would actually be one that would be a better Emacs to use if we can get that folded into the system. I'm hoping we'll be able to do that in a future version. The multiple windows, Emacs with running inside a terminal window is convenient. You can run it over the net. You can do all that kind of good stuff. but having a multiple window Emacs with the buffers and mouse sensitivity is actually a really good thing.

We will cover a little bit about languages. We have C, we have C++, we have Objective-C, and we have Objective-C++. We have Java, which is based on Sun's Java 1.3.1. There's a full set of the command line tools, jikes and so forth, that you can run. We have a number of interpreted type languages. We have Perl, Tickle, PHP, and in Jaguar, there'll also be Python. For 10.1, you'd have to download it. The third parties also have command line versions of their tools. There is a command line version of Metrowerks and there's command lines for ABSOF's Fortran. In addition, you can download G77s, the Fortran compiler. How many people want it to be a standard part of Jaguar?

It hasn't been decided yet, but it's a commonly requested item, and so it's quite possible to still be able to do that. So there's also some nutcases that have been working on Ada for OS X. Where are the nutcases? I know they're in this audience somewhere. Oh, they're hiding. OK, anyway, it actually is working just as a very, very short time ago. And they're actually starting to work on how to get it integrated into Project Builder. But the command line stuff is there already. Probably not going to be a standard thing in Jaguar. We can also download versions of Lisp and Scheme and so forth. There's quite a few languages that have been ported to OS X.

So our build tool options, as Sean alluded, there are basically two kinds of makes. GNU Make is a standard. There's also a BSD Make, but it's pretty much for compatibility. And actually, I personally don't know of any tools that require the use of BSD Make, but I know that such exist. There's also a command line tool called Jam, which is the underlying make type tool for PBX build, which is a command line version of Project Builder. It sounds kind of odd. Why would you have a command line tool for Project Builder? Well, it has an advantage in a work group where you say you have some people using IDE and some people using the command line, or if you have a situation where you need to run, say, a nightly script and you don't want to have to make your most junior guy come in and click on the mouse in the middle of the night to get something to run.

So you can also SSH into a machine and run PBX build there. So PBX build is very convenient. The project builder projects are actually in a text form. They're XML syntax and they're textual files. And the truly brave can actually edit them manually. But officially, we don't recommend it. But if you're truly brave, truly brave. Okay. I should also note that Apple's Jam is extended from the net version to support PB. So if you download a net version of JAM, don't expect to be able to drop it in on top of the JAM that we supply.

Other useful tools, we have about 400 or 500, I think in Jaguar it's actually closer to over 500 now, tools in slash bin and slash user bin. And the collection of tools most resembles FreeBSD. There's CVS, RCS, and SCCS for source code control. CVS is perhaps the most commonly used of those. There are a lot of projects that run on the net, open source projects will use CVS over the network to manage their code.

For people at old Unix types that use the old TROF, NROF formatting tools, those are actually all still there. At this point, their main use is to format the man pages. So I'm not sure that anybody actually writes new stuff in them outside of man pages. But they're all there if you love that kind of stuff. We have Lex and Yak for compiler generation. We have the GNU equivalents Flex and Bison. We also have a lot of tools that are more expected to manipulate object files, do fairly low-level things. There's RanLib and AR, which I'll talk more about in a bit. The assembler is called AS. It generally resembles the GNU syntax, but it's evolved somewhat, so it's a good idea to check the OS X assembler manual if you're getting into assembly code.

For the old Mac heads, the syntax is somewhat different from PPC-ASM, so you should be aware of that. O-Tool is the tool we use instead of ObjDump to dump out object files to get the contents of them. And you can do man O-Tool to find out more about it. We also have things like AutoConf, which I'll also talk more about.

Shifting gears a little bit to talk about APIs, we implement most of POSIX, but we don't implement all of POSIX, and we want you to report POSIX nonconformance wherever you find it. Now, POSIX applies to both command line tools as well as to programming interfaces. So, for instance, if LS-L doesn't operate as you would expect it to do on a different Unix machine, That is a bug in the command tool side of the POSIX specification. And then anything that doesn't operate like what a "normal" Unix machine operates like would be a nonconformance in the POSIX API.

So we'll get to posix eventually, I think, but it's certainly not the case in 10.1, it's not the case in 10.2. Other APIs, we do OpenGL and Glut. And from personal experience, I think things come over quite readily. Very little change required. We also have Carbon and Cocoa for GUI, which, of course, you've heard nonstop about here. There's also a different API, which is I/O Kit, that's used for drivers and kernel extensions. And I/O Kit is a C++ object-oriented thing. It's actually kind of interesting to use C++ at the device driver level. It makes possible to write very small drivers and be able to share most of the code. And for anybody that's ever tried their hand that a Linux device driver, you really appreciate that. We provide a lot of the common code, and you only have to write the stuff that's unique to your device. We also provide, not as a standard part of OS X, but there's a couple different X11 systems available. So if your users can run a server, then X11 apps can run on those machines also.

So the APIs are provided by what are known as frameworks. And I have to apologize for doing a graphics on this. This is the only graphics in the talk. Command line guys don't need no stinking graphics. But this one looked good, and I said, oh, sure, why not?

Okay, so a framework is basically Apple's answer to the problem of managing shared libraries and headers and resources that go along with those libraries. So what it actually looks like on the system is you'll have something for a framework called foo. You'll have a foo.framework. Inside that, you'll have the shared library proper, which will usually just be called foo. And if you did the file command, the file command tells you what's in a file. And the file command says this is an executable. Well, in some sense it's an executable, but you don't execute it by itself. It's just a shared library. That's just how it happens to be marked. There's also a subdirectory called headers. All the headers sit in that. And there's a subdirectory called resources. And the resources are things like strings that you might localize or other information about the framework. And these are all text files, again, in XML syntax. And you can edit them if you're feeling brave.

So another detail about frameworks, if you actually go wandering around looking at the framework, you notice that a bunch of stuff is symlinked. And when I say headers, they're headers technically as a symlink to versions and then say A and then headers. And this is a versioning mechanism that frameworks have that in practice is not really used very much. The most you'll notice is when you try and look at the headers and it says, "Oh, this is just a symlink." And then you have to say, "Look at headers flash," and then and it'll show you what's inside. So that's just something to know about frameworks.

To use them, you'll say include foo/foo.h in your source code. I'm sure some of you are looking at it and thinking, "Isn't that confusing if you had something user include foo/foo.h?" Actually, yes. There is an ambiguity there. They chose this framework syntax before I came along, so I would have told them to use something like foo semicolon foo.h or something that wasn't so obviously a path. But anyway, we luck out most of the time because user include doesn't have a foo subdirectory in it, so this thing doesn't get confused. Is that some of that capital letters?

uppercase, lowercase, that's a non-issue. It's basically a convention thing. Most of the frameworks tend to use mixed case, and that's essentially something I'd basically inherited from the next world. To link, you say -framework foo. Most of the frameworks live in /systems/library/frameworks. There's about 40 or 50 of them, I guess.

However, most of the system stuff, the standard Unix system stuff, doesn't live in the frameworks. That's the normal headers, POSIX headers, live in slash user include. They look the same as always. If anybody remembers the public beta and earlier stages, there was actually a, quote, system framework. And all the headers actually lived in system library frameworks, and user include was sort of symlinks. In practice, that turned out to be kind of confusing, and so we essentially ditched the whole system framework idea. The only remnant now is that if you look at the user lib, you'll see a copy of the file "user lib lib system.b.dilib" or something like that. That is the standard C library and all the stuff that goes in it, and still has the syntax as if it were a framework.

anyway to define your own frameworks need to you can you like a stick in the system library framework so they can be erased by the next uh... uh... always ten uh... software update or you can put them in your own place that's safe and use dash F and the path to that to find the framework. And dash F will get passed both to the compiler, so that it includes work, and to the linker so that it knows what to do when it sees a dash framework.

So moving on again. So the compiler is GCC. And we get this question a lot. I think pretty much everybody's worked it out by now. But the compiler is GCC. You do not need to download from the FSF and try to build GCC in order to get started because you'll almost certainly be disappointed. We have a lot of extensions to GCC. Some of those extensions, like the framework lookup, are fairly important for doing anything on OS X. So whether those things will make it into FSF GCC, we don't know. It's kind of a thing unique to the Mac, and the rest of the world isn't necessarily that enthusiastic about adopting this stuff. But by and large, the usual GCC options work.

We do have a number of additional options. Most of them are distinct to Mac programming, so you won't need them for the porting of Unix applications. And for Mac applications, most of that stuff will have worked already. That is, if you used it previously on OS 9 application, pragmas and so forth, they'll work pretty much the same on OS 10.

I just wanted to call your attention to a couple interesting options. We have a dash F Altivec that enables all the Altivec support. So by default, because Altivec actually makes the keyword vector or the symbol vector into a keyword. So if you had a program with the variable called vector, you turn on F Altivec and it kind of chokes. So we made that an option. and we have to actually explicitly request -f Altivec.

So if you're porting anything, and there's probably not too much of this code, if you're porting from a PowerPC Linux where they had a Motorola version of the Altivec support added to GCC, they called that option dash FVec, and we renamed it to Altivec because that was a little bit more accurate. And so that would be what you'd change the FVec into.

Another option in the compiler session we'll talk about is some more depth. There's a -mdynamicnopic that you might want to add to when building applications. It saves a couple of instructions, but it makes your application not relocatable. This is fine for applications. You wouldn't want to do this all the time because the shared libraries you actually want to be able to relocate around an application's address space as the dynamic library gets loaded and unloaded by the OS.

So to build libraries, it depends on whether you want to do a statically linked library, a traditional archive format, or a dynamic library. To build a static library, you use AR, another old Unix program, and then you use RanLib on the result to make that into a, essentially to add a table of contents. This is something that you don't normally do on a Linux machine, so that's a little bit of a departure for people that are familiar with Linux.

The other way to build a library is to make it a dynamically linked library. That's the library that underlies the framework. And there we use the option cc-dynamiclib. and then all the right things happen behind the scenes. Now, one way to cover this up, and quite a few heavily ported applications know how to do this, there is a system of shell scripts called LibTool, which tries to give a platform-independent mechanism for building libraries. One of the unfortunate things about the many Unix variants in the world is that while they all call their compiler CC and they all use -g to say output debugging info, somehow that never quite happened for building of shared libraries.

And so on one system it's -r, another one's -shared, for us it's -dynamiclib, et cetera, et cetera. So the lib tool is basically a wrapper, and it's a shell script that wraps around the compiler and the linker invocations to pass the correct kinds of options for the platform you're running on.

So it's a very handy thing. For porting, the main thing that you have to worry about is updating the lib tool bits. There's a standard, again, comes from the GNU project, GNU.org, and most projects have fairly up-to-date lib tool bits, and they know about Darwin OS 10, but I've seen a couple where they've been out of date and the right thing to do is to update.

And speaking of Darwin, another thing to know about is the different versions of the system. You've heard this a bunch of times, lower layer system is called Darwin. Darwin basically consists of the open source part, few or no frameworks. I think core foundation is probably the only framework that's actually in Darwin, and none of the GUI stuff.

This matters because there's two different kinds of tools that you use to get version numbers. One of the tools is called SW_VERSE. That reports the Mac OS X version, such as 10.1.3. It also, underneath, reports a build number, something like a 5P64. That's the way to identify an exact build image. Most of the time, that really only matters to people, say, getting seeds, where it's different than the final release number.

The other tool, and this is a Unix standard tool, is called Uname. And you say Uname-A, and it will give you the Darwin version number. And there's a little chart showing how they match up. Mac OS 10.0 is Darwin 1.3.1. 10.1 is 1.4. And then, for reasons that seemed good at the time, but they still seem good, We bumped the number so that the software update to 10.1.1 changed the Darwin version number to 5.1. There were a few people surprised by that, let me tell you. Not often you get a major version number change by doing a software update. Anyway, the purpose of that actually was to align the Darwin version numbers with the build numbers used internally.

So when I say 10.1 is base 5P whatever, the Darwin is a version 5 to go along with that 5. So to take an example, in Jaguar, your systems you name -A will say it's a Darwin 6.0 and do along with 10.2 as an OS X version number.

The reason this matters is because it ties into one of the very common ways of doing handling ports, which is to use GNU's configure and make process. So there's a lot of stuff to go into here. We don't really have time to go into it in any depth.

Makefiles are basically not adequate for really large or complicated software projects. So what the Gadoo project adopted years ago was a process of editing the makefile to adapt it to the system. And the shell script, which started out as a couple-page shell script, and is now like 100 pages long if you ever printed it out. But the configure script will essentially edit the makefile and take care of any system dependencies or user-chosen options or what have you, and edit the makefile so that the right thing will happen for the system.

And this is why in many of these projects you can actually pull the source code down off the FTP site, take it onto your OS X system, even if the code has never been ported before, and many of them just work. It configures, knows how to dig around and user include, it knows how to turn if-def's on and off depending on what a system has on it, edits the make file appropriately. When you run make, all those things are taken into account and the program produces the executable.

So one of the ways though which that could fail is if the guessing part about what system you're running on is incorrect, okay? and there's a script. Then you'll see that at the top level of these directories called config.guess. And config.guess is basically a wrapper around uname. And what it does is it translates the-- Darwin 1.3, the uname output, and translates it into a triple. Configuration triple traditionally starts architecture, vendor name, and then operating system name, and possibly a version attached to the end of it. So a Linux system will come up looking like something like I686-PC-Linux. Darwin systems will come up as PowerPC-Apple-Darwin 5.3.

And then later on, the configure script can then make a test based on that. Is this a version that supports a feature in ctype.h or something like that? Anyway, config.guess for many projects nowadays is up-to-date enough to recognize Darwin as a platform, but not always. And if yours is one of the unlucky guys, then you want to get the two scripts, config.guess and config.sub, from the GNU organization. and I put there the URL that actually gives you to the CVS web where it shows you the latest version. Since these two scripts are self-contained, it's generally always okay just to take those scripts and drop them into an existing project.

Another thing to help you get started on porting, some projects do want to see GCC. They actually invoke GCC by name. It's convenient to symlink CC to GCC, C++ to G++. This will be done in Jaguar. If you look at Jaguar, it's already got those symlinks, so this is strictly a 10.1 issue now. Thank you.

Now the other thing that people often ask about is they want some kind of predefined macro. We don't have a predefined macro. Partly the reason is historical, partly it's a policy thing. The macro that we would use would inevitably get confused with, say, different generation of Next Step, which doesn't really matter much anymore, but it did up until fairly recently, and other versions of Apple's systems as well. So in general, what we recommend is either to test for the features directly, and I'll talk about that more in a minute, or to essentially insist that the user add a dash, a define of Mac OS X as a symbol, and then use that in your code if you absolutely have to do it that way.

So there are interfaces that have to be ported, despite all the command line emphasis. Curses just works. Curses are built into the system framework. It's already all there. I haven't personally experienced any problems with bringing over a piece of code that uses curses. There are now aquified versions of TickleTK and of QT. So you can actually write a tickle script that brings up the lickable buttons and all that good stuff.

X11, as I said, is available if your users are willing to run an X11 server. In something like a university environment, that would be a very reasonable thing to do. So those are available. The distributions are commonly readily available. There's X386. There's a commercial package from Tenon. and OpenGL as our standard. The one thing that will get you though is that the includes, for most systems you say include GL/GL.h, The OpenGL framework is called OpenGL.framework, which means you include OpenGL slash GL.h. So one way is to change the source code, if def every include of GL slash, or the other alternative might be to actually add a GL subdirectory to user include and make symlinks from there to the OpenGL.framework headers.

Some more common problems that people run into: the compiler uses precompiled headers. These precompiled headers win big time. They're like a 4x speed improvement for compiling Cocoa things. As it happens, relatively little Unix code that you're bringing over uses Cocoa, amazingly enough. And so you're actually not really getting any benefit from using precompiled headers. And the preprocessor, this mechanism works by using an intelligent preprocessor, sort of intelligent anyway. And it takes extra time to preprocess when doing its thinking about whether to use the precompiled header or not. So as it turns out, it basically has no upsides and all kinds of downsides when doing Unix porting. And so we have an option no CPP precomp that basically switches back to using GNU CPP. you Other things you'll run into, there's missing declarations. There's some that we know about that are going to be fixed in Jaguar, and there's probably others we haven't heard about, and they're going to be fixed in whatever comes after Jaguar. Ditto for missing functions. One way to deal with that is to reimplement them, conditionalize them when they're running on OS X. Sometimes you have to if-def the functionality, alas.

Another thing that can happen is extra definitions. The system framework, lib system, has a lot of stuff glued into it. As I mentioned, the curses library is glued into it. If you have a program that can't be linked with curses, that you don't normally expect to link with curses, and so you reuse goto xy or some other curses function, then you'll get something back from the linker saying, warning, multiple definitions of goto xy. You're saying, uh, The only one I know of is mine. It is a warning. It's not a fatal flaw. The linker complains because Mac developers expect it to complain.

So we have an option called "multiply defined suppress" that you can feed to the compiler and it gets passed on to linker and that will stop the complaints. Thank you. Another one that I've seen in that same category, we have an implementation in GetOpt, which is used to get command line options in a standardized fashion. And the lib system has a version of GetOpt, and they had a lot of GNU tools link in their own copy of GetOpt. So you had also warnings about duplicates there.

getting a little bit weird. So how many people knew about designated initializers already? Thank you. Yeah, that's about what I thought. They've been in GNU C for about ten years, and they're basically a way to fill in an array positionally, which is kind of cool. No need to have Cs of zeros trying to get down to the one element you want to fill in with the character code of A or something like that.

It turns out that C99 actually has picked up this GNU extension and it's now actually standard part of the language, except they added an equal sign. Anyway, as it happens, and for technical reasons that I'll be happy to rant about offline should anybody be interested, our 295-based compiler can't deal with this, and it will give you lots of errors. One way in which we noticed this was in GCC version 3 itself, which uses designated initializers now, and it complained. This will be fixed in 3.1, so it will no longer be an issue.

DLopen is also something that's occasionally requested. This is to open a dynamic library programmatically. And it's... I can't remember if it's a POSIX feature, but it's fairly common among Unix systems in one form or another. It's not directly available. And, in fact, for technical reasons, it can't be totally emulated by the Mach dynamic load stuff. So, in general, what people have been doing is they emulate the functionality, whichever part of the functionality they happen to need. Thank you.

Another thing that people have bumped into is Pthreads. We have Pthreads, but we don't have complete Pthreads. Perhaps a better way to say it is we don't have all the Pthread options that all the Pthread implementations in the world have, and so people have run into missing options. Sometimes you can emulate, sometimes you'll just have to send a bug report to Apple and say resend it every week until something happens.

Feel free. We use eight-digit numbers for radar, so there's plenty left. We're only up to about 29 million, I guess. Anyway, namespace conflicts. It's always been possible that there are a lot of namespace conflicts because of the way Mako works. In practice, I haven't actually seen as many namespace conflicts as one might expect. In any case, if you run into this, the way you'll see this is that you'll have a function, It will report a conflict.

There's no documentation on the function it's conflicting with. It's just in some framework. So one way to deal with this then is to use the option dash two level namespace, which introduces the, makes non-exported functions invisible. Like I said, it happens to some people, it doesn't happen that often. But you'll know it if it does, 'cause you have a conflict between symbol names and there's no way to fix it.

Two-level namespace can help you there. Another thing to do, and this should be on the more common category, is you have to run ranlib after AR. Ranlib creates a table of context for an archive. It used to be that Unix always had to do this. In ELF, which is what Linux systems today are based on, ranlib isn't typically necessary. So makefiles inherited from the old days will run ranlib, which is a no-op on ELF, and make files written, say, originally for Linux and not ever having been ported to another Unix system, they won't run ranlib. You'll run the make file, it says, oh, it can't link 'cause their table of contents is out of date or something. The way to fix it is just run ranlib on the name of that archive.

So Sean is going to give us a demo. Now, I think the way he described it more, that he was going to do all of Mozilla and in 15 keystrokes. - You re... Yeah, I don't think. All right, what I was just gonna show here was something using configure that ran into problems. I don't know if anyone's familiar with it, if anyone used rdist.

Artist is like rsync, which is built in the system, only where rsync pulls, artist pushes. A while ago, I had a request for artist, and I supplied it for someone. It almost but not quite worked. Artist 7 almost not quite worked. Artist 6 just worked. I've already configured this because it takes a while.

We do a make, and it runs for a while. still runs for a while even on this fast system, and it will eventually fail. I have some patches which I will go over and show. They mostly change the configuration, which Stan talked about. See? Look at that. How horrible. Conflicting decorations. Sigh.

These are what my disks look like. Can people read that, or should I increase the size? Alright. Set thought that's 14, about 18. Oh, there we go. All right. As you see, the first sets of patches are to the configure.in file, which is what autoconf uses to generate the configure script, which you should then run. Most systems, for those who are aware of them, configure comes already. You just run configure. However, if you are the developer, you need to create the script that generates configure. So there were some problems with statfs in the original version, and this does the right thing. The other one worked. It just wasn't as good, I thought. And there's more of this configure stuff. Da da da da da dum. And there was an include of malloc.h. malloc.h is not a standard include file. You should not use it. And lastly, artist used a function called setMode despite the fact that ANSI describes a function called setMode. So there was that.

I'm gonna do that. Oops, I run it with the wrong option, sorry. Dash p1 tells patch to ignore the first file. No. Anyway, autoconf to generate it. Run it again, and as everyone would see, it just... This did not happen in my previous tests, I'm sorry. But it worked.

I do apologize. Anyway. That's generally, I actually had to search for a while to find a well-known program that would not compile. Most things you just run configure and make and they do just work. - Didn't I do that? Yes, in fact, I did. Oh, no, you didn't. Thank you. I am stupid today.

Yeah, teamwork is good. Yeah. Wow, you're smarter than me. Voila, it works. Thank you. So that's an example of how you deal with things. And I did, by the way, send the patches to this back to the artist7maintainer, and I have not checked recently if he folded them in, but they were small, so I presume he did.

Back to Stan. Thank you, Sean. Thank you. That's very nearly a perfect example of what actually happens, including remembering to rerun Configure when you make these kinds of changes. If the thing that Sean did looked like gobbledygook, it is documented how to do this stuff, and that's what I was going to talk about. The tool is called AutoConf. AutoConf is weird. There's a macro process called M4. The syntax is bizarre.

The only excuse I can think of is that it was developed incrementally over a number of years, and so it's more as accreted as much as anything else. What AutoConf does, though, is very powerful, which is it essentially directly tests your system to find out what things are present. For instance, you need to know whether ctype.h is present. ANSI requires and ISO requires that ctype.h be present. It's not necessarily the case that every machine in the world has one. What autoconf does is it basically synthesizes a one-line C program that just says include angle bracket ctype.h, compiles it, and sees what the compiler said. Compiler errors out, guess what? Either ctype.h is not there or it has a mistake in it and you don't want to use it anyway. It then turns on a flag, depending on how you can set up things. It says something like ctype.h not available. In your code, you would say something like, "If ctype.h available, include ctype.h, else do something else," whatever it is you need to do in your program.

So the auto-conf mechanism is essentially 100% accurate for the system you're building on. Now it's not quite so accurate if you need to build on a range of systems. If you're say on a Jaguar system and you need to build something that works on 10.1 and Jaguar and future systems, you may have to think a little bit harder about how to make that work. One of the things we have available as of Jaguar is a new header file called availabilitymacros.h.

And this will have a set of macros that essentially define what's available in different versions of the OS. It has macros that are like half a page long, and they read something like, "If Mac OS X 1.0 but not 10.2," things like that. That's how they literally read. So you can use those to make something that works across multiple versions, should it be using features that change from one version to the next.

But anyway, the nice thing about AutoConf is that it actually has a book describing it. And it was published a couple of years ago. And it's just a standard book, readily available. In fact, I noticed last fall in Las Vegas in Borders Bookstore, which is not exactly what you think of as the high-tech mecca, okay, not Las Vegas and not really Borders either. And they had in the entryway where everybody coming into, going out of the store has, and they had large numbers of this book on display for everybody to see as they're going in and out. And I'm going, you know, there must be a lot of auto-conf experts in Las Vegas now.

I had no other explanation. Anyway, and by contrast, I noticed that Fry's last night, the Fry's down in Kamloops, there's only one. So somebody needs to get it quickly, and you'll be the person who knows autoconf, and nobody else will. This also describes AutoMake, which is a way to synthesize Make files that a number of people are using nowadays. And it also describes LibTool, which I talked about earlier. It actually has a lot of stuff about the inner secrets of LibTool.

some caveats to go along with it. You can be root. Is there anybody that does not know how to become root on OS X? Good. Okay. Anyway, but now that you've created root, you have all these responsibilities to go along with it. In particular, it's very tempting to dink around with the system to try and get it to compile your program. We do not recommend this in general because you'll take that program over and somebody else will try and build it and they will not have the modifications on their system. So that's why we're doing sim linking GCC to CC in the system so that every system will behave this way. I mentioned before about sim linking, adding user include GL/GL.H to user include. Again, somebody doesn't change their system in that way, that will fail for them. So if you do this, you need to come up with some way to, say, have a script they can run as root and modify their system in the same way.

Another thing to be aware of, Mako object files are very different. They are a little bit like ELF. They're a little bit like, I'm sorry, I don't have anything as exciting as whatever they're. I'm sorry. Godfrey can get up and dance. You want to-- Anyway, that's like object files really are dull. But anyway, Mako object files are very different. They have some features that no other object files have. For instance, they can support multiple architectures within the object file. One of the consequences of that, there's not a standard GNU binutils port.

So that's another thing. Don't bother getting binutils from the FSF and try and build an OS X because it won't do you any good. So we have our own O-tool and AS and so forth. All those are there. If you have equivalence all, it's just the standards you can use stuff won't do you any, it won't help. Another thing to watch out for is HFS+ versus UFS issues. I'm sure everybody's been bumped into that, but not everybody that writes software has quite tumbled to this. And there's been a number of projects, I think the risk of slandering somebody, I think Pearl was one of those. Somebody correct me if I'm wrong, but they had actually the same file names with different cases in the same directory.

Pardon? Oh, Python. That's right. Okay. Incorrectly slandering Perlis. Python that I want to slander. Okay. Okay. Actually, there was another similar case that actually happens in the GCC sources themselves, but they have a library called libffi, which is supposed to call from Java to native C code, and somebody in there just had to have a mips.s lowercase and a mips.s uppercase. So you check this out from the FSF onto your HFS volume, and CVS doesn't like it at all. It says, "You've got a conflicting file. Every time you check it out or update, you've got a conflicting file." Yes, I know it's a conflicting file. It works fine on UFS. If you're not aware, your buddy that just happened to be building something on a UFS partition, everything works fine, and on yours it messes up for some strange reason.

So to talk a little bit about debugging, Mac OS X debugger is GDB. It's currently based on the FSF 5.0 release, and for Jaguar, I believe it's based on 5.1. Is that right? Yeah. And it has a lot of additional commands. I don't have space to go into them all. There's a session on Friday that we'll talk about that. We have a future breakpoint that you can set for code that hasn't been loaded in yet. We can print an obc object, It actually sounds almost like a reflection kind of thing.

You can ask for information on all kinds of properties of Mach, such as the Mach tasks. I found info Mach tasks to be kind of interesting because it actually lists all the tasks, including the ones that don't belong to you. But I didn't actually go in and try to see what I could do to the tasks that don't belong to me. That seemed like an opportunity. Thank you.

We've heard quite a bit about GCC3 already. I'll just cover a couple bits that are specific to the command line. The old one's based in 295. The new one will be based on 3.1, unless the FSFP will drag their feet any longer on the 3.1 release. We have the optimization C++ conformance. We have what's called PFE for precompiled headers. It's a different strategy. I forgot to mention the command line option. The command line options are -dumppch to write out the headers and then -loadpch to load them in again. The release notes for Jaguar will go into that in more depth.

There is something that's important to know about this, though, which is in this transitional period there are a number of places where you can get hosed by GCC3. For instance, its optimization characteristics are different. O3, for instance, will inline code, could cause your program to bloat. There are C++ conformance issues where GCC2 let things go and GCC3 says, "Uh-uh, not going to allow that."

So your code simply fails to compile. Indeed, in our very own OS X sources, we ran into a few of those, and people had to go fix their code. Anyway, so as a workaround, we set things up so that both compilers will be available in Jaguar. And this will be true of the ship Jaguar as well as the previews that you have. So the rule is 2952 is always going to be available at user bin GCC2. That's the permanent home of the executable. Latest of the version 3, this will go for 3.2, 3.3, or whatever, user bin GCC3. And we take user bin CC and GC and we symlink to one or the other. And then to switch back and forth, we have a script called GCC select. And you just say GCC select 2, GCC select 3. And this will flip all the symlinks. So you can have a makefile that if it refers to GC2 literally, then you can always refer to that. You don't have to worry about the switching. Anything where you just want to refer to CC and try it both ways, SelectScript is available. And again, that's something where it's going to be part of Jaguar for some time.

For Project Builder, we do have a way to pull in legacy targets into Project Builder. It sets up a lot of defaults and flags. It gives you easier access to documentation. As I mentioned earlier, there is a PBX build command. Sean will do the demo. I have to apologize for showing the GUI in this.

This was actually the largest part of the demo, and I was going to demonstrate, if I get into Finder. I lost my terminal, didn't I? Sorry. And I forgot to change that too. But it's real easy to do so if we remember the command and can read it. Alt, right. True aficionados put terminal in their startup.

I can never remember the path to the project builder script, or program, I should say, so... I told you I can never remember it. Project builder. All right, as Stan just said, one of the things you can do is use project builder to build a legacy application, which is your normal Unix type application. So we'll do that. Set all the defaults here. Great. We don't need the release notes. Create a new project. We're gonna create an empty project because it's not one of the others.

Da da da, we'll call it, I'm going, oh. The thing I'm going to be wrapping this round is the GNU Hello World program. And you may think that a Hello World program wouldn't be very complex, but this is GNU. So what did I call it? Now, first thing we need to do is get the files. And I have this under new project, under project, add files. Thank you.

There are the files that I've gotten. Just select them all. Add. We want to copy rather than just refer to them, so that we'll copy the files in there. We're all done. Actually, we're not. The first thing you need to do with the GNU Hello World program is you need to configure it. So we will add a new target.

which is a legacy makefile, which is to say it will run a script rather than using one of its internal build paradigms. Now let's call it configure. And the program it's going to run is binsh. And the action is./configure. And we need to tell it which directory to use. And it's already there. We're all done. Don't sit there. And now let's build it. And as you can see, it ran configure. That was almost as easy as doing it from the command line.

Now that we've done the configure, however, we actually want to build the program. So we do a new target, again, a legacy make file. Let's call this one hello, because that's what it'll be building. All the actions are right. We wanna set the directory, 'cause otherwise it will use the build directory and the program wouldn't be there. Now we build. Oops, first we have to select the right target.

Let's try building it again. And there. And now we can run it. We have not set the executable, so there's nothing to run. Setting the executable is easy. want build, no, sorry. It's under here, new custom executable. And the executable name is, hello, ah, Executable path is, come on. Maybe hello.

Build and run. And look, it printed "Hello World." Now, that might seem like a whole lot of work for just Hello World, and you'd probably be right. However, if you have a more complicated program, you could then use this to set the... use the nice graphical interface to the debugger, which I admit is pretty nice and almost as nice as Emacs interface to the debugger, which is my personal favorite. Emacs. There's always VI's interface to the debugger. Bang, bang, GDB. And voila, and that's my demo. I think that's it. Thank you.

The interesting part about GNU Hello is it's actually a template. It's not to the point that it does anything, but it provides a template for what a GNU program is supposed to look like. In case anybody is wondering why there is such a thing. Anyway, Godfrey is here to tell us about the technical documentation. Thank you all for your time.

Thank you, Stan and Sean. Unfortunately, we have extremely little time. We started late due to a small electrical problem, so we will not have time today for Q&A. Just for your information, technical documentation, command line tools all have man pages, and you obtain that man page at the terminal prompt, man tool name, as on any Unix system. There are reference documentation also in the developer documentation dev tools directory, And there's specific detailed information for the compiler, preprocessor, GDB, the macro runtime, and these are all available in PDF and HTML forms.

More information is available through various URL tools. These are all wrapped together onto the master URL list, which we list-- for everyone, a roadmap. Next sessions to look at. For porting Unix apps to Mac OS X, there's a session immediately following this in Civic Auditorium. We have a feedback forum for technical documentation tomorrow, as well as the first of our project builder forums and our performance tools tomorrow. I'd be delighted to see you all there. And with that, we're going to have to end the session because we are already over time. Thank you very much for attending. Thank you.