Link issues with CMake, CTest and Catch2

I’ve been helping a friend improve it’s SDR (Software Defined Radio) project by trying to improve the build system.

The project has gotten to a point where everything seems to be quite stable and functional so I wanted to start hacking on a unit testing infrastructure. My tech stack is CMake + CTest + Catch2.

The project structure is as follows:

  • src - source code of the sigutils library.
  • tests - source code that generates the test binaries.

The source code can be found at GitHub - antoniovazquezblanco/sigutils at dev/tests.

Currently, the base CMakeLists.txt adds the src dir. In the src/CMakeLists.txt the sigutils library target is defined and everything seems to be working as expected. In linux, this target generates an .so file, a .dll in windows and a .dylib in MacOS…

At the bottom, the base CMakeLists.txt adds the tests dir and attempts to generate an executable for CTest to execute later on…

I am having problems compiling and executing the tests:

  • On linux things seem to be working…
  • On MacOS things break during the compilation phase due to a dyld[6621]: Library not loaded: '@rpath/libsigutils.1.dylib' Referenced from: '/Users/runner/work/sigutils/sigutils/build/tests/sigutils_test' Reason: tried: '/usr/local/lib/libsigutils.1.dylib' (no such file), '/usr/lib/libsigutils.1.dylib' (no such file)
  • On Windows things break when calling CTest with an exception while executing the tests due to being unable to load our library when executing the test; 1/1 Test #1: Test normalized frecuency scale ...Exit code 0xc0000135

Build and test logs:

I am currently linking the library with the following command:

target_link_libraries(sigutils_test $<TARGET_LINKER_FILE:sigutils>)

I am also trying to execute the tests in the src working directory to be able to find the lib:

catch_discover_tests(sigutils_test WORKING_DIRECTORY "$<TARGET_FILE_DIR:sigutils>")

I don’t know if I am making things difficult for myself or if my approach is generally oriented with good CMake practices. Any orientation in this regard is appreciated… Some of the doubts I had during the process include:

  • Should I compile a static version of the lib and always statically link the tests? This may take longer but it ensures everything works…
  • I would rather not mix library code and test code but, is there any alternative?
  • Should the library be copied to the tests folder on library compilation? Seems a weird approach…

Thanks in advance!

1 Like

After some research I concluded that, in my case, one of the best options is to flatten the target destinations while keeping the source in different folders.

# Always use top level dir for generated targets to avoid linker problems
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

This causes generated targets to be placed in my build directory root.

I am still facing problems in Windows but they seem non-related to the original issue…

For those interested, the new logs are located at:

I’ve also been trying to tackle this problem recently I have tried your approach, but no luck yet

I have seen an alternative [1], but that one is also painful to implement here. I’ve tried setting up the PATH variable [2], and that didn’t do anything either.


  1. Using gtest_discover_tests from cmake.test() in conan2 · Issue #12782 · conan-io/conan · GitHub ↩︎

  2. Using gtest_discover_tests from cmake.test() in conan2 · Issue #12782 · conan-io/conan · GitHub ↩︎

Apparently the folder structure is important, the following worked:

	set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
	set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
	set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})