Skip to content

[docs] Improve instructions for using Ninja with Xcode & move them to GettingStarted.md #61713

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 1 addition & 27 deletions docs/DevelopmentTips.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,31 +97,5 @@ By default, `build-script` will spawn as many parallel compile / link jobs as th
For example, to have `build-script` spawn only one link job at a time, we can invoke it as:

```
build-script --llvm-cmake-options==-DLLVM_PARALLEL_LINK_JOBS=1 --swift-cmake-options=-DSWIFT_PARALLEL_LINK_JOBS=1
build-script --llvm-cmake-options=-DLLVM_PARALLEL_LINK_JOBS=1 --swift-cmake-options=-DSWIFT_PARALLEL_LINK_JOBS=1
```

## Using ninja with Xcode

Although it's possible to build the swift compiler entirely with Xcode (`--xcode`), often it's better to build with _ninja_ and use Xcode for editing and debugging.
This is very convenient because you get the benefits of the ninja build system and all the benefits of the Xcode IDE, like code completion, refactoring, debugging, etc.

To setup this environment a few steps are necessary:
* Create a new workspace.
* Create Xcode projects for LLVM and Swift with `utils/build-script --skip-build --xcode --skip-early-swift-driver`. Beside configuring, this needs to build a few LLVM files which are needed to configure the swift project.
* Add the generated LLVM and Swift projects to your workspace. They can be found in the build directories `build/Xcode-DebugAssert/llvm-macosx-x86_64/LLVM.xcodeproj` and `build/Xcode-DebugAssert/swift-macosx-x86_64/Swift.xcodeproj`.
* Add the `swift/SwiftCompilerSources` package to the workspace.
* Create a new empty project `build-targets` (or however you want to name it) in the workspace, using the "External Build System" template.
* For each compiler tool you want to build (`swift-frontend`, `sil-opt`, etc.), add an "External Build System" target to the `build-targets` project.
* In the "Info" section of the target configuration, set:
* the _Build Tool_ to the full path of the `ninja` command
* the _Argument_ to the tool name (e.g. `swift-frontend`)
* the _Directory_ to the ninja swift build directory, e.g. `/absolute/path/to/build/Ninja-DebugAssert/swift-macosx-x86_64`. For debugging to work, this has to be a debug build of course.
* For each target, create a new scheme:
* In the _Build_ section add the corresponding build target that you created before.
* In the _Run/Info_ section select the built _Executable_ in the build directory (e.g. `/absolute/path/to/build/Ninja-DebugAssert/swift-macosx-x86_64/bin/swift-frontend`).
* In the _Run/Arguments_ section you can set the command line arguments with which you want to run the compiler tool.
* In the _Run/Options_ section you can set the working directory for debugging.

Now you are all set. You can build and debug like with a native Xcode project.

