dSYM files for multiple plugin targets

To generate a dSYM I’ve set the ‘custom Xcode flags’ in the Projucer Xcode release exporter to

GCC_GENERATE_DEBUGGING_SYMBOLS = YES, 
GCC_DEBUGGING_SYMBOLS = full, 
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym,
COPY_PHASE_STRIP = YES,
DWARF_DSYM_FOLDER_PATH = "$(CONFIGURATION_BUILD_DIR)",
DWARF_DSYM_FILE_NAME = "$(PRODUCT_NAME).dSYM"

This works fine for a standalone application. But not when dealing with a JUCE
5 plugin project. Here, for each Xcode scheme a dSYM gets created. But sadly
with the exact same name. So first, the dSYM for the VST. Then,
the dSYM for the VST3, which overwrites the VST dSYM. Then, the AAX dSYM, which overwrites the VST3 dSYM. At the end, the dSYM for the AU
component is the only one left.

Is there a build variable that holds the scheme name, to replace the
PRODUCT_NAME above? I tried SCHEME_NAME, but it’s not a valid
option. TARGET_NAME doesn’t provide unique names either.

A list of build variables is available at
https://pewpewthespells.com/blog/buildsettings.html
but ‘scheme’ isn’t mentioned.

Any ideas?

1 Like

Have you tried setting DWARF_DSYM_FOLDER_PATH = "$(TARGET_BUILD_DIR)"? The dSYM files would still be named the same, but they would normally end-up in different folders.

Thank you for the suggestion! Doesn’t change anything though. The dSYM files are still written to Builds/MacOSX/build/Release/ and overwrite each other.

Do you have the same problem on Debug? If not, it would be interesting to see what the difference is between the 2 configurations.

It’s reproducible with the JUCE demo plugin, same behaviour in the Debug configuration as in the Release configuration. Just add the ‘custom Xcode flags’ from my first post to the otherwise untouched JUCE demo plugin Projucer project file. (Happens on the latest develop branch, compilation from the command line.)

A work-around would be to have a separate Projucer project for each plugin format. This way, a build script could access the different dSYM files after compilation. These Projucer projects could be temporarily generated by the build script from the main Projucer project. But compilation time would increase and it kinda defeats the purpose of the shared lib file…

I finally got my hands on a Mac to try this out. I opened JUCE/examples/audio plugin demo/Builds/MacOSX/JuceDemoPlugin.xcodeproj in Xcode 7.3.1 and I built it. Obviously no dSYM files were generated. Then I opened JuceDemoPlugin.jucer in Projucer, added DEBUG_INFORMATION_FORMAT = dwarf-with-dsym to the “Custom Xcode flags” of the Debug configuration, saved and built again in Xcode.

In JUCE/examples/audio demo plugin/Builds/MacOSX/Build/Debug, I get the following files:

  • JuceDemoPlugin.app
  • JuceDemoPlugin.app.dSYM
  • JuceDemoPlugin.appex
  • JuceDemoPlugin.appex.dSYM
  • JuceDemoPlugin.component
  • JuceDemoPlugin.component.dSYM
  • JuceDemoPlugin.vst
  • JuceDemoPlugin.vst.dSYM
  • libJuceDemoPlugin.a

So try removing DWARF_DSYM_FOLDER_PATH and DWARF_DSYM_FILE_NAME from the “Custom Xcode flags” in Projucer. The default values of Xcode seem to work already.

3 Likes

Awesome, thanks a lot for your help @McMartin!

If someone is curious about how to handle a crash report, this is what I do.

Example crash report with stripped symbols (where I forced a crash by dereferencing a nullptr):

