Video hosted by Apple at devstreaming-cdn.apple.com

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: wwdc2012-404
$eventId
ID of event: wwdc2012
$eventContentId
ID of session without event part: 404
$eventShortId
Shortened ID of event: wwdc12
$year
Year of session: 2012
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2012] [Session 404] Building fr...

WWDC12 • Session 404

Building from the Command Line with Xcode

Developer Tools • iOS, OS X • 50:28

New features in Xcode make it easier than ever for command line developers to manage powerful build configurations in both Terminal and the Xcode IDE. Discover how to adapt your makefile-based projects to use the latest LLVM compilers, switch effortlessly between installed toolsets, and learn best practices for building from the command line.

Speakers: Anders Bertelrud, Daniel Dunbar

Unlisted on Apple Developer site

Downloads from Apple

HD Video (395.4 MB)

Transcript

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

Good afternoon. I'm Anders Bertelrud. Welcome to session 404, Building from the Command Line with Xcode. A lot of the Xcode sessions in this week are going to talk about various aspects of the Xcode user interface, the editor, source code management, building, debugging. But in this next hour, we're going to focus on working with your projects from the command line.

So the first question is, why? Well, why work from the command line when there's a great IDE? Turns out that it's both interesting and useful to do that, and we'll show many examples of that in this session. And so after convincing ourselves that it's useful and interesting, we're going to talk about how to use Xcode build. Xcode build is the main gateway to Xcode from the command line.

After that, we'll look at how you can customize your project in the Xcode user interface so that you can use Xcode build with it more effectively. You can set up some defaults that you can then invoke from Xcode build. Then we'll look at automating your build workflow using Xcode build and... Excellent. You're in the right session. And after that, we're going to take a look at how you can invoke the compiler and linker directly if you're using a project that doesn't even use the Xcode build system.

So first of all, why? Well, in a word, it's automation. So on a Unix-based OS like Mac OS X, the command line tools are the way to automate things, whether it's through shell scripts or Python or Perl or anything like that. The automation works by invoking commands. And so using this, you can set up nightly builds or daily builds so that when you come into the morning, there's a ready-built version for the testers or for yourself to use.

And of course, you can integrate with continuous integration systems. Some of you may not be familiar with that, so we'll talk more in detail about that in the second part of the talk, what that is. And then a secondary use for command line tools are if you have a build system that doesn't use Xcode at all.

So you may have a cross-platform project that you're working on that works on a lot of different systems. And Xcode, of course, is an OS X app, so you may need to use the linker and compiler directly in order to build your project. And there are various systems like Mac Ports and Fink and Homebrew that use the tools directly, the compiler and linker.

So in order to use Xcode Build, let's take a look first, what is Xcode Build? So Xcode Build, it's a command line tool, and it allows you to work with the projects and workspaces. Xcode 4 introduces the concept of workspaces, and Xcode Build understands both, projects and workspaces.

And what it lets you do is to perform batch operations on your projects and workspaces. What I mean by that is, it's not a tool for opening up your project in a console editor and for customizing your project or working with it at a fine-grained level. It's a tool for operating on projects and workspaces as a whole. So you can build them, you can archive them, and for OS X projects, you can do unit testing automatically. And you can also query your projects and workspaces for information, such as what schemes they define, what the names of the targets are, those kinds of things.

And Xcode Build is a very rich tool that has a lot of options, and there is an excellent man page, the standard Unix man command for manuals. It gives you a lot of information. We're going to cover some of it in this talk, but there's a lot more information using man Xcode Build.

Okay, so let me bring up a Terminal window because no command line tool session would be complete without Terminal. And I'm just going to show you some of the most common uses of it and then we'll get progressively more advanced. So first of all, Xcode build works like many of the other build tools that you may be familiar with.

Make or Ant or any of the other ones like that where you first change directory into the directory that contains your project. And then the simplest thing to do is to just invoke Xcode build and that will build your project using the settings that you had the last time you opened it in Xcode. So the same thing that would happen if you hit Command R to build and run in Xcode itself.

So when you do that, you get a bunch of output. The first part of it we see here. And that's the build log and so it shows you the details of everything that happened during the build. So let's take a look at what that actually is showing you. So first of all, the build log is a little bit more complex.

The build log has a hierarchical structure and at the top level are the one or more targets that you're building as part of that build log. It could be just your single app or it could be a very complicated workspace that has 50 projects, each of which has 10 targets. So at the top level, the targets. And then for each target, it's built using one or more commands.

