MobileNativeFoundation / MobileNativeFoundation/rules_xcodeproj

Bug: Xcode beachballs when opening a generated file in certain situations

Open
#2,480 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Swift
Stars
626
Forks
124
PR merge metrics
No merged PRs in 30d

Description

Description

Context

When trying to cmd+click on a symbol that lives in a Swift generated file (such as SwiftProtobuf, or any other genrule or custom rule a project might have), Xcode can end up beach-balling before opening the file for various seconds. A sample of Xcode shows the following:

 2175 Thread_810300   DispatchQueue_1: com.apple.main-thread  (serial)
    + 2175 start  (in dyld) + 2236  [0x1a313ff28]
    +   2175 NSApplicationMain  (in AppKit) + 880  [0x1a6760794]
    +     2175 -[DVTApplication run]  (in DVTKit) + 60  [0x10299cabc]
    +       2175 -[NSApplication run]  (in AppKit) + 464  [0x1a6789344]
    +         2175 -[DVTApplication nextEventMatchingMask:untilDate:inMode:dequeue:]  (in DVTKit) + 300  [0x10299d8b4]
    +           2175 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]  (in AppKit) + 716  [0x1a6794ee0]
    +             2175 _DPSNextEvent  (in AppKit) + 636  [0x1a6795d44]
    +               2175 _BlockUntilNextEventMatchingListInModeWithFilter  (in HIToolbox) + 76  [0x1acdbe7d4]
    +                 2175 ReceiveNextEventCommon  (in HIToolbox) + 648  [0x1acdbea7c]
    +                   2175 RunCurrentEventLoopInMode  (in HIToolbox) + 292  [0x1acdbec40]
    +                     2175 CFRunLoopRunSpecific  (in CoreFoundation) + 612  [0x1a35744b8]
    +                       2175 __CFRunLoopRun  (in CoreFoundation) + 1852  [0x1a3575348]
    +                         2175 __CFRunLoopDoTimers  (in CoreFoundation) + 356  [0x1a358fbc8]
    +                           2175 __CFRunLoopDoTimer  (in CoreFoundation) + 940  [0x1a3590070]
    +                             2175 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__  (in CoreFoundation) + 32  [0x1a35903c8]
    +                               2175 __NSFireDelayedPerform  (in Foundation) + 372  [0x1a450b1c4]
    +                                 2175 -[IDEEditorGeniusResults _doFindGeniusResults]  (in IDEKit) + 1676  [0x10702b750]
    +                                   2175 -[IDEGeniusResultsFinder findGeniusResultsForEditorDocument:selectedDocumentLocations:]  (in IDEKit) + 224  [0x10702c7c0]
    +                                     2175 -[IDESwiftGeneratedInterfaceGeniusResultsFinder _updateGeniusResults]  (in IDEKit) + 260  [0x10730ce48]
    +                                       2175 -[IDEGeneratedInterfaceBasedGeniusResultsFinder locateSwiftObjcGeneratedHeaderFileURLs]  (in IDEKit) + 304  [0x106f36f50]
    +                                         2175 -[NSSet(DVTNSSetAdditions) dvt_objectsPassingTest:]  (in DVTFoundation) + 228  [0x1037f2454]
    +                                           2175 __87-[IDEGeneratedInterfaceBasedGeniusResultsFinder locateSwiftObjcGeneratedHeaderFileURLs]_block_invoke  (in IDEKit) + 20  [0x106f3705c]
    +                                             2173 -[Xcode3Target containsFilePath:]  (in DevToolsCore) + 92  [0x1145f6518]
    +                                             ! 2173 -[PBXTarget containsFileReferenceForAbsolutePath:]  (in DevToolsCore) + 16  [0x114445b10]
    +                                             !   2145 -[PBXTarget buildFilesForAbsolutePath:]  (in DevToolsCore) + 48  [0x114445294]
    +                                             !   : 2145 -[PBXTarget buildFilesForResolvedAbsolutePath:]  (in DevToolsCore) + 68  [0x114445044]
    +                                             !   :   2145 -[PBXContainer fileReferenceForPath:]  (in DevToolsCore) + 64  [0x11449170c]
    +                                             !   :     747 -[PBXContainer referenceForPath:class:]  (in DevToolsCore) + 280  [0x11449184c]