If the project structure changes, e.g. new source files are added or deleted, you just have to re-create the LLVM and Swift projects with `utils/build-script --skip-build --xcode --skip-early-swift-driver`.
95 changes: 77 additions & 18 deletions docs/HowToGuides/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ toolchain as a one-off, there are a couple of differences:
- [Editing code](#editing-code)
- [Setting up your fork](#setting-up-your-fork)
- [First time Xcode setup](#first-time-xcode-setup)
- [Using Ninja with Xcode](#using-ninja-with-xcode)
- [Other IDEs setup](#other-ides-setup)
- [Editing](#editing)
- [Incremental builds with Ninja](#incremental-builds-with-ninja)
Expand Down Expand Up @@ -270,24 +271,6 @@ In the following sections, for simplicity, we will assume that you are using a
unless explicitly mentioned otherwise. You will need to slightly tweak the paths
for other build configurations.

### Using both Ninja and Xcode

Some contributors find it more convenient to use both Ninja and Xcode.
Typically this configuration consists of:

1. A Ninja build created with `--release-debuginfo`.
2. An Xcode build created with `--release-debuginfo --debug-swift`.

The Ninja build can be used for fast incremental compilation and running tests
quickly. The Xcode build can be used for debugging with high fidelity.

The additional flexibility comes with two issues: (1) consuming much more disk
space and (2) you need to maintain the two builds in sync, which needs extra
care when moving across branches.

### Integrate a Ninja build with Xcode
It is possible to integrate the Ninja build into Xcode. For details on how to set this up see [Using Ninja with Xcode in DevelopmentTips.md](/docs/DevelopmentTips.md#using-ninja-with-xcode).

### Troubleshooting build issues

- Double-check that all projects are checked out at the right branches.
Expand Down Expand Up @@ -368,6 +351,82 @@ select the following schemes:
run.
<!-- TODO: Insert SourceKit/stdlib specific instructions? -->

### Using Ninja with Xcode

Although it's possible to build the toolchain entirely with Xcode via `--xcode`,
a more efficient and robust option is to integrate a Ninja build with Xcode.
This is also convenient in that you can navigate, build, run, edit, and debug in
Xcode while retaining the option of using Ninja on the command line.

Assuming that you have already [built the toolchain via Ninja](#the-actual-build),
several more steps are necessary to set up this environment:
* Generate Xcode projects with `utils/build-script --skip-build --xcode --skip-early-swift-driver`.
This will first build a few LLVM files that are needed to configure the
projects.
* Create a new Xcode workspace.
* Add the generated Xcode projects or Swift packages that are relevant to your
tasks to your workspace. All the Xcode projects can be found among the
build artifacts in `build/Xcode-DebugAssert`. For example:
* If you are aiming for the compiler, add `build/Xcode-DebugAssert/swift-macosx-*/Swift.xcodeproj`.
This project also includes the standard library and runtime sources. If you
need the parts of the compiler that are implemented in Swift itself, add the
`swift/SwiftCompilerSources/Package.swift` package as well.
* If you are aiming for just the standard library or runtime, add
`build/Xcode-DebugAssert/swift-macosx-*/stdlib/Swift-stdlib.xcodeproj`.
<!-- FIXME: Without this "hard" line break, the note doesn’t get properly spaced from the bullet -->
<br />

> **Warning**
> Adding both `Swift.xcodeproj` and `LLVM.xcodeproj` *might* slow down the IDE
and is not recommended unless you know what you're doing.

In general, we encourage you to add only what you need. Keep in mind that none
of the generated Xcode projects are required to build or run with this setup
because we are using Ninja—an *external* build system; rather, they should be
viewed as a means of leveraging the navigation, editing and debugging features
of the IDE in relation to the source code they wrap.

* Create an empty Xcode project in the workspace, using the
_External Build System_ template.
* For a Ninja target that you want to build (e.g. `swift-frontend`), add a
target to the empty project, using the _External Build System_ template.
* In the _Info_ pane of the target settings, set
* _Build Tool_ to the path of the `ninja` executable (the output of
`which ninja` on the command line)
* _Arguments_ to the Ninja target name (e.g. `swift-frontend`)
* _Directory_ to the path of the build directory associated with the Ninja
target. For Swift targets, including the standard library and runtime, you
want `path/to/swift-project/build/Ninja-*/swift-macosx-*`
* Add a scheme for the target. Be sure not to select a target from one the
generated Xcode projects.
* > **Note**
> Ignore this step if the target associates to a non-executable Ninja target
like `swift-stdlib`.

Adjust the _Run_ action settings of the scheme:
* In the _Info_ pane, select the _Executable_ built by the Ninja target from
the appropriate `bin` directory (e.g. `build/Ninja-*/swift-macosx-*/bin/swift-frontend`).
* In the _Arguments_ pane, add the command line arguments that you want to
pass to the executable on launch (e.g. `path/to/file.swift -typecheck` for
`swift-frontend`).
* You can optionally set the working directory for debugging in the
_Options_ pane.
* Configure as many more target-scheme pairs as you need.

Now you are all set! You can build, run and debug as with a native Xcode
project. If an `update-checkout` routine or a structural change—such as when
source files are added or deleted—happens to impact your editing experience,
simply regenerate the Xcode projects.

> **Note**
> * For debugging to *fully* work for a given component—say, the compiler—the
`build-script` invocation for the Ninja build must be arranged to
[build a debug variant of that component](#debugging-issues).
> * Xcode's indexing can occasionally start slipping after switching to and back
from a distant branch, resulting in a noticeable slowdown. To sort things
out, close the workspace and delete the _Index_ directory from the
workspace's derived data before reopening.

### Other IDEs setup

You can also use other editors and IDEs to work on Swift.
Expand Down