CMake + Catch2 on iOS

Hi. I’m working on a cross-platform project that uses CMake to build and Catch2 (and its CMake integration) for tests.

I have it almost working but there’s a Postbuild Script that is generated in Xcode that fails.
The postbuild script looks something like

if test "$CONFIGURATION" = "Debug"; then :
    cd /Users/jason/dev/project/build/iOS/tests
    /opt/homebrew/Cellar/cmake/3.29.2/bin/cmake -D TEST_TARGET=PROJECTTests -D TEST_EXECUTABLE=/Users/jason/dev/project/build/iOS/tests/Debug/ -D TEST_EXECUTOR= -D TEST_WORKING_DIR=/Users/jason/dev/project/build/iOS/tests -D TEST_SPEC= -D TEST_EXTRA_ARGS= -D TEST_PROPERTIES= -D TEST_PREFIX= -D TEST_SUFFIX= -D TEST_LIST=PROJECTTests_TESTS -D TEST_REPORTER= -D TEST_OUTPUT_DIR= -D TEST_OUTPUT_PREFIX= -D TEST_OUTPUT_SUFFIX= -D TEST_DL_PATHS= -D CTEST_FILE=/Users/jason/dev/project/build/iOS/tests/PROJECTTests_tests-b12d07c.cmake -P /Users/jason/dev/project/build/iOS/_deps/catch2-src/extras/CatchAddTests.cmake

That last cmake command in the generated script will just lock and if I escape out, it logs DYLD_ROOT_PATH not set for simulator program

Is anyone familiar with how to fix this issue? And if not, is there any way I can short circuit building that postbuild script? The built binary is valid so I can manually load it into a simulator and run the tests.


Got halfway there but any advise is still welcome if anyone’s cleanly dealt with this before.

You can remove the Postbuild script mentioned by removing catch_discover_tests() from the CMake configuration. It will still build a binary with all the tests, it will just not say that no tests are found after the build.

1 Like

It sounds like you have test discovery running as a post-build step instead of a pre-test step. Take a look at the CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE variable. Setting that to PRE_TEST in your project’s top level CMakeLists.txt before you make any calls to catch_discover_tests() will probably address your problem, although I don’t know how well running tests through ctest for iOS will work.

Thanks. Yeah, the set(CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE PRE_TEST) gets me past the PostBuild Script issue but then it ends up with the same hang because the DYLD_ROOT_PATH not set for simulator program.

Considering that the only way I can run these tests right now seems to be by creating, booting, installing and launching the generated test app on an iOS Simulator, I’m guessing that’s out of scope of what CMake/Catch2 handles right now? I haven’t run across any documentation about Simulator specification in CMake.

Take a look at the CROSSCOMPILING_EMULATOR and TEST_LAUNCHER target properties. One of those may help you implement the behavior you’re after.

1 Like

I’ve had some success with using a shell script as the CROSSCOMPILING_EMULATOR. This shell script will start the simulator, install the application, run it and report the results. Here’s an example of such a script. The gotchas are:

  • XCODE_EMIT_EFFECTIVE_PLATFORM_NAME must be set to off for this to work
  • Last I checked, Catch2 didn’t well support test case discovery through this mechanism. There was an issue open in their repo requesting support for integration with XCTest, but I’m not sure if that ever got fully implemented.
  • This only works with .app bundles. You may need to set some properties such as MACOSX_BUNDLE_GUI_IDENTIFIER, MACOSX_BUNDLE_BUNDLE_VERSION, etc.
1 Like

Nice! Thanks. I wasn’t sure exactly how that CROSSCOMPILING_EMULATOR was supposed to work so seeing an example is super helpful.
I was able to get something working with just add_custom_command(TARGET target POST_BUILD ... but those suggestions look a lot more explicit so I’ll give it a shot.
Off topic but I’ve also never messed with CMake presets but now that I’ve seen it, I just want to rewrite all of my cmake to use json. Very cool.

1 Like