You could have a very large project such as the WebKit, the project that builds WebKit that has thousands of compiler invocations. But you could also have a target whose only purpose is to run a custom shell script to just produce some file that you have set up. In that case, it's just one command for the target. But in either case, that's the second level underneath the targets. And then of course, we hope that our build completes without a single warning or error, but that's not always the case.

So if there are diagnostics, they show up underneath the commands. So even when you're looking at a flat text output, that's the basic structure of a command, of a build log. So looking at this build log again, you see at the top there is a fairly handy summary of what it is you're actually building. In this case, just the one target. But one of those will show up at the beginning of each target.

And then of course the commands. Each one has a summary line at the beginning, and then the actual commands that get run underneath. On a console they'll actually wrap, but I made them not wrap here just to show the basic structure of it. Further on down we see, for example, an interface builder compilation. Those are resources too that get compiled into a runtime format.

A pre-compilation of a header to speed up the rest of the build, and then some compiler commands. So if you look at this, you'll see every little switch that Xcode is actually generating. So Xcode, when it compiles, most of you know this, but some may not, is actually invoking the same command line tools that you would invoke outside of Xcode.

And it's passing arguments that are generated based on the configuration of your project. So at the bottom here we have one or more link commands. If you're building something that gets loaded. So this is the first one that gets linked. One or more because there could be multiple architectures. And then hopefully the build succeeds. So that's the status line at the end. So this is really the same thing that we're seeing in the Xcode console, basically. The Xcode run log. And so at the top you have some filter fields.

Just to let you narrow things down, and then you see the target level here. Just trying to draw an association here between the Xcode build output and what you may already be familiar with in the IDE. You see the commands underneath in the IDE, and then the status line at the end. So that's really the same as the build log on the console. Except for one thing. You don't actually see the commands in the IDE, right? Or do you? You actually do.

You see the summary command, but then there is a little widget on the right side, which you can click, and you can actually see the command that Xcode will execute, which is the same thing you see on the console. So if you twist that down by clicking on the widget, you'll see actually the same summary line as you see on the console. You'll see the changing of the directory into the directory that contains the project, setting environment variables, and invoking the full command.

And here's a little useful tip. You can actually copy the commands from the build log inside. You can actually copy the commands from the build log inside of Xcode and paste them into a terminal window to change the directory to the right place, set the right environment variables, and call the right command. This can be useful if you want to invoke it, for example, with extra verbosity to see exactly what the compiler is doing. So that's a useful tip.

So after having seen the build log and what the output is, one of the questions is, where do the outputs go? If you build and run in Xcode, the IDE, then Xcode puts them someplace, and you can use show in finder to actually get to the outputs, or if you make an archive, it shows up in the organizer. But on the command line, we need to know where they go.

So there are three kinds of outputs. There are the intermediates, of course, which are the compiled code and the generated sources. These are the files that you don't actually ship to your users. They're just there to make the builds go faster if you do iterative builds. And so you can control that using a build setting called objroot. It's kind of an archaic name, but it's for where the objects go. So that's the root directory where the objects go. And there's a shared precomp dur that's similar for the precompiled headers.

They're shared because they're shared between the targets in your workspace. The second level of output are the debug products. So these are similar to what you would ship to your users, but they are built maybe without optimization by default. They're built with extra debug symbols. And so they're more suitable for debugging than the release products are.

So there is a setting that controls where they go. That's the SIM route for the symbolicated routes. And that's also where the DSIM files go. These are what the files that contain the DWARF debug output that get included automatically in an archive when building from Xcode itself. The release products go into what we call the distribution route, DST route, and these are the actual release products that are built with full optimization. And if you have specified an install path, which you would not do for an app, but for example, if you have a kernel extension, then they get put underneath the dest route in a path which is equivalent to the install route.

So that's where the outputs go. And so you can customize -- so that's something you control on an invocation basis when you invoke Xcode build. But you can also customize your project and set things that you want to be true every time you build with Xcode build. And there are two main ways to do that. You control that using schemes.

That's the main way. But you can also override individual build settings. So any build setting that you can set in your project, you can actually override on the Xcode build command line. We'll look at detail how to do that. And so that involves configuration files. There is a flag to Xcode build to use a particular configuration file full of settings. But you can also specifically set architectures, SDKs, or any other build settings that you have the name of.

So just a quick note about schemes. So there will be a session tomorrow in Marina at 4:30, same time as this, talking in detail about schemes and how to put them to good use in Xcode. But just briefly here today so the rest of the content makes sense.

