[Bug]: Unable to load nwb extensions in compiled MATLAB app.
What happened?
I've implemented support for NWB files to a MATLAB application I'm developing. My code works fine, but when I try to load any NWB file after compiling the application, I get an error stating that the extension the NWB file in question relies upon (in this case ndx_multichannel_volume, which adds support for C. Elegans microscopy data) is inaccessible:
These are my compilation settings:
This seems to happen the moment any nwbRead() call that relies on an extension occurs, regardless of whether I include matnwb by passing it as a support package to mcc or by including it in the application path from the get-go.
It may also be worth noting that compilation also triggers two errors when this is first attempted:
- That lines 30 and 32 of +util/loadTimeSeriesData.m are invalid Matlab syntax. Checking the file shows that there are two colons used in IF statements on those lines, and removing those resolves this error.
- That the tutorial folder contains empty files that would cause errors. Deleting the tutorial folder resolves this error.
I couldn't find any recommended notes on how to include matnwb as a support package in a compiled Matlab app in the documentation, so if there's something I'm missing, please let me know.
Steps to Reproduce
1. Create Matlab application that utilizes nwbRead().
2. Create .prj file and compile said application with matnwb packaged.
3. Try to open NWB file that relies on extensions with compiled app.
Error Message
No response
Operating System
Windows
Matlab Version
-----------------------------------------------------------------------------------------------------
MATLAB Version: 23.2.0.2515942 (R2023b) Update 7
MATLAB License Number: 40702059
Operating System: Microsoft Windows 11 Home Version 10.0 (Build 22621)
Java Version: Java 1.8.0_202-b08 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
-----------------------------------------------------------------------------------------------------
MATLAB Version 23.2 (R2023b) License 40702059
Simulink Version 23.2 (R2023b) License 40702059
Bioinformatics Toolbox Version 23.2 (R2023b) License 40702059
Computer Vision Toolbox Version 23.2 (R2023b) License 40702059
Curve Fitting Toolbox Version 23.2 (R2023b) License 40702059
Deep Learning HDL Toolbox Version 23.2 (R2023b) License 40702059
Deep Learning Toolbox Version 23.2 (R2023b) License 40702059
Global Optimization Toolbox Version 23.2 (R2023b) License 40702059
Image Processing Toolbox Version 23.2 (R2023b) License 40702059
MATLAB Coder Version 23.2 (R2023b) License 40702059
MATLAB Compiler Version 23.2 (R2023b) License 40702059
MATLAB Compiler SDK Version 23.2 (R2023b) License 40702059
Optimization Toolbox Version 23.2 (R2023b) License 40702059
Parallel Computing Toolbox Version 23.2 (R2023b) License 40702059
Partial Differential Equation Toolbox Version 23.2 (R2023b) License 40702059
Signal Processing Toolbox Version 23.2 (R2023b) License 40702059
Statistics and Machine Learning Toolbox Version 23.2 (R2023b) License 40702059
System Identification Toolbox Version 23.2
Code of Conduct
- [X] I agree to follow this project's Code of Conduct
- [X] Have you ensured this bug was not already reported?
May be worth noting that I've replicated the issue on MacOS as well. All three errors mentioned pop on both systems.
Pinging @lawrence-mbf
@RR-N It looks like when running the compiled app, the path to the extension might get messed up. What is the directory that you are running the compiled app from? Is it C:\Users\sep27\Documents\GitHub\NeuroPAL_ID\win_visualize\for_redistribution_files_only\NeuroPAL_ID_mcr?
Pinging @lawrence-mbf
@RR-N It looks like when running the compiled app, the path to the extension might get messed up. What is the directory that you are running the compiled app from? Is it
C:\Users\sep27\Documents\GitHub\NeuroPAL_ID\win_visualize\for_redistribution_files_only\NeuroPAL_ID_mcr?
The compiled app is run from C:\Users\sep27\Documents\GitHub\NeuroPAL_ID\win_visualize\for_redistribution_files_only\. And yeah, that's exactly what it looks like -- once compiled the extension seems to be searched for in ctfroot + the path to matnwb that was passed to the compiler.
This probably has to do with the misc.getMatnwbDir() directory which may be baked into the compiler. If you call generateCore() from your compiled application, where are the files generated?
This probably has to do with the
misc.getMatnwbDir()directory which may be baked into the compiler. If you callgenerateCore()from your compiled application, where are the files generated?
Within the mcr folder in for_redistribution_files_only, so C:\Users\sep27\Documents\GitHub\NeuroPAL_ID\win_visualize\for_redistribution_files_only\NeuroPAL_ID_mcr\Users\sep27\AppData\Roaming\MathWorks\MATLAB Add-Ons\Collections\NeurodataWithoutBorders_matnwb(2):
@RR-N It looks like by default (if you add the directory to "Files required for your application to run"), the working directory from misc.getMatnwbDir() should end up in %LOCALAPPDATA%\temp\<user>\mcrCachexx.x\<project name>\<matnwb dir>\
I wonder if you should use that instead of the -a option?
@RR-N Ah, I think I know the issue actually. I do not believe the compiled mcr can actually fread externally generated matlab files. This is probably a security thing to prevent arbitrary execution (we do use eval for the purpose of accessing these generated class constructors).
Also, the ".m" files are in fact p-coded so the mcr simply does not run ".m" source code and complains that it is "inaccessible".
I was also wrong on the fread part, it is just the mcr not being able to read MATLAB source code at all. You would need to pre-generate all the class files/extensions necessary before packaging the matnwb package.
MatNWB is heavily reliant on generated static MATLAB source files. Modifying the code to support this would be essentially rewriting the entire project.
Pre-generating and adding an external reference to the extension within an isdeployed check worked for now -- I'll try a packaged solution next. I do still need to explicitly delete the colons in +util/loadTimeSeriesData.m and delete the tutorial folder to avoid errors during compilation though.
If that is causing problems, you can just remove +util/loadTimeSeriesData.m afaik it is only used in tutorials which you have already deleted. None of which are required for nwbRead()
That the tutorial folder contains empty files that would cause errors. Deleting the tutorial folder resolves this error.
Just curious since this seems strange. The repo does not have empty files in the root tutorials folder... Were the tutorial files modified or run and then generated empty files?
That the tutorial folder contains empty files that would cause errors. Deleting the tutorial folder resolves this error.
Just curious since this seems strange. The repo does not have empty files in the root tutorials folder... Were the tutorial files modified or run and then generated empty files?
No, I didn't touch any of them prior to compilation.