-
Notifications
You must be signed in to change notification settings - Fork 88
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
Set clang flags in lldb, propagate linker options #119
Conversation
@@ -506,6 +506,10 @@ Double check your rule declaration for naming or add `xcodeproj-ignore-as-target | |||
target_settings["SWIFT_ACTIVE_COMPILATION_CONDITIONS"] = " ".join( | |||
["\"%s\"" % d for d in defines_without_equal_sign], | |||
) | |||
target_settings["BAZEL_LLDB_SWIFT_EXTRA_CLANG_FLAGS"] = " ".join( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the key for getting swift to work again right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two issues: (1) LLDB settings need to be right or else LLDB will dump a bunch of errors and (2) the linker command for the application/test needs to include the add_ast_path
option. This linker option needs to get propagated down to the application/test target by setting linkopts
in the ObjcProvider returned from the framework target for the dependency. If we don't provide the AST option to the linker, then LLDB will not load all the necessary ASTs for swift debugging to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thx for this! I should have caught them on the description section.
Looking back, I wonder how can we know these are the steps needed without Sam's input...
Also did you manually ensure that breakpoints work in test projects in this repo? If not that's fine I can do another round of tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can explain how I went about finding these problems. I first added the line log enable lldb types -f /tmp/types.log
to my lldbinit, so that I would get very verbose diagnostic lldb logging in a file called /tmp/types.log
- I noticed the linker invocations being made by bazel to generate the final binary did not reference all the AST paths for transitive dependencies. I saw that LLDB was (1) sometimes complaining about missing ASTs and (2) in the types.log file , I noticed that the AST for transitive deps were not being loaded (They were being loaded in the working case.) So I just experimented with adding on the
add_ast_path
option to the linker and that did the trick.
As far as the actual implementation of this change, Sam noticed that framework.bzl was not propagating linker opts for transitive deps, which would explain why these linker options were not present.
- After I made that fix, debugging was still not working. The LLDB output was complaining about an error with importing GPBProtocolBuffers.h. I noticed that one of our projects at Square has a clang flag with GPB in the name (this flag affects the way we build source files that depend on google protobufs.) So I used the lldb setting for extra-clang-flags to add all the necessary clang flags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will double check the breakpoints in the test project, but note that debugging in the test project only works when sandboxing is disabled (which requires changing local bazelrc.)
In order to test this change, I updated build.sh to check for the presence of AST files in the symbol table for the binary. I think that should be sufficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the detailed explanation! Learnt that we can do logging for lldb just like we can do it for SourceKIT (so in future get the logs is the priority so we can not shooting in the dark)
As far as the testing go, I think it might be worth to call out in readme that sandbox needs to be disabled to get debugging working? Definitely a separate concern tho
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@amberdixon Can point to me where are the changes on build.sh for presence of AST files? 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@amberdixon Can point to me where are the changes on build.sh for presence of AST files? 🙏
saw the updated checks, that's awesome!
"source", | ||
"define", | ||
"include", | ||
"link_inputs", | ||
"linkopt", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the reference for objcprovider: https://docs.bazel.build/versions/master/skylark/lib/ObjcProvider.html
I searched for the string "link" and "final bundle" on this page to see what fields have to get propagated.
.bazelrc
Outdated
@@ -6,9 +6,6 @@ build --incompatible_objc_compile_info_migration | |||
# so circumvent by not using the sandbox | |||
build --strategy=Stardoc=standalone | |||
|
|||
# Debugging does not work in sandbox mode. Uncomment these lines to turn off sandboxing. | |||
# build --genrule_strategy=standalone |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left these in here by accident, will revert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmm this breaks existing tests because SomeFramework
is not found, interesting.
|
||
if [ -v BAZEL_LLDB_SWIFT_EXTRA_CLANG_FLAGS ] | ||
then | ||
cat <<-END > ~/.lldbinit-source-map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder since we are modifying this file ~/.lldbinit-source-map
why not modify ~/.lldbinit
as well here? Is it because this is our own file while .lldbinit can be shared by multiple projects/other IDE that uses lldb?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's because the developer owns ~/.lldbinit and should be allowed to put what they want in there without us clobbering it. For example, they might put Tulsi LLDB debug settings in there too or any custom debug settings they want xcode to pick up.
If we ask the developer to explicitly include this other file (~/lldbinit-source-map) in their ~/lldb-init, then they maintain control of the contents of lldbinit.
i assume you have tested against the downstream project that depends on this project? I am referring to the test script we have to ensure the correct debugging experience in various apps/tests? |
I'm seeing this too, I'll dig in. Not sure if it's regression, this wasn't working too well to begin with :( Note that because of issue #108 , you have to disable sandboxing in this repo's bazelrc to get debugging working locally. That alone is not enough however, because I still see this issue. |
I appear to have green builds now. I was probably missing a few things, but they should be resolved. |
I identified the fix to this issue and will push it shortly. LLDB settings should not point to directories that don't exist! will fix. |
Yes, I have tested with one of our internal projects at Square and confirmed that these changes fix the problem we were seeing with debugging swift dependencies. Before my changes were applied, it was not possible to evaluate variables in the debugger. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good! left a few comments, feel free to merge once they're addressed
cat <<-END > ~/.lldbinit-source-map | ||
settings set -- target.swift-extra-clang-flags $BAZEL_LLDB_SWIFT_EXTRA_CLANG_FLAGS | ||
END | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing newline
@@ -403,7 +403,7 @@ def _xcodeproj_impl(ctx): | |||
"BAZEL_BUILD_EXEC": "$BAZEL_STUBS_DIR/build-wrapper", | |||
"BAZEL_OUTPUT_PROCESSOR": "$BAZEL_STUBS_DIR/output-processor.rb", | |||
"BAZEL_PATH": ctx.attr.bazel_path, | |||
"BAZEL_RULES_IOS_OPTIONS": "--@build_bazel_rules_ios//rules:local_debug_options_enabled --features=-swift.cacheable_swiftmodules --features=-swift.use_global_module_cache", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any particular reason these features are removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of this change, debugging works in local development, even when cacheable swiftmodules are enabled. Therefore, we don't need to explicitly turn off the cacheable swiftmodules feature ... the developer can decide what to do with the feature in their bazelrc if they wish.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome!!
settings set target.sdk-path $SDKROOT | ||
settings set target.swift-framework-search-paths $FRAMEWORK_SEARCH_PATHS | ||
END | ||
|
||
set +u | ||
if [[ -n $BAZEL_LLDB_SWIFT_EXTRA_CLANG_FLAGS ]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could do -n ${BAZEL_LLDB_SWIFT_EXTRA_CLANG_FLAGS:-}
so you don't need to turn off -u
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you!! i was having trouble figuring this out.
if [[ -n $BAZEL_LLDB_SWIFT_EXTRA_CLANG_FLAGS ]] | ||
then | ||
set -u | ||
cat <<-END >> ~/.lldbinit-source-map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: indent the contents of conditional bodies
set -u | ||
|
||
BAZEL_EXTERNAL_DIRNAME="$BAZEL_WORKSPACE_ROOT/bazel-$(basename "$BAZEL_WORKSPACE_ROOT")/external" | ||
if [ -d $BAZEL_EXTERNAL_DIRNAME ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
quote the variable in case it contains a space?
if [ -d $BAZEL_EXTERNAL_DIRNAME ] | ||
then | ||
cat <<-END >> ~/.lldbinit-source-map | ||
settings append target.source-map ./external/ $BAZEL_EXTERNAL_DIRNAME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it need to be quoted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some comments from Sam that are definitely worth fixing
@@ -506,6 +506,10 @@ Double check your rule declaration for naming or add `xcodeproj-ignore-as-target | |||
target_settings["SWIFT_ACTIVE_COMPILATION_CONDITIONS"] = " ".join( | |||
["\"%s\"" % d for d in defines_without_equal_sign], | |||
) | |||
target_settings["BAZEL_LLDB_SWIFT_EXTRA_CLANG_FLAGS"] = " ".join( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the detailed explanation! Learnt that we can do logging for lldb just like we can do it for SourceKIT (so in future get the logs is the priority so we can not shooting in the dark)
As far as the testing go, I think it might be worth to call out in readme that sandbox needs to be disabled to get debugging working? Definitely a separate concern tho
…d bundling from framework.bzl.
…pilation_mode=dbg in this repo, so we can test binaries contain debug symbols
…so read the presence of the clang flags variable correctly
1d64da3
to
9bf6f0b
Compare
Debugging apps and tests with transitive swift when
cacheable_swiftmodules
was enabled was not working for us, because:link_inputs
is a critical piece to propagate forward to the linker; according to the documentation (https://docs.bazel.build/versions/master/skylark/lib/ObjcProvider.html#link_inputs): "Link time artifacts from dependencies that do not fall into any other category such as libraries or archives. This catch-all provides a way to add arbitrary data (e.g. Swift AST files) to the linker. The rule that adds these is also responsible to add the necessary linker flags to 'linkopt'."Note that when
cacheable_swiftmodules
is disabled, libraries are built with theserialize-debugging-options
flag, so debugging works just fine. Whencacheable_swiftmodules
is enabled however, we need to give LLDB some additional information and also make sure all the dependent ASTs are linked into the final app/test binary.The
dsymutil
command is being used in the tests to view the debugging sections of the generated app/test binary to ensure ALL necessary ASTs are linked to it.