A scheme is essentially a collection of targets to build. For a simple iOS app, it would probably be just a single app. For something else like client server, it may be things that have meaning to you as a user to go together. There's some semantic connection even though there may not be a technical connection.

So you can collect any arbitrary collection of targets you want into a scheme and say, "Yep, when I build this scheme, I want all these guys built." And you can then specify a configuration to use for building. You can specify a different configuration for archiving. Typically you would use debug for debug builds and release for archive builds. You can also specify an optional collection of tests that you want to run. So unit tests are a great way to test your code. Make sure that you don't introduce any regressions when you make changes. And you can specify those in a scheme as well.

In addition, you can define anything that you can run as a shell script, you can actually define as a pre-condition or a pre-action or post-processing action. So you can say, for example, that after my build, I want to go ahead and upload my build product to an internal staging server I'm going to use for testing or anything like that.

So in order to know which schemes to build from the command line, you want to be able to see which schemes are in the project. And both workspaces and projects can contain schemes. So in this case, we're going to list the schemes in a workspace here. So we use the Xcode build command, and we specify dash workspace to give it the name of the workspace.

And then the list command will tell you what's in the workspace. In this particular workspace, there are just two schemes. There could be other things in the workspace, but that's all we have right here. But those names are the actual names that you would then specify on the command line.

Now, if we look in the IDE, we see the exact same thing in the scheme manager. So you have here, for example, baffle-os10 and baffle-ios, which are, in this case, two sample projects in this workspace. So that's the correlation there with the IDE and the command line. And then to use the schemes, you basically configure it in Xcode, and then you use it in Xcode. build. That's the general pattern here.

And the Scheme flag is the flag that you use when you build in Xcode. So, pretty straightforward. So some ideas for how to customize Schemes are just to show you some of this UI if you're not familiar with it. Again, the session tomorrow at 4:30 gives details. But you can set up what happens when you build, you can set up what happens when you archive.

And here's an example, not sure if it's readable, but it's an example of invoking a shell script after building that uses SFTP to actually put the archived binaries up onto a server, and then sends out an email letting you know that a new build is available. For example, you might have this run every night so that every morning when you come in, there's a new build.

So how do you specify a scheme on the command line? So, well, the scheme option, as I mentioned. And make sure you put the exact name that you saw in the list as output from the list flag. Another thing you can specify as an override are the SDKs.

So, for example, you may have a project that you currently have set up to build against 10.7, but you want to try building it against 10.8, see what kind of warnings come out. You can see what SDKs are available for you to build against by using the "show SDKs" flag.

And I know I'm going through these fairly quickly, but these are all documented, again, in the man page in full detail. This is mainly to get you aware of what settings are available. We'll also see later on in the talk how to put this to practical use in a demo.

So, I realize I'm going fairly quickly through these. On the left side, you see the actual description of what the SDK is, and on the right, what the actual name of it is, the identifier that you need to pass on the command line. And so, use the -sdk flag to specify one of those.

[Transcript missing]

Or, as I mentioned, you can set it in the environment. And in this case, you want to just set the same thing. You export a variable with the same name, and then just invoke Xcode build. And the same thing will happen. So there are a lot of build settings.

And we have great documentation on the details of that. It's a document called Xcode build settings reference. And it's available inside the Xcode built-in documentation, of course. It's also available as both HTML and a PDF file on the developer resources PDF file, so you can put it on your iPad and read at the beach, of course.

What else could be better? So to put this all together, we looked at different settings here, and before we go to a demo a little bit later, I'm going to show you what a realistic command line invocation of Xcode build would look like for real. So I'm going to use the backslash notation here, which is the line continuation in shell syntax. So Xcode build, of course. And then you need to specify the workspace, again, because your directory may contain multiple projects and workspaces, so you need to tell Xcode which one to use.

You'll want to specify a scheme specifically. You don't want to leave that out, because if you leave it out, Xcode will use the active scheme in the workspace. But the active scheme is what you've chosen in the pop-up in Xcode, so that means that you don't really get predictable results.

You get whatever the active chosen scheme is for you the last time you open it in the workspace. And again, this automation, a lot of it is about predictability, right? So you want to make sure that you really specify what it is you want to build, especially if you're doing that through a nightly build script or something like that.

The next thing is you can optionally specify an SDK. If you don't specify one, it will use whatever is set in the target. But if you specify one, like in this case, you can actually test build against a different SDK that may be useful to see what warnings show up, those kinds of things.

