external code test with Catch2

BenCello's icon

Hi there,

For obscure reasons I am trying to test part of my external's code with Catch2 framework (https://github.com/catchorg/Catch2). I am using cmake toolchain (on macOS) and following the documentation of Catch2 made me build/link/call Catch2 rather easily.

However, I am trying to build an "autonomous" test binary (not a bundled external object) which is not executed by Max but directly in command line. And thus I have lots of troubles linking/finding/using all Cycling's frameworks.

Because my binary is not placed at the exact same spot as Max binary, the @executable_path is not the same and the frameworks are not found. I tried using install_name_tool to change both MaxAudioAPI.framework and JitterAPI.frameworkand it worked for those two, but they are themselves calling the other frameworks (MaxLua.frameworketc.) which are, in turn, not found.

I also tried to brutally copy all theFrameworksfolder of Max.app in the right place (relatively to my test binary) but that did not work either, MaxAudioAPIImpl and JitterAPIImpl are still not found. Maybe because they use the @rpath and not the@executable_path?

Of course, I do not want to change the paths in the frameworks themselves, just for the test binary. And actually, I do not intend the use Catch2 to test the parts of the code which has something to do with Max/MSP/Jitter APIs, only the "pure" C/C++ methods.

But I am stuck now at this point...

Has anyone already tried this? Has somebody (from Cycling?) any idea on how to get around this?

Thank you very much!

Benjamin

JBG's icon

Hi Benjamin,

I don't really have an answer to your question on how to link this, but I could share some insights that might be helpful. 

The ideal approach for these types of scenarios is probably to separate your code into a core library (what you describe as "pure" C/C++) and an IO wrapper layer, where only the latter includes the Max SDK. With such an approach, you could easily just link your core library to the Catch2 framework for your tests (as well as create other wrappers if you want, for example if you want a CLI wrapper or a JUCE wrapper for your library). It seems from your description that your code more or less already is structured like this so perhaps it wouldn't be that much work to do this?

If this isn't a feasible approach, you could have a look at the min-api, which already comes with its own distribution of Catch2. While you probably won't be able to use this directly (I assume that you're using the max-sdk), you could have a look at how they handle the linking there. Most min packages have a similar structure to max-sdk packages (you basically include min-pretarget.cmake and min-posttarget.cmake, which are light wrappers around max-pretarget.cmake and max-posttarget.cmake), plus the additional min-object-unittest.cmake which handles all the linking to their own catch distribution and mock kernel

I believe that it shouldn't be too difficult to adapt the relevant includes/definitions/properties/options from this script (plus the test/CMakeLists.txt) to your own code base

BenCello's icon

Hi JBG,
Thank's for your long reply!

Indeed, I ended up doing a bit of both options you mentioned:

I split the code into two parts, the part "agnostic" from Max and MaxAPI that I could test with Catch2 easily in a command line executable and the part wrapping this core-code into Max objects.

And I indeed had a dive into Min API CMakeLists to see how they're doing it.

And it does work in two sides this way!

The code base I wanted to test is actually mainly written in C. So it's another (time consuming) project to convert everything to modern C++ using Min API. Nevertheless, I may do it at some point.

Best,
Benjamin