Skip to content

Commit bfae4cd

Browse files
authored
Add remotely debuggable Swift document (bazelbuild#576)
1 parent 73a07d0 commit bfae4cd

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ bazel run @build_bazel_rules_swift//tools/dump_toolchains
107107
**Linux hosts:** At this time, Bazel uses whichever `swift` executable is
108108
encountered first on your `PATH`.
109109

110+
## Supporting remote builds
111+
112+
To make remote builds work correctly with debugging and general
113+
reproducibility see [this doc](doc/debuggable_remote_swift.md)
114+
110115
## Future Work
111116

112117
- Support for building and linking to shared libraries (`.dylib`/`.so`) written

doc/debuggable_remote_swift.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Debuggable Remotely Built Swift
2+
3+
This is a guide to using remotely built Swift modules in local debug builds.
4+
5+
At the time of writing, `lldb` depends on debugging options embedded in `.swiftmodule` files. These options include paths that are only valid on the build host. For local builds, this all just works, but for remote builds, it doesn't.
6+
7+
The solution is two parts:
8+
9+
1. Use `-no-serialize-debugging-options` globally, to prevent embedded paths
10+
2. Use `-serialize-debugging-options` locally in one empty module
11+
12+
Globally disabling debugging options makes those `.swiftmodule`s usable on any machine. Locally enabling debugging options for one module provides lldb with enough info to make debugging work.
13+
14+
An lldb bug has been filed here: https://bugs.swift.org/browse/SR-11485
15+
16+
### Disable Debugging Options Globally
17+
18+
To globally disable debugging options, use the `swift.cacheable_swiftmodules` feature in rules_swift. For example, your `.bazelrc` could look like this:
19+
20+
```
21+
build --features=swift.cacheable_swiftmodules
22+
```
23+
24+
What this does is ensure all modules are built explicitly with `-no-serialize-debugging-options`. It has to be explicit because `swiftc` enables `-serialize-debugging-options` in some cases.
25+
26+
### Add Debug Build Config
27+
28+
In a `BUILD` file - in this example, the root `BUILD` file, define the following [`config_setting`](https://docs.bazel.build/versions/master/be/general.html#config_setting). This will allow targets to conditionally depend on the locally built debugging module.
29+
30+
```python
31+
config_setting(
32+
name = "debug",
33+
values = {
34+
"compilation_mode": "dbg",
35+
},
36+
)
37+
```
38+
39+
### Define Local Debug Target
40+
41+
In the `BUILD` file of your choice, define a `swift_library` with:
42+
43+
* A single empty source file
44+
* Enables `-serialize-debugging-options`
45+
* Built locally, not remote - using the `no-remote` tag
46+
47+
Here is one way to define the `BUILD` file, using a [`genrule`](https://docs.bazel.build/versions/master/be/general.html#genrule) to create the empty swift file.
48+
49+
```python
50+
genrule(
51+
name = "empty",
52+
outs = ["empty.swift"],
53+
cmd = "touch $(OUTS)",
54+
)
55+
56+
swift_library(
57+
name = "_LocalDebugOptions",
58+
srcs = [":empty"],
59+
copts = [
60+
"-Xfrontend",
61+
"-serialize-debugging-options",
62+
],
63+
module_name = "_LocalDebugOptions",
64+
tags = ["no-remote"],
65+
visibility = ["//visibility:public"],
66+
)
67+
```
68+
69+
### Update Top Level Test Targets
70+
71+
Finally, for each top-level test target (`ios_unit_test`, `ios_ui_test`*, etc), conditionally add the local debugging module to the deps. This is done via the [debug config](#add-debug-build-config). In the past this also had to be done for `ios_application` targets but that has since been fixed in lldb.
72+
73+
```python
74+
debug_deps = select({
75+
"//:debug": ["//some/path:_LocalDebugOptions"],
76+
"//conditions:default": [],
77+
})
78+
79+
ios_unit_test(
80+
name = "...",
81+
deps = debug_deps + [
82+
# ...
83+
],
84+
# ...
85+
)
86+
```
87+
88+
##### Note about `ios_unit_test`
89+
90+
When using a test host, the debugging module must be added to the test host target only, not the unit test target. _However_, for tests without a test host, the debugging module must be added to the unit test target.
91+
92+
### LLDB Settings
93+
94+
Additional settings may be required, depending on your build setup. For example, an Xcode Run Script may look like:
95+
96+
```
97+
echo "settings set target.sdk-path $SDKROOT"
98+
echo "settings set target.swift-framework-search-paths $FRAMEWORK_SEARCH_PATHS"
99+
```
100+
101+
Other settings you can try customizing are:
102+
103+
* `target.clang-module-search-paths`
104+
* `target.debug-file-search-paths`
105+
* `target.sdk-path`
106+
* `target.swift-extra-clang-flags`
107+
* `target.swift-framework-search-paths`
108+
* `target.swift-module-search-paths`
109+
* `target.use-all-compiler-flags`
110+
* `symbols.clang-modules-cache-path`
111+
112+
These settings would be written to some project specific lldbinit file which you can include directly in Xcode's scheme.

0 commit comments

Comments
 (0)