Open kodokoto opened 2 years ago
Could be worth creating a second branch. One branch demonstrating a successful build w/o Julia and a second the demonstrates the build that crashes.
I am 75% sure this is down to how the libjulia.dylib
is being included and embedded.
The CMake file don't automatically add the library search path, link to the library or add the relevant compiler flags in OTHER_LDFLAGS
. Linking the library via Xcode and not flags and Max gives me an error along the lines of
Error loading ~/Documents/Max 8/externals/dspnode~.mxo/Contents/MacOS/dspnode~: dlopen(~/Documents/Max 8/externals/dspnode~.mxo/Contents/MacOS/dspnode~, 262): Library not loaded: @rpath/libjulia.dylib
Referenced from: ~/Documents/Max 8/externals/dspnode~.mxo/Contents/MacOS/dspnode~
Reason: image not found
in this instance I altered the build destination to ~/Documents/Max 8/externals
and added this to Max's search path.
Julia has it's own long list of instructions for embedding which may need to scrutinised more closely.
In Build Settings
> Other Linker Flags I've added
-I
/Applications/Julia-1.6.app/Contents/Resources/julia/include/julia
-L
/Applications/Julia-1.6.app/Contents/Resources/julia/lib
-Wl,-rpath,/Applications/Julia-1.6.app/Contents/Resources/julia/lib
-ljulia
Which of course isn't ideal as /Applications/Julia-1.6.app/Contents/Resources/julia
should be some kind of environment variable. For our purposes (using macOS and Julia-1.6) this should be fine for now. Ideally this would be added to a CMakeLists.txt
somewhere in the project.
After adding the above, now I'm getting a EXC_BAD_ACCESS
error on jl_init();
here
I think a good first step, if you haven't already done this, would be to configure a simple C cli project in Xcode that consists of:
#include <julia.h>
int main(int argc, char *argv[])
{
jl_init();
(void)jl_eval_string("println(sqrt(2.0))");
jl_atexit_hook(0);
return 0;
}
that way it should help to narrow down what is a Julia problem and what is a Julia + Max problem.
I think a good first step, if you haven't already done this, would be to configure a simple C cli project in Xcode that consists of:
#include <julia.h> int main(int argc, char *argv[]) { jl_init(); (void)jl_eval_string("println(sqrt(2.0))"); jl_atexit_hook(0); return 0; }
that way it should help to narrow down what is a Julia problem and what is a Julia + Max problem.
I've been able to build this just fine linking to libraries in an identical way to the dspnode~
project. I'm a little stumped. I've tried also including the julia library in an non-CMake based project and the same thing is happening, so I don't think this is a conflict with flags CMake is adding.
It does fundamentally seems to be down to a Mach-O bundle (the .mxo
) trying to dynamically load libjulia.dylib
. I'll keep scratching away at this, I'm interested to see what is going on.
I hate admitting defeat, so I snooped around the issues over at https://github.com/JuliaLang/julia and this one came across my eye: https://github.com/JuliaLang/julia/issues/40246
This got me thinking that perhaps you've been doing everything correctly, it's the Julia .dylib
that's the problem. I installed Julia version 1.5.4
low and behold everything works
I altered the simplemsp_dsp64
method in this case so that it looks like
// registers a function for the signal chain in Max
void simplemsp_dsp64(t_dspnode *x, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags)
{
post("my sample rate is: %f", samplerate);
jl_init(); // initialize julia, this in itself does not break anything
jl_value_t *ret = jl_eval_string("sqrt(2.0)");
if (jl_typeis(ret, jl_float64_type)) {
double ret_unboxed = jl_unbox_float64(ret);
post("sqrt(2.0) in C: %e \n", ret_unboxed);
}
else {
post("ERROR: unexpected return type from sqrt(::Float64)\n");
}
jl_atexit_hook(0);
object_method(dsp64, gensym("dsp_add64"), x, simplemsp_perform64, 0, NULL);
jl_atexit_hook(0);
}
which will execute when you start the DAC
.
I think your only option for now is to embed the libjulia.1.5.4.dylib
in your .mxo
and reference that, at least for macOS.
We are now in the same state:
It appears any calls to julia in the audio thread (simplemsp_perform64
) throw a EXC_BAD_ACCESS (code=1, address=0x118)
error for me.
Since the audio thread is time critical, if any calls to julia are happening on another thread it means you won't be able to use them directly. You may need to get a bit more clever about how you wish to interface with julia code via your external.
I ran into the same problem with Julia 1.6; turns out that forcibly changing the working directory before jl_init()
makes the dynamic linking work 😭 😬 Anyway, I'm now in the same state too.
So, yes: the audio thread is to be treated with due care. Strikes me that, in the end, you would probably want to have Julia compile expressions on a not-audio thread, and only do evaluation on the audio thread. That implies possibly using the Julia API at a lower level, in order to cache function pointers to compiled expressions.
There's what seems to be an equivalent project for Supercollider here: https://github.com/vitreo12/JuliaCollider/ which might give some pointers on how to get Julia to play nicely in an audio context, and how to separate compiling from evaluating.
Even a simple call such as evaluating print() causes Max to crash:
Something tells
console.app logs from the crash:
Full report
Click to expand
``` Process: Max [2299] Path: /Applications/Ableton Live 11 Suite.app/Contents/App-Resources/Max/Max.app/Contents/MacOS/Max Identifier: com.cycling74.Max Version: 8.1.9 [2bed8a1] (8.1.9) Code Type: X86-64 (Native) Parent Process: Live [1139] Responsible: Live [1139] User ID: 501 Date/Time: 2021-11-18 17:41:26.468 +0000 OS Version: macOS 11.3.1 (20E241) Report Version: 12 Anonymous UUID: 08F05759-F010-436B-A994-606E0E2EC641 Time Awake Since Boot: 1300 seconds System Integrity Protection: enabled Crashed Thread: 43 Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000040 Exception Note: EXC_CORPSE_NOTIFY Termination Signal: Segmentation fault: 11 Termination Reason: Namespace SIGNAL, Code 0xb Terminating Process: exc handler [2299] VM Regions Near 0x40: --> __TEXT 102ecb000-103b0d000 [ 12.3M] r-x/r-x SM=COW /Applications/Ableton Live 11 Suite.app/Contents/App-Resources/Max/Max.app/Contents/MacOS/Max Thread 0:: CrBrowserMain Dispatch queue: com.apple.main-thread 0 libsystem_platform.dylib 0x00007fff2059b064 memset_pattern16_sse_np + 68 1 com.apple.CoreGraphics 0x00007fff25164715 CGBlt_fillBytes + 277 2 com.apple.CoreGraphics 0x00007fff25172da9 argb32_mark + 18359 3 com.apple.CoreGraphics 0x00007fff2515f7a3 RIPLayerBltShape + 1476 4 com.apple.CoreGraphics 0x00007fff2515d80c ripc_Render + 328 5 com.apple.CoreGraphics 0x00007fff2515a824 ripc_DrawRects + 463 6 com.apple.CoreGraphics 0x00007fff2515a5c5 CGContextFillRects + 96 7 com.apple.CoreGraphics 0x00007fff2515a55a CGContextFillRect + 105 8 com.cycling74.Max 0x0000000103676898 juce::CoreGraphicsContext::fillCGRect(CGRect const&, bool) + 216 9 com.cycling74.Max 0x0000000103673f2a juce::CoreGraphicsContext::fillRect(juce::Rectangle