It seems like DevToolsCore is wasting a lot of time in computing various file references and/or resolving files with their absolute paths. I have filed a feedback (FB12819854) to Apple about this, but we should try to find a workaround.

Findings

Example Project

What I noticed is that if I alt+click on a type, I can copy the link to which file Xcode will bring me to.
Screenshot 2023-08-17 at 3 21 04 PM
In a simple example in our integration project, the link points to something like:

//file:///Users/me/path/to/rules_xcodeproj/examples/integration/bazel-output-base/rules_xcodeproj.noindex/indexbuild_output_base/execroot/_main/bazel-out/ios-sim_arm64-min15.0-applebin_ios-ios_sim_arm64-dbg-ST-f0ca9b8bc01a/bin/UI/generated/generated.swift

Opening this file in Xcode doesn't show the beach-balling behavior (it could be because the example project is rather small too).

If we cmd+click the generatedInt type in the example, we end up in a file that isn't part of the xcodeproj.
Screenshot 2023-08-17 at 3 31 06 PM

Other files which are present in the project with a similar name can be found via cmd+o (quick open).
Screenshot 2023-08-17 at 3 34 36 PM

Opening any of these files (which aren't grayed out because they haven't been generated yet due to building for a different config), reveals them correctly without any beach-balling. On top of that, Xcode reveals the full path, meaning that the file actually lives in the project.

Screenshot 2023-08-17 at 3 35 25 PM

So in short, I wasn't able to reproduce the beach-balling behavior outside our project. This is likely because the issue is only reproducible in very big projects with lots of files and targets.

Our Project

In our project, alt+clicking the type which demonstrates the beach-balling behavior shows the file living at path:

file:///private/var/tmp/_bazel_me/9c146a5e97098b318f66f519df2b642d/rules_xcodeproj.noindex/indexbuild_output_base/execroot/project_name/bazel-out/ios-sim_arm64-min14.0-applebin_ios-ios_sim_arm64-dbg-ST-efefcef94047/bin/path/to/generated.swift

This is a bit surprising but could explain the issue. Only files living at certain paths cause Xcode to reveal the beach-balling behavior. Even in our project, opening the file via cmd+clicking shows a version of the file which isn't part of the project. When using cmd+o the file, the beach-balling behavior doesn't happen. The version of the file being opened in this case is at:

/var/tmp/_bazel_me/9c146a5e97098b318f66f519df2b642d/rules_xcodeproj.noindex/build_output_base/execroot/project_name/bazel-out/ios-sim_arm64-min14.0-applebin_ios-ios_sim_arm64-dbg-ST-efefcef94047/bin/path/to/generated.swift

One really bad workaround that I've noticed is that disabling indexing (defaults write com.apple.dt.XCode IDEIndexDisable 1) fixes the issue. This basically causes Xcode not to do live indexing, and so only the correct indexstore imported by Bazel and rules_xcodeproj is found.

Conclusion

My theory is that live indexing makes Xcode populates the index store with new paths for certain files. When cmd+clicking on types living in these files, it causes Xcode to perform certain operations with files which aren't living directly in the project, so they're somehow unknown. This can cause performance slowdowns in the experience. Ideally Xcode would solve the performance issue, but it's possible we could find ways for Xcode to index the correct files without disabling indexing completely.

Reproduction steps

https://github.com/MobileNativeFoundation/rules_xcodeproj/tree/pb/generated-source-demo

Expected behavior

Xcode shouldn't beach-ball when opening certain generated files.

rules_xcodeproj version

1.9.1

Xcode version

Xcode 14.2

Bazel version

6.3.2

rules_apple version

No response

rules_swift version

No response

Additional information

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the generated-source-demo reproduction project linked in the issue and compare cmd-clicking a generated symbol with opening the same file through cmd+o. Profile the beach-balling path described in the Xcode sample, then verify that generated files open without the reported delay while indexing remains enabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
build-system, developer-experience
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.