And then I'm going to override the three build settings that I mentioned earlier: obdroute, symroute, and destroute. In real life, you wouldn't want to send those outputs to temp because that will go away when your machine is rebooted. If you're doing a nightly build, you'll actually want to put those someplace that you can get back to if there turns out to be a problem with the build.

So there's one more question, though, that needs to be answered. And that is, if I just run Xcode build, well, which Xcode build? There's one Xcode build for each Xcode. So all of you have Xcode 4.3. As of yesterday, you have 4.3.3. That's the latest GM version of Xcode.

That's the one you need to use to submit to the App Store. It's the one you need to use for the final build of your apps. And it's the production Xcode. And so you'll still want to have that on your system. But as of yesterday, you also have an Xcode 4.5 preview.

So now you have two Xcodes on the system. And I'm sure you're eager to try out what all the new things are in Xcode 4.5, the SDKs. But you still need to be able to choose which Xcode build to invoke, which build system, which set of tools get invoked. And each of these Xcodes contains inside of it a set of the low-level command line tools-- the compiler, which is Clang. Clang for us. The linker, lex, yak, make, even some subversion and get. Those commands are all inside of the Xcode app wrapper.

But there's another set of them as well that are in the preview. So that's a preview release of the compiler, the linker, et cetera. And you don't want to use that for a production build of your OS. So which Xcode build gets chosen? And the answer is there's a tool called Xcode Select.

And that is in user bin. And what it does is it sets the default Xcode that gets used when you type Xcode build on the Terminal window. And it has an option called print path that will just give you what is the path of the current one. So assuming you installed Xcode, the GM release from the App Store, it will be an application's Xcode, and the developer directory underneath it will be the default.

But you can switch that to be the 4.5 preview in this case, and you can just provide the path to the app, and then Xcode Select will actually set the developer path underneath there to be the place where it looks for headers, libraries, for the command line tools by default when you're building from the command line. So now if I say Xcode build-version, you'll see that this has been set to the preview.

So that sets it for the entire system. And what it actually does is it sets the default that's used by a bunch of tools that are in user bin. So there's an Xcode build in user bin that calls the right one in whatever Xcode select you have chosen. There's XCRUN, which is a tool I haven't mentioned yet in this talk, which is also very handy.

I'll talk about it in a moment. OpenDiff is a tool that lets you open up -- it's the same as diff, but instead of showing you the differences graphically -- or differences in the console, it opens it up inside of a tool called File Merge and shows your graphical difference. Instruments is the command line interface to the Instruments developer tools app.

And there are also a variety of other tools in there that look at the setting. And again, that's all on the man pages. XCRUN is particularly interesting. And so let's take a closer look at that. So Xcode build is what you use when you want to simply build or operate on an entire Xcode workspace or project.

XCRun is finer grained than that. It's a tool that lets you run a particular command line tool that lives inside of Xcode. So the compiler, the linker, those kinds of things. It's context sensitive, meaning that it depends on what build settings you pass in as override, it depends on the SDK you've chosen, and returns you the appropriate tool to use for those conditions.

And it also falls back on using the standard Unix path variable, so that if you ask for the path of a command that doesn't exist inside of Xcode, it will return one from the system. So you always get a good result back if there's anything at all in the path.

There are two modes to use this. One is to just get back the path of the tool. So that's the find command, the find option to that. The second mode is to prefix the path of the tool. So you prefix the name of the tool with XCRun, and then provide the arguments. So in that mode, XCRun will look up the tool, find the path, and then invoke it with the arguments.

So an example of that is finding the CC alias for the Client Compiler will return the full path that's inside of Xcode. But invoking it directly is if we just invoke the compiler prefix with XCRUN, we'll just invoke the compiler. And this can be particularly useful when you are configuring a makefile or something like that.

Another use of XCRUN is for the version control commands. So if you recall, I mentioned that Xcode also includes Git, SVN, and those commands inside of it. So if you say XCRUN find Git, it will find the one that's inside of whatever Xcode you've selected. And so when you go to run Git from the command line, then you can use XCRUN as a prefix, but you can also take advantage of shell aliases and set up, in this case, this is bash syntax, which is the default shell.

So you can set up that Git is an alias for XCRUN Git. So in this case, every time you type Git, it's actually going to call XCRUN Git. So you'll get whatever Xcode has been selected at that time. So then if I just say Git-version, it actually calls XCRUN Git, which redirects inside of Xcode and invokes the right one.

