Linking static juce into ObjC++ project

Hi everybody,

I created a juce music renderer, that I want to link into an Obj-C++ project (to use it inside Apple’s FxPlug SDK).
So I created a static library with juce and added an Obj-C++ file (.mm) exposing the interface and owning the instance of the renderer.
This static library I drag into XCode and link it to the FxPlug code.

The problem is, that the static library does not contain the STD, and when the FxPlug is linked it is missing it.
And because the FxPlug is Obj-C++, it won’t link the STD into the project by default.

I tried:

  1. adding linker flags: -std=c++11 -stdlib=libc++ -> leads to warning “linker input unused”
  2. adding a dummy cpp file to the main project -> no change at all
  3. EDIT: dragged all sources directly into the project -> now I have to deal with what to compile, and what to exclude because it is inlined from .mm wrappers… that becomes even more confusing, so I would want to continue a projucer-setup project and link it into the Obj-C++ xcode project

What did I do wrong?

Any hint is appreciated!
Cheers, Daniel

Here is the linker call and first few errors:

Ld /Users/daniel/Library/Developer/Xcode/DerivedData/Filmstro-FC-fdzfoettchncilftpgaqvhpqaagk/Build/Products/Debug/Filmstro-FC.fxplug/Contents/MacOS/Filmstro-FC normal x86_64
    cd /Volumes/data/Developer/Filmstro/FFC/repo/Filmstro-FxPlug
    export MACOSX_DEPLOYMENT_TARGET=10.8
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -bundle -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -L/Users/daniel/Library/Developer/Xcode/DerivedData/Filmstro-FC-fdzfoettchncilftpgaqvhpqaagk/Build/Products/Debug -F/Users/daniel/Library/Developer/Xcode/DerivedData/Filmstro-FC-fdzfoettchncilftpgaqvhpqaagk/Build/Products/Debug -F/Library/Developer/Frameworks -filelist /Users/daniel/Library/Developer/Xcode/DerivedData/Filmstro-FC-fdzfoettchncilftpgaqvhpqaagk/Build/Intermediates/Filmstro-FC.build/Debug/PlugIn.build/Objects-normal/x86_64/Filmstro-FC.LinkFileList -Xlinker -rpath -Xlinker @loader_path/../Frameworks -mmacosx-version-min=10.8 -Xlinker -object_path_lto -Xlinker /Users/daniel/Library/Developer/Xcode/DerivedData/Filmstro-FC-fdzfoettchncilftpgaqvhpqaagk/Build/Intermediates/Filmstro-FC.build/Debug/PlugIn.build/Objects-normal/x86_64/Filmstro-FC_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -fobjc-link-runtime -std=c++11 -stdlib=libc++ -framework Accelerate -framework AudioToolbox -framework AudioUnit -framework Carbon -framework Cocoa -framework CoreAudio -framework CoreAudioKit -framework IOKit -framework Foundation /Volumes/data/Developer/Filmstro/FFC/repo/ThemeLibrary/Builds/MacOSX/build/Debug/libThemeLibrary.a -framework FxPlug -Xlinker -dependency_info -Xlinker /Users/daniel/Library/Developer/Xcode/DerivedData/Filmstro-FC-fdzfoettchncilftpgaqvhpqaagk/Build/Intermediates/Filmstro-FC.build/Debug/PlugIn.build/Objects-normal/x86_64/Filmstro-FC_dependency_info.dat -o /Users/daniel/Library/Developer/Xcode/DerivedData/Filmstro-FC-fdzfoettchncilftpgaqvhpqaagk/Build/Products/Debug/Filmstro-FC.fxplug/Contents/MacOS/Filmstro-FC

