Using a Juce-based static library in a non-Juce project

Hi, I've created a static library using Juce and I'd like to add this library to an existing application that isn't Juce-based. I've tested the library using a small Juce-based app and it worked fine, but when I try to compile the non-Juce application, I get plenty of unresolved externals at link time. I guess this means the library doesn't contain the Juce code that's used by my own code, and that it worked with the test app because it was also Juce-based and therefore also contained the Juce source code? If so, I'm surprised my lib file is so huge (the release version is >70MB -surprisingly the debug version is <50MB- , while it contains only a portion of the source code of an application whose executable file is <3MB)

=> When creating a static lib relying on Juce and using it in a non-Juce app, shall the application project include Juce code in addition to the library in order to compile? I did the same in the past using a DLL instead of a static lib, and I didn't need to do this...

Thanks

Note: the static library project was generated using the Introjucer

Same issue here. I built an audio effect toolbox as a static library and test it with another Juce-based application. The static library requires and includes juce_dsp module. The application doesn’t have the module included and is successfully built. From this point I could infer external dependency is not required.

However, when I test it with a non-Juce application, there are some link errors of undefined symbols shown below:

undef: OBJC_CLASS_NSProcessInfo undef: _OBJC_CLASS__NSAutoreleasePool
undef: _vDSP_vsmul
undef: OBJC_CLASS_NSFileManager undef: _OBJC_CLASS__NSDictionary
undef: OBJC_CLASS_NSOperationQueue undef: _OBJC_CLASS__NSMutableArray
undef: OBJC_CLASS_NSWorkspace undef: _OBJC_CLASS__NSHTTPURLResponse
undef: OBJC_CLASS_NSMutableData undef: _OBJC_CLASS__NSString
undef: OBJC_CLASS_NSURLSessionConfiguration undef: _OBJC_CLASS__NSMutableURLRequest
undef: _vDSP_create_fftsetup
undef: OBJC_CLASS_NSData undef: _OBJC_CLASS__NSAppleScript
undef: OBJC_CLASS_NSURLSession undef: _OBJC_CLASS__NSThread
undef: OBJC_CLASS_NSObject undef: _OBJC_CLASS__NSMutableDictionary
undef: OBJC_CLASS_NSURL undef: _vDSP_vclr undef: _OBJC_CLASS__NSBundle
undef: _vDSP_fft_zop
undef: _vDSP_fft_zrip
undef: _vDSP_destroy_fftsetup
Undefined symbols for architecture x86_64:
“OBJC_CLASS_NSProcessInfo", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSAutoreleasePool”, referenced from:
objc-class-ref in Temp_lto.o
“_vDSP_vsmul”, referenced from:
juce::dsp::AppleFFT::perform(std::__1::complex const*, std::__1::complex, bool) const in Temp_lto.o
juce::dsp::AppleFFT::performRealOnlyForwardTransform(float
, bool) const in Temp_lto.o
juce::dsp::AppleFFT::performRealOnlyInverseTransform(float*) const in Temp_lto.o
“OBJC_CLASS_NSFileManager", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSDictionary”, referenced from:
objc-class-ref in Temp_lto.o
“OBJC_CLASS_NSOperationQueue", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSMutableArray”, referenced from:
objc-class-ref in Temp_lto.o
“OBJC_CLASS_NSWorkspace", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSHTTPURLResponse”, referenced from:
objc-class-ref in Temp_lto.o
“OBJC_CLASS_NSMutableData", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSString”, referenced from:
objc-class-ref in Temp_lto.o
“OBJC_CLASS_NSURLSessionConfiguration", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSMutableURLRequest”, referenced from:
objc-class-ref in Temp_lto.o
“_vDSP_create_fftsetup”, referenced from:
juce::dsp::FFT::EngineImpljuce::dsp::AppleFFT::create(int) const in Temp_lto.o
“OBJC_CLASS_NSData", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSAppleScript”, referenced from:
objc-class-ref in Temp_lto.o
“OBJC_CLASS_NSURLSession", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSThread”, referenced from:
objc-class-ref in Temp_lto.o
“OBJC_CLASS_NSObject", referenced from: objc-class-ref in Temp_lto.o "_OBJC_CLASS__NSMutableDictionary”, referenced from:
objc-class-ref in Temp_lto.o
“OBJC_CLASS_NSURL", referenced from: objc-class-ref in Temp_lto.o "_vDSP_vclr", referenced from: juce::dsp::AppleFFT::performRealOnlyInverseTransform(float*) const in Temp_lto.o "_OBJC_CLASS__NSBundle”, referenced from:
objc-class-ref in Temp_lto.o
“_vDSP_fft_zop”, referenced from:
juce::dsp::AppleFFT::perform(std::__1::complex const*, std::__1::complex, bool) const in Temp_lto.o
“_vDSP_fft_zrip”, referenced from:
juce::dsp::AppleFFT::performRealOnlyForwardTransform(float
, bool) const in Temp_lto.o
juce::dsp::AppleFFT::performRealOnlyInverseTransform(float*) const in Temp_lto.o
“_vDSP_destroy_fftsetup”, referenced from:
juce::dsp::AppleFFT::~AppleFFT() in Temp_lto.o
juce::dsp::AppleFFT::~AppleFFT() in Temp_lto.o
ld: symbol(s) not found for architecture x86_64

Looks likely that you just need to include some macOS frameworks. If you have a look through the module header files of all the modules you included in your static library you should be able to see which ones, the easiest way to find them all is probably to search for “OSXFrameworks:” in the project of your static library.

1 Like

You can also avoid having to include the specific frameworks used by JUCE by creating a dynamic library instead. You would then need to specify a location where the dynamic library expects to be found, by adding “Custom Xcode flags” to the project, for example:

DYLIB_INSTALL_NAME_BASE = "@rpath",

LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)"

You would then need to embed/copy the dynamic library to the “Products Directory” in the parent project.

You mean using dynamic library instead of static library to get rid of dependency?

It turns out Projucer just doesn’t include any framework for static library project. It is understandable in case you use another Juce project which already includes these frameworks. But for a non-Juce project, I need to add them manually.

Is it even possible to include frameworks in a static library? the frameworks are resolved at link time right? which won’t of happened yet as a static library is compiled but not linked. The linking stage will happen when someone builds something other than a static library but references things in the static library. Even then, If the parts of the static library that are referenced don’t use the frameworks then I doubt the frameworks would be required at all. I might be mistaken but I was under the impression that’s how it worked.