But there's one caveat here, or something to keep in mind. It's really convenient to have a default Xcode when you're just typing at the Terminal, and you just type Xcode build and those things. But again, if you're automating this and running this from a nightly script, you really want to make sure that you're invoking a specific Xcode build. Because otherwise, if somebody uses Xcode select to change which Xcode is the default, you may get an unexpected one.

So to do that, what you want to do is you want to set the developer dir environment variable in the environment, or you could just pass it directly. There's different shell notations for doing this, but one is to use the export command. So if you set that in the environment, then Xcode build and Xcode run and all the other tools will look at that in preference to whatever you have Xcode selected.

So setting developer dir in the environment overrides whatever has been Xcode selected. So this means that for a particular invocation of Xcode build, you can guarantee that you get a certain one. That gets important for automated builds, as we'll see in the demo. And then of course XCRUN after this will find the right one. And on to Xcode build. So with that, I'd like to ask my colleague Daniel Dunbar to come up and provide a more concrete example of putting some of this to use. Thanks.

All right. Thanks, Anders. My name's Daniel Dunbar. I'm an engineer on the Apple compiler team. And what I want to do is make some of the ideas Anders talked about a little more concrete by giving an example of automating Xcode build, and, in particular, using Xcode build within the context of continuous integration.

So I hope a lot of you already know the term continuous integration. But if not, here's a slightly formal definition. So continuous integration, also referred to as CI, means defining a continuous process for integrating and applying quality checks to software development. What does that actually mean? For most developers, continuous integration is a pretty simple process.

You're working, you're developing commits to your source repository. And then somewhere else there's a continuous integration server which is watching that repository. And when you make a new commit, it's going to automatically dispatch a build of your software. Typically you'll run any automated tests that you have available. And then finally usually you'll publish those either for deployment or for further testing.

So if you're new to continuous integration, you may think, OK, when would that be useful for me? Well, there's a very compelling example we have here at WWDC. So a common problem is, as Anders mentioned, you have the Xcode GM tools. You have Xcode 4.3, and you need to be using that to work on your app.

But you might also want to start experimenting with the new preview. Maybe you're going to write some test code. Maybe you're just going to check how it builds against the new SDK. And so you'd like to build with both versions of the tools, make sure everything keeps working.

Also, I know a lot of developers have code, or some part of code, that's shared between a product for OS X and a product for iOS. If you make a change to the shared code, then you don't want to always have to switch to another target to make sure you didn't break the build on that platform. And that would be disruptive to your development. So how can we solve this? Well, it's pretty straightforward. We can use Xcode build in conjunction with a continuous integration system to automatically do these builds.

And we'll give an example of that in a second. So before I get to the example, there's a couple important points to remember when you're going to try and automate Xcode build. And this is sort of just reiterating some of the points Anders mentioned before. But these are things that are worth keeping in mind when you want to automate the build.

The first one is you should almost always be setting developer dir. You want to make sure that you're building against a very specific version of Xcode, not whatever was most recently selected on the system. Also, make sure you use the appropriate options to set the workspace, the scheme, and the SDK.

And finally, you probably want to use build settings to control where the output files go. You don't want them to go in the default derived data folder. Generally, you want them to go in a specific directory that's going to be managed by your continuous integration system. There are two other points that are a little more subtle. Oh, sorry, the settings, as Anders mentioned, are destroot, obstrut, symroot, and sharedprecomster.

So there's two other slightly more obscure points that I just want to make clear. So usually a continuous integration system runs as an alternate user. So you need to make sure that that user account on the system has accepted the license agreement. If you have complete control over the system and you know all the users, you can also accept the license agreement for all the users on the system by running sudo xcode build-license. So that will accept the license agreement for all of the users on the system.

The other important point is if you're going to do builds for iOS, then code signing needs access to appropriate development certificates. And a full discussion of this is outside the scope of this talk, but the tools that you would need to use to do that are keychain access, which manages the keychains that have the certificates, and then there's a command line tool called security that lets you access those certificates.

So with those prefaces out of the way, I'm going to go ahead and switch to the demo machine and look at an example of actually setting up a continuous integration system. So the continuous integration system here I'm using here is called Jenkins. There are a lot of free and open source -- Cool.

There are a lot of free and open source continuous integration systems out there. Some other popular ones are Buildbot or Cruise Control. The basic mechanics of all of them are very similar. So what I'm showing here should apply in almost any continuous integration system. So in this case, this system is installed on the local machine here.