Undefined symbols for architecture x86_64:
  "std::__1::__vector_base_common<true>::__throw_length_error() const", referenced from:
      std::__1::vector<float, std::__1::allocator<float> >::__append(unsigned long, float const&) in libThemeLibrary.a(filmstro_audioeffects_FSCompressor.o)
  "std::__1::locale::use_facet(std::__1::locale::id&) const", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(double) in libThemeLibrary.a(juce_core.o)
  "std::__1::ios_base::getloc() const", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(double) in libThemeLibrary.a(juce_core.o)
  "std::exception::what() const", referenced from:
      vtable for juce::Expression::Helpers::EvaluationError in libThemeLibrary.a(juce_core.o)
      vtable for std::__1::bad_function_call in libThemeLibrary.a(juce_core.o)
      vtable for std::__1::bad_function_call in libThemeLibrary.a(juce_audio_processors.o)
      vtable for std::__1::bad_function_call in libThemeLibrary.a(juce_gui_basics.o)
      vtable for std::__1::bad_function_call in libThemeLibrary.a(juce_events.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(char const*, unsigned long)", referenced from:
      juce::String::toStdString() const in libThemeLibrary.a(juce_core.o)
  "std::__1::ctype<char>::id", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(double) in libThemeLibrary.a(juce_core.o)
  "std::__1::locale::classic()", referenced from:
      juce::NumberToStringConverters::StackArrayStream::StackArrayStream(char*) in libThemeLibrary.a(juce_core.o)
  "std::__1::locale::locale(std::__1::locale const&)", referenced from:
      juce::NumberToStringConverters::StackArrayStream::StackArrayStream(char*) in libThemeLibrary.a(juce_core.o)
  "std::__1::locale::locale()", referenced from:
      std::__1::basic_streambuf<char, std::__1::char_traits<char> >::basic_streambuf() in libThemeLibrary.a(juce_core.o)
  "std::__1::locale::~locale()", referenced from:
      juce::NumberToStringConverters::StackArrayStream::StackArrayStream(char*) in libThemeLibrary.a(juce_core.o)
      std::__1::basic_streambuf<char, std::__1::char_traits<char> >::~basic_streambuf() in libThemeLibrary.a(juce_core.o)
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(double) in libThemeLibrary.a(juce_core.o)
  "std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::id", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(double) in libThemeLibrary.a(juce_core.o)
  "std::__1::ios_base::__set_badbit_and_consider_rethrow()", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(double) in libThemeLibrary.a(juce_core.o)
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::flush() in libThemeLibrary.a(juce_core.o)
  "std::__1::ios_base::init(void*)", referenced from:
      juce::NumberToStringConverters::StackArrayStream::writeDouble(double, int) in libThemeLibrary.a(juce_core.o)
  "std::__1::ios_base::clear(unsigned int)", referenced from:
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(double) in libThemeLibrary.a(juce_core.o)
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::flush() in libThemeLibrary.a(juce_core.o)
      std::__1::basic_ostream<char, std::__1::char_traits<char> >::sentry::~sentry() in libThemeLibrary.a(juce_core.o)
  "std::__1::ios_base::~ios_base()", referenced from:
      std::__1::basic_ios<char, std::__1::char_traits<char> >::~basic_ios() in libThemeLibrary.a(juce_core.o)
  "std::bad_alloc::bad_alloc()", referenced from:
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(filmstro_themes_ThemeRenderer.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(filmstro_themes_ThemeProcessor.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(juce_audio_basics.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(juce_audio_formats.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(filmstro_themes_XLoopSource.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(filmstro_audioeffects_FSCompressor.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(juce_audio_processors.o)
      ...
  "std::bad_alloc::~bad_alloc()", referenced from:
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(filmstro_themes_ThemeRenderer.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(filmstro_themes_ThemeProcessor.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(juce_audio_basics.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(juce_audio_formats.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(filmstro_themes_XLoopSource.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(filmstro_audioeffects_FSCompressor.o)
      juce::HeapBlockHelper::ThrowOnFail<true>::checkPointer(void*) in libThemeLibrary.a(juce_audio_processors.o)
      ...

If you were compiling with gcc then you could use the linker flags -static-libgcc -static-libstdc++, which statically links the c++ library (and the c library). I assume there are equivalent options for clang.

Thanks @t0m, that was a good hint.
But unfortunately with a google research I found out, that Apple doesn’t support static linking of system libraries: StackOverflow

But looking from different angles, I think, I missed the point:
My problems come up at build time, not at runtime. But on the other hand, I specified -stdlib=libc++ on both projects, but the FxPlug build ignores them.

I will try to build the library as dynamic library and load it into the FxPlug project. Let’s see where that approach takes me.

Meanwhile I am open for any suggestions or hints on that topic :slight_smile:
Cheers

So that was a real PEBCAK. I can simply add the juce static library to the XCode project like I tried before. The only thing that was missing was in frameworks to select libc++.tbd and it builds successfully. No need for compiler flags.

I hope that it will also work that easily when I try to deploy that.

The FxPlug project I will have to maintain in XCode anyway, and I can maintain the JUCE part still with the projucer’s static library template.

So case closed (hopefully, famous last words…)