What's the solution for "error: Couldn't IRGen expression, no additional error" on Xcode 10.1?
Asked Answered
M

3

17

We have a large project with a lot of dependencies brought in through Carthage. Whenever we try to look at a variable in the lldb debugger (p variablename), it gives us an error: error: Couldn't IRGen expression, no additional error

None of the workarounds are very good. We can run carthage with --no-use-binaries to get around it, but it makes builds take a prohibitively long time. We can use fr v on some variables, but not all. People have fixed this in previous versions of Xcode by changing permissions on some Swift directories, but I can't find the corresponding directories in Xcode 10.1. And I saw someone say that changing the build system back and forth helped him, but that hasn't worked for us.

So I'm starting this search for a solution on Xcode 10.1 specifically. Has anyone else found out what's causing this error, and/or a good solution to it?

Maser answered 19/2, 2019 at 23:24 Comment(1)
We appear to have eventually found the root cause of the problem: one of our dependencies was missing a header file. When we included the header file in the dependency, the main project was then able to display variable information in lldb without any further trouble. We don't understand why this simple fix solved the cryptic error, but we're okay with that. – Maser
M
29

Someone on my team shared a solution to this that actually works (I don't know if he discovered it or found it elsewhere):

Set a breakpoint on the first line of the AppDelegate didFinishLaunchingWithOptions method. Set the action for this breakpoint to: po application

Now, when your run your application, the debugger will pause at that breakpoint and will display this text in the lldb debugger pane (with your app name instead of Foo):

note: Swift compiler options for Foo conflict with options found in other modules; Switching to a new expression evaluator for Foo, old $R variables are lost.

And then the lldb debugger will work properly, able to p and po variables and expr expressions.

I don't know why it works, but it works, and reliably too!

Maser answered 5/3, 2019 at 20:14 Comment(2)
Thanks, I worked. Before I tried to delete carthage cache and derived data, delete carthage folder, kill Xcode and rebuild everything but It did not work. I have installed locally two Xcode versions, but I built the carthage dependencies with the same one I was running the app, so Thanks again, it was driving me nuts. – Lover
unfortunately not working for me. Have some binaries from firebase and elsewhere. Wish I knew WHICH module was causing the issue. – Choline
T
19

A colleague and me found a solution:

Create an Objective-C file in your Swift project. Hit yes when it asks for the Bridging Header.

Test.h

#import <Foundation/Foundation.h>

@interface Test : NSObject

- (id)init;

@end

Test.m

#include "Test.h"

@implementation Test

- (id)init
{
    return self;
}

@end

MyProject-Bridging-Header.h

#include "Test.h"

And now: πŸŽ‰ no more error: Couldn't IRGen expression, no additional error and you can debug again.

So I think just adding a bridging header works as a workaround...

But If that doesn't work:

Add a breakpoint in AppDelegate.swift in application: UIApplication, didFinishLaunching like so and hope that this helps:

Breakpoint in Xcode

Trooper answered 15/5, 2020 at 16:33 Comment(5)
Great it worked for me with same problem with Amazon Amplify framework – Mobster
I have the same exact issue with the same framework I'll look at this an leave a comment – Inflect
and it solved my issues – Inflect
and changed the swift package to use local and gone now is not working again no matter this solution. amplify sucks – Inflect
Wow creating an empty bridging header without Obj-C file worked fine. – Pyroxylin
C
13

There is currently a hard requirement that the version of the swift compiler you use to build your source and the version of lldb you use to debug it must come from the same toolchain. Currently the swift debug information for types is just a serialization of internal swift compiler data structures. It also depends on local path information, which makes it hard to move around.

There is a longer term effort to change that design, but for now you have to rebuild all your binaries every time you update your tools, and you can't use pre-built binaries.

I'm a little surprised this causes a day-to-day problem, however. This full rebuild only needs to happen when you pull new sources from Carthage or update your tools, which shouldn't be that often. If you are triggering rebuilds more frequently than that, maybe dependencies aren't getting tracked properly, so that more files are getting rebuilt than need to be?

Canonist answered 20/2, 2019 at 18:53 Comment(5)
What do you mean by "same toolchain", exactly? All of our dependencies are built with Xcode 10.1, except for a few third-party dependencies we have, but we're generally not debugging those. If I'm building with a version of some dependency that was built with an older Xcode, why would that prevent me from being able to see local variables in a method in one of my classes that's not using that dependency? – Maser
lldb can't build a swift context for expression evaluation (or variable inspection) without successfully importing the full tree of module dependencies. lldb tries to make a general context that includes all the modules that get loaded into your running app, so you can play around with anything. That's going to fail in your case. – Canonist
Starting in Xcode 10, if that fails, we build a new context that only sees the modules imported by the module containing the code you are currently stopped in in the debugger. If that module doesn't include third party modules in the closure of its imports, you should be fine. Except, of course, you won't be able to access types/variables/etc that aren't visible to this module. But if the current module does import your third party dependencies, we're back at the same problem. – Canonist
And for "same toolchain": lldb includes a copy of the swift compiler sources as part of its build. That copy of the swift compiler sources, and the one used to build the swiftc you built your code with, have to be the same sources. – Canonist
We are hitting this issue, but we are using Rome (github.com/blender/Rome) to cache our frameworks as building them every time wastes a lot of developer hours. Is there a workaround we are able to use to allow for debugging? – Corm

© 2022 - 2025 β€” McMap. All rights reserved.