dSYM files for multiple plugin targets


#1

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?


How to set up a profiler config for XCode
#2

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.


#3

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.


#4

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


#5

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…


#6

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.


#7

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

Decoding OSX crash
#8

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.


#9

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.