Generally this would be on a server on your private network, but for the purposes of the demo, it's just on the machine right here. And what I have here is Safari, and this is showing the web access to the server. So what we're going to do is we're going to start by creating a new job for our test project.

I'm going to click New Job here, and I'm going to say I'm creating a job for Baffle. That's the name of our project. And I'm going to say I want to build a multi-configuration project. That just means that we're going to end up doing multiple builds from the same sources. I'm going to click OK.

And then we need to define the full configuration for our project. So I'll start with a simple description. As you can see, it's an amazing word game. And the first thing we need to do is tell the continuous integration system where to find the sources for our project. Again, because it's a demo, I just have the SVN repository set up on the local machine. Normally this would be out on your network.

So that's the path to the SVN repository on this machine. And then I also need to tell the system how often it should look for changes in the source repository. Again, because it's a demo, I'm just going to say, why don't you check every single minute? So now we're going to define a build variable. This is a custom variable that we're going to use eventually to select what version of Xcode to build against. So for now, I'm just going to give this build variable something called XcodeAppName, and the value I'm going to give it is just Xcode.

You'll see in a minute what I'm going to use this for. So finally, the last and really the important part, and the part that relates to this talk, is we need to define how do we build our project. And generally, you're going to do this by writing some kind of shell script.

So let's start by just taking the commands that Anders showed before and integrating them into this script. So we'll start by setting the developer dir environment variable. And you can see what I'm doing here is just using that Xcode app name variable I defined before to automatically derive the correct developer dir path. So in this case, it's going to expand to applications developer.app, and then the correct Xcode build will get invoked. And then the only other thing we need to do is set up the call to Xcode build.

So this should look very similar to what Anders showed before. We're calling Xcode build, we're setting -- passing the workspace, passing a scheme, and then we're setting up all build setting overrides so that the outputs go in the directory we want. And in this case, we're using one additional environment variable workspace here, and that's just a variable which has automatically been provided by Jenkins, and it says where it wants our outputs to go.

So with that out of the way, I'm going to go ahead and click save, and let's kick off a build. I'm going to click build now, and in a few seconds, you'll see a build has started. I can click on that, and then I can navigate to the build log. And what you see here is pretty typical of what you would see in any continuous integration system. The first thing it's doing is running a local -- an SVN checkout of our project.

You can see it's getting the shared code, the shared resources. And if I scroll down, then you'll see what it's doing after that is embedding the build. And it's just running the shell script we ran before, or that we defined before. So it's setting developer dir, and it's calling Xcode build.

And everything after that is just the build log output from Xcode build, which is the same thing you would have seen -- very similar to what you would have seen in the IDE. And if we scroll down to the bottom, then -- If we scroll down to the bottom, then you'll see that the build succeeded and the continuous integration system declared success.

Pretty simple. But that's just one build. What we wanted was a more complicated matrix. So let's go ahead and set that up. I'm going to go back to our project and click configure again. And the first thing we're going to do is just add to this to the Xcode app name. We're going to say we also want to build against Xcode 4.5 DP1. That's the default name of the Xcode 4.5 preview that you got yesterday.

So we're also going to add a new build variable. We're going to call it SDK name and we're going to put in the values of the SDKs we want to build against. So in this case, I'm putting in Mac OS X, iPhone simulator and iPhone OS. And one thing that Anders didn't mention before, when you pass the SDK name, you can actually just pass it without the version and Xcode will use whatever the most recent version of the SDK is.

So now I'm going to update my build script to use that variable. And the things I need to change are the scheme here has been hard-coded to OS X. So we're going to have to fix that, and we also need to pass the SDK option. So let's start by deriving the correct scheme based on the SDK name variable. And this is just a little bit of shell programming.

If you're not familiar with shell syntax, that's okay. It's pretty easy to figure it out. So all we're doing is we're testing if the SDK name is Mac OS X, then we're going to say the scheme name is baffle-osX. Otherwise, the scheme name is baffle-ios. And so now we just need to update this.

So here's our new build command. So we passed the workspaces before, and this time we pass in the derived scheme name variable, we pass in the SDK name, and everything else is the same. So when we save this now, you'll see that Jenkins shows us a table of all six configurations that are defined here. There's two versions of Xcode, and there's three SDKs we want to build against. So let's go ahead and kick off another build and see how things do. Again, after a few seconds, the build should show up.