...
Thread 0 Crashed:: JUCE Message Thread  Dispatch queue: com.apple.main-thread
0   com.klangfreund.multimeterstandalone	0x000000010003b853 0x100000000 + 243795
1   com.klangfreund.multimeterstandalone	0x000000010003b5f4 0x100000000 + 243188
2   com.klangfreund.multimeterstandalone	0x000000010003aee3 0x100000000 + 241379
3   com.klangfreund.multimeterstandalone	0x00000001000de9f9 0x100000000 + 911865
4   com.klangfreund.multimeterstandalone	0x00000001000de92e 0x100000000 + 911662
5   com.klangfreund.multimeterstandalone	0x00000001000e5d54 0x100000000 + 941396
6   com.apple.CoreFoundation      	0x00007fffa4055321 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
7   com.apple.CoreFoundation      	0x00007fffa403621d __CFRunLoopDoSources0 + 557
...
Binary Images:
       0x100000000 -        0x100245fff +com.klangfreund.multimeterstandalone (1.8.1 - 1.8.1) <C3755769-A3E6-3F92-A9B9-B776A4701773> /Users/USER/*/Multimeter.app/Contents/MacOS/Multimeter
...

The same example with symbols, just for reference:

...
Thread 0 Crashed:: JUCE Message Thread  Dispatch queue: com.apple.main-thread
0   com.klangfreund.multimeterstandalone	0x000000010003b853 FloatingToolWindow::FloatingToolWindow(juce::String const&, juce::String&, juce::Component*, juce::ScopedPointer<FloatingToolWindow>&, int, int, int, int, int, int) + 351 (FloatingToolWindow.h:65)
1   com.klangfreund.multimeterstandalone	0x000000010003b5f4 SettingsPanel::generateFloatingSettingsWindow() + 182 (SettingsPanel.cpp:330)
2   com.klangfreund.multimeterstandalone	0x000000010003aee3 SettingsPanel::valueChanged(juce::Value&) + 103 (SettingsPanel.cpp:313)
3   com.klangfreund.multimeterstandalone	0x00000001000de9f9 juce::Value::callListeners() + 109 (juce_Value.cpp:233)
4   com.klangfreund.multimeterstandalone	0x00000001000de92e juce::Value::ValueSource::sendChangeMessage(bool) + 102 (juce_Value.cpp:56)
5   com.klangfreund.multimeterstandalone	0x00000001000e5d54 juce::MessageQueue::runLoopSourceCallback(void*) + 244 (juce_osx_MessageQueue.h:85)
6   com.apple.CoreFoundation      	0x00007fffa4055321 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
7   com.apple.CoreFoundation      	0x00007fffa403621d __CFRunLoopDoSources0 + 557
...

In the ‘Binary Images’ section of the crash report, the UUID C3755769-A3E6-3F92-A9B9-B776A4701773 is provided. Make sure that you have the binary and the dSYM file at hand matching this UUID:

dwarfdump --uuid Multimeter.app/Contents/MacOS/Multimeter
dwarfdump --uuid Multimeter.dSYM

To symbolicate e.g. the address 0x000000010003b853 (first line of the crashed thread), place the dSYM next to the binary and use

lldb Multimeter.app
(lldb) image lookup -v --address 0x000000010003b853

Result:

Address: Multimeter[0x000000010003b853] (Multimeter.__TEXT.__text + 239203)
    Summary: Multimeter`FloatingToolWindow::FloatingToolWindow(juce::String const&, juce::String&, juce::Component*, juce::ScopedPointer<FloatingToolWindow>&, int, int, int, int, int, int) + 351 at FloatingToolWindow.h:65
     Module: file = "/Users/sam/data/docs/code/LUFSMeter/projects/MultimeterStandalone/Builds/MacOSX/temp/Multimeter.app/Contents/MacOS/Multimeter", arch = "x86_64"
CompileUnit: id = {0x002146fc}, file = "/Users/sam/data/docs/code/LUFSMeter/projects/LUFSMeter/Source/gui/SettingsPanel.cpp", language = "c++"
   Function: id = {0x0021f731}, name = "FloatingToolWindow", range = [0x000000010003b6f4-0x000000010003b8a7)
   FuncType: id = {0x0021f731}, decl = juce_Path.cpp:24, compiler_type = "void (const class juce::String &, class juce::String &, class juce::Component *, class juce::ScopedPointer<class FloatingToolWindow> &, int, int, int, int, int, int)"
     Blocks: id = {0x0021f731}, range = [0x10003b6f4-0x10003b8a7)
  LineEntry: [0x000000010003b853-0x000000010003b85c): /Users/sam/data/docs/code/LUFSMeter/projects/LUFSMeter/Source/gui/FloatingToolWindow.h:65:16
     Symbol: id = {0x000003ba}, range = [0x000000010003b6f4-0x000000010003b8a8), name="FloatingToolWindow::FloatingToolWindow(juce::String const&, juce::String&, juce::Component*, juce::ScopedPointer<FloatingToolWindow>&, int, int, int, int, int, int)", mangled="_ZN18FloatingToolWindowC2ERKN4juce6StringERS1_PNS0_9ComponentERNS0_13ScopedPointerIS_EEiiiiii"
   Variable: id = {0x0021f754}, name = "this", type = "FloatingToolWindow *", location =  rbx, decl =
   Variable: id = {0x0021f78c}, name = "content", type = "juce::Component *", location =  r13, decl = FloatingToolWindow.h:26
   Variable: id = {0x0021f79f}, name = "ownerPointer", type = "juce::ScopedPointer<FloatingToolWindow> &", location =  r14, decl = FloatingToolWindow.h:27
   Variable: id = {0x0021f7b2}, name = "defaultW", type = "int", location =  r12, decl = FloatingToolWindow.h:28
10 Likes

I did the same steps with the Juce Demo plugin as described above and I am getting the .dsym files for each target. I’m trying to get line-based profiler information in Instruments, but it just doesn’t work. Instruments claims to know the dsym location (green light in the Symbols…) dialog, but sources still won’t show up. This is using XCode 7.3.1 and the latest Juce. Has anyone managed to make this work.

ok. it does work, but only for some functions. And this is with a Debug build, so inlining shouldn’t be the issue. This is driving me mad! Sources seem to be located for just random functions and for others I get “Unavailable” although source would clearly be available for those. Well maybe time to give up with Instruments and use something else.

@pflugshaupt did you ever make progress on this? I’m able to generate dsym files for my plugin project, but Instruments says they don’t contain any symbols for the plugin that’s running. i’m using xcode 10.1 so maybe things changed a lot since xcode 7.3.1, which you were using.

No, I gave up on it and actually forgot I ever tried! Now I’m using XCode 9, but I’m not optimistic setting this up right got any easier.

did you try this btw ([GUIDE] Symbolicating Release Builds)?
it is still working fine here though it’s explicitly set using xcodebuild.
I’ll update it for newer JUCE but it the shell scripts should be pretty much the same.

2 Likes

i wanted to include the dsym files in the archive on macOS.
what worked for me was adding these Custom Xcode Flags in the Juce Project.

GCC_GENERATE_DEBUGGING_SYMBOLS=YES,
GCC_DEBUGGING_SYMBOLS=full,
DEBUG_INFORMATION_FORMAT=dwarf-with-dsym,
COPY_PHASE_STRIP = YES,
DWARF_DSYM_FILE_SHOULD_ACCOMPANY_PRODUCT=YES

only when i added DWARF_DSYM_FILE_SHOULD_ACCOMPANY_PRODUCT the dsym files were finally added to the archive.

6 Likes