And we'll click here, and what's happening is the continuous integration system is automatically dispatching the builds. And this machine, it's decided to just do two at once, and it's sort of randomly picked two of the iPhone OS -- the iOS versions in the preview. So what you can see here is those builds have actually failed.

Red indicates failure. So let's go ahead and see what that looks like. So if we go to console output and we view as plain text, so now if I scroll down to the bottom, what you can see is Xcode build is reporting this build has failed. Because Xcode build is returning an error in that case, Jenkins is also saying, oh, the build failed.

And what happened is there's two compile commands that failed. An easy way to find them is just to search for error colon in a build log that quickly takes you to the compiler output. And what happens is that the compiler output is saying that there's multiple declarations of methods contains word. So you may be wondering, well, how come the build succeeded before? Well, remember, this was the build against Xcode 4.5. Every time we come out with a new compiler, there are almost always new warnings or improved diagnostics.

And so this is a new diagnostic that got added in the Xcode 4.5 version of Clang. And because I build my project with -w error, warnings become errors. And so that caused this project to fail. So let's just go ahead and fix that. So I'll start Xcode 4.5. And you can see I've already got it set to open my project. And let me just kick off a build here.

So very quickly, the build's done, and you can see that the same diagnostic is shown here in Xcode. And this is a pretty obvious error. It turns out that there was just probably a paste error and there's a duplicate version of the method, and Clang has just decided to warn on this because it's a code cleanliness issue. So let's just delete that, and then let's commit this to our local repository. I'll type a quick message, "Fix a duplicated method name." And hit commit. So again, that went to the local SVN repository. Let me switch back now to the dashboard of Jenkins.

So as you remember, before, when we defined the SVM repository, we also set up a source control management polling behavior. So any continuous integration system is generally going to want to have some way to watch for commits. And so this system is just polling every minute. And so what you can see here is that now it's already automatically scheduled build number three because it saw I had committed a new change, and without me having to do anything, it's kicked off that build. And if I click this now, you can see, in fact, already four of the builds are already done, and they've all succeeded. And now every build is finished, and they've all succeeded.

So I made a change to the code I built and tested against one configuration in one version of Xcode, but the automated system handled automatically doing the builds in the six flavors I cared about. And so I hope that gives you an idea of why you might want to use a continuous integration system and how Xcode build can fit into that. And so with that, let's switch back to the slides.

So far, we've talked just about Xcode build. What happens when you need to work outside of Xcode? So if you're familiar with OS X development, Xcode is really the place to do OS X development. Why would you want to work outside of Xcode? Well, there's a couple reasons. The main one is there are many projects out there in the world that don't supply native Xcode projects.

A couple examples, you may have some kind of legacy code base. It's been around before Xcode, possibly. You may want to do traditional Unix development where all the tools are available in your path. Or you may be working with some kind of cross-platform open source project, and the maintainers of the project haven't defined an Xcode, haven't set up an Xcode project for that.

So I want to talk now about the tools for working outside of Xcode, and in particular what I want to convey is an understanding of the command line tools package. So this is a brief roadmap for this part of the session. So the first thing I want to just say what is the command line tools package and talk about how you install it. And then I want to give some best practices as far as when should you use the command line tools package and when do you not need the command line tools package.

So the command line tools package, what is it? Well, it's new. It was introduced in Xcode 4.3, which GMed earlier this year. And it's a separate package for doing extensive command line development. And the main thing is it's the supportive mechanism for doing Unix-style development where you need tools and headers, et cetera, to be present in /user.

So what does the package contain? Well, roughly speaking, it contains everything for command line development. It contains the same tools that Xcode and Xcode build use, but it contains them packaged in a different way. They're bundled at the standard Unix location. There's really three main pieces of the command line tools package. There's the tools themselves, things like the compiler and the linker, but there's also a version of the OS X SDK and the documentation, the man pages that we've been talking about.

And the tools that are included here aren't just the development tools like the compiler. It also includes things like debuggers as well as source control tools. So if you need SVN or Git from the command line, they're there. And in general, any tool that's available embedded inside Xcode, so for example, the tools for working with AppleScript, those are available in the command line tools package.

How do you get it? There are two ways. You can either download it from the developer resources section of developer.apple.com, or if you have Xcode installed, you can actually install directly, and I'll show that in a second. That's the easier way. So to get it from developer.apple.com, it's fairly straightforward. You just go to the resources section of the site, and then select Mac OS X downloads from the OS X development section.

From there, that takes you to this page, and the best way to find the tools is just type in command line tools for Xcode, and the top link will be the latest version of the command line tools. From Xcode, it's much simpler. All you do is open the Preferences pane and then select the Downloads section. So from there, there's a row for command line tools, and if you select Install, Xcode will handle automatically downloading and installing that package for you.

So when should you install this package? For 99% of people on a Mac, and developers included, the main reason to install the package is if you're doing some kind of open source development or you want to work with some open source component. Maybe you just want some open source server running on your machine.

So this is really the recommended practice for working with any of the open source package management facilities like Fink and Maxports and Homebrew. What you may not realize is that when you run a command like Fink install WGIT, many times what's actually happening is that the binary isn't being downloaded, but the source is being downloaded. And that tool is actually being built and installed local to your machine. So that means you need a version of the development tools, and that's really what the command line tools package is geared for, for most people.

You might also want it if you just happen to be doing extensive command line development like we talked before, whether that be you have a traditional workflow, legacy projects, or you're doing some kind of development outside of Xcode. So the key defining feature here is that you need all of the tools to be available on the command line. You want to be able to type Clang, you want to be able to type CC, and you want them to be available in your path. You want standard I/O.h to be available at user include.

The last reason is if you're only doing a small amount of development, maybe you have a server and you just need to build a small tool remotely, then the command line tools package is a very small download size. It's also completely self-contained. So the command line tools package doesn't contain the IDE or other package. It's completely independent, and that means it's about 120 megabytes. It doesn't take much disk space, very quick to download.

So that's great. And I know for almost all of you, you want to just click install on everything to get everything you could possibly have. But why might you not want to install the package? Well, My recommendation is don't install the command line tools just to get access to SVN or Git.

If that's all you want to be able to type on the command line, then instead use XCRUN and use shell aliases like Anders showed before. And in general, the message is don't install the command line tools unless you need them. They're the same tools that are in Xcode. They're not new tools. And there's only one instance of the command line tools. Because they're packaged in /user, they can only be one instance.

And that means also the install is distinct from Xcode. It's a separate copy. So what that means is if you update your Xcode, you should probably also manually update your command line tools. And if you never need them, there's no reason to do that work. So that covers the command line tools package. And I know we've covered a lot of disparate things in this talk, so I wanted to do a bit of a review of the main takeaways.

So the primary commands that you're going to use when doing command line development with Xcode are the top three listed here. So Xcode select is the tool you'll use to choose the default Xcode. Xcode build is the tool you'll use to interact with your projects, whether that be to build them, to archive them, or to query information from them. And Xc run is the tool you use to get more fine-grain information, where are individual tools, or to execute individual tools. And for all of those, and any of the other command line tools, you can use the built-in man command to get access to the documentation.

So I also wanted to provide a brief summary of the main options that you'll use for these tools, because many of them, for example, Xcode build has many more options if you look at the man page. So for Xcode select, there's really only two. Print path will show you what the currently selected default Xcode developer directory is. And you can also use dash switch to pass the path to a new Xcode that you want to become the default.

For Xcode build, the main options that you'll use are -workspace or -project. That specifies what you want to operate on. And then in conjunction, you'll use -scheme and -sdk to override what the defaults are, what was set in the project the last time it was open. As far as querying information, -show_sdks shows you the installed SDKs on your system, and -list can tell you the schemes and targets in your project. Finally, -show_buildsettings is very helpful for showing you the active build settings.

Those are the things that you could use in your configuration, or the things that get inherited because of what you've set up before. And if you need to override a build setting, the syntax you use is name, then an equals, and the value you want to set it to.

So for XCRUN, there are two main ways of invoking the tool. You can use -find to find the tool inside the app. And then you can also pass the name of the tool and then a bunch of arguments if you just want to make sure that the tool is in the right place. So for XCRUN, there are two main ways of invoking the tool. You can use -find to find the tool inside the app.

And then you can also pass the name of the tool and then a bunch of arguments if you just want to make sure that the tool is in the right place. So for XCRUN, there are two main ways of invoking the tool and then a bunch of arguments if you just want to make sure that the tool is in the right place. And for either of those, you can pass -sdk to specify the SDK to look up the tools in.

[Transcript missing]

I hope I've made a compelling argument for why you might want to look into using continuous integration for improving your own development if you aren't already. And lastly, use the command line tools package when you need to work outside of Xcode, when you need to work with some kind of open source project. So that's it for us. Thanks and have a great WWDC.