Ctest does not find catch2 tests with subdirectory - c++

I don't seem to get my CTest project to recognize my Catch2 tests. The test project itself builds fine and I manage to run the tests using the executable created by it. However when running
ctest -V
The output I keep getting is:
UpdateCTestConfiguration from :/home/user/code/project/libs/DartConfiguration.tcl
UpdateCTestConfiguration from :/home/user/code/project/libs/DartConfiguration.tcl
Test project /home/user/code/project/libs/
Constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
No tests were found!!!
My set-up is as follows:
The folder structure:
libs
├── maths
│   ├── matrix.cpp / hpp
│   ├── function.cpp / hpp
│   └── CMakeLists.txt
├── ctest
│   ├── matrix_test.cpp
│   ├── function_test.cpp
│   └── CMakeLists.txt
├── build
   └── CMakeLists.txt
I build from the build folder
cmake ..
cmake --build .
ctest -V
CMakeLists.txt in ctest
set(SOURCE_FILES
main.cpp
maths/matrix_test.cpp
maths/function_test.cpp
)
# find the Catch2 library
find_package(Catch2 REQUIRED)
# create a test executable
add_executable(ctest ${SOURCE_FILES})
target_link_libraries(ctest maths Catch2::Catch2)
include(CTest)
include(ParseAndAddCatchTests)
ParseAndAddCatchTests(ctest)
The main CMakeLists.txt
# set CMake version
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(mathlib LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_SHARED_LIBRARY_PREFIX "lib")
include(GNUInstallDirs)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
set(LIB_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../libs")
find_package(Catch2 REQUIRED)
enable_testing()
add_subdirectory("${LIB_BASE_DIR}/maths" maths)
add_subdirectory("${LIB_BASE_DIR}/ctest" ctest)
include(CTest)
include(Catch)
catch_discover_tests(ctest)
add_test(
NAME catch_test
COMMAND $<TARGET-FILE>:ctest --success
)
I have looked at the recipes here, the cmake cookbook, modern-cmake, the catch2 github page, but I seem to miss something obvious as for some reason the tests do not get picked up. I have not been able to find an example with add_subdirectory so may be that leads to a different set-up.
If I run
./bin/ctest
all tests run fine. So the executable itself is fine.

Related

CMake with multiple sub projects building into one directory

I'm not very familiar with CMake and still find it quite confusing. I have a project that has a server and client that I want to be able to run independent of each other but that builds together into the same directory (specifically the top level project build directory kind of like how games have the server launcher and game launcher in the same directory) Currently it just creates a builds directory in each sub project, so one in client, one in server etc.
This is my current project structure
.
├── CMakeLists.txt
├── builds
│   ├── debug
│   └── release
├── client
│   ├── CMakeLists.txt
│   ├── assets
│   └── source
│   └── Main.cpp
├── documentation
├── libraries
│   ├── glfw-3.3.7
│   └── glm
├── server
│   ├── CMakeLists.txt
│   └── source
│   └── Main.cpp
└── shared
├── PlatformDetection.h
├── Utility.h
├── events
└── platform
├── linux
├── macos
└── windows
This is my root CMake file
cmake_minimum_required(VERSION 3.20)
project(Game VERSION 1.0.0)
add_subdirectory(libraries/glfw-3.3.7)
add_subdirectory(client)
add_subdirectory(server)
Client CMake file
cmake_minimum_required(VERSION 3.20)
project(Launcher LANGUAGES CXX VERSION 1.0.0)
set(CMAKE_CXX_STANDARD 23)
set(SOURCE_FILES source/Main.cpp ../shared/events/Event.h ../shared/Utility.h
source/Client.cpp source/Client.h ../shared/PlatformDetection.h ../shared/events/EventManagementSystem.cpp
../shared/events/EventManagementSystem.h)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
include_directories(${CMAKE_SOURCE_DIR}/libraries/glm)
include_directories(${CMAKE_SOURCE_DIR}/libraries/glfw-3.3.7/include/GLFW)
include_directories(${CMAKE_SOURCE_DIR}/shared)
add_executable(Launcher ${SOURCE_FILES})
target_link_libraries(Launcher LINK_PUBLIC glfw)
Server CMake file
cmake_minimum_required(VERSION 3.20)
project(ServerLauncher LANGUAGES CXX VERSION 1.0.0)
set(CMAKE_CXX_STANDARD 23)
set(SOURCE_FILES source/Main.cpp ../shared/events/Event.h ../shared/Utility.h
../shared/PlatformDetection.h ../shared/events/EventManagementSystem.cpp
../shared/events/EventManagementSystem.h)
include_directories(${CMAKE_SOURCE_DIR}/libraries/glm)
include_directories(${CMAKE_SOURCE_DIR}/shared)
add_executable(ServerLauncher ${SOURCE_FILES})
How can I make the client and server build into the same directory? And can these cmake file structures be improved at all? They seem quite messy and all over the place to me though that may just be due to my unfamiliarity with CMake.
You cannot have multiple subdirectories use the same build directory, but that doesn't seem what you're trying to achieve.
Assuming you don't set the variable CMAKE_RUNTIME_OUTPUT_DIRECTORY anywhere in your project, and you don't specify the RUNTIME_OUTPUT_DIRECTORY target property for any of your targets by some other means, you could simply set the variable in the toplevel CMakeLists.txt before using add_subdirectory:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
add_subdirectory(...)
...
Note that for distributing the program you should be using install() logic:
Client CMakeLists.txt
...
install(TARGETS Launcher RUNTIME)
Server CMakeLists.txt
...
install(TARGETS ServerLauncher RUNTIME)
Note that you may need to add logic for installing dependencies.
Using those install commands allows you to use
cmake --install <build dir> --prefix <install dir>
to install the programs locally in the default directory for binaries on the system. Furthermore it's the basis for packaging your project using cpack.

CMake not running tests if tests are defined in subdirectory [duplicate]

I have a project with the following structure:
linalg
├── build
├── CMakeLists.txt
├── docs
│   └── Doxyfile
├── include
│   └── linalg
│   └── vector3.hpp
├── src
│   ├── CMakeLists.txt
│   └── linalg
│   └── vector3.cpp
└── test
├── CMakeLists.txt
└── linalg
└── test_vector3.cpp
The file test_vector3.cpp is a gtest unit test file which provides two simple tests. The top level CMakeLists.txt simply sets up the includes and adds the src and test subdirectories:
cmake_minimum_required(VERSION 2.8)
project(linalg)
include_directories(include)
add_subdirectory(src)
add_subdirectory(test)
The src/CMakeLists.txt file compiles vector3.cpp into a static library:
cmake_minimum_required(VERSION 2.8)
add_library(linalg linalg/vector3.cpp)
The test/CMakeLists.txt file is based on the example provided in /usr/share/cmake-2.8/Modules/FindGTest.cmake:
cmake_minimum_required(VERSION 2.8)
enable_testing()
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(test_vector3 linalg/test_vector3.cpp)
target_link_libraries(test_vector3 linalg ${GTEST_BOTH_LIBRARIES} pthread)
add_test(test_vector3 test_vector3)
I then run the following:
cd build
cmake ..
make
I get the liblinalg.a library compiled correctly in to build/src and I get the test_vector3 executable compiled correctly in to build/test. I can run the test_vector3 executable and I get the output from googletest saying that all tests have passed, however if I run make test I get no output whatsoever and if I run ctest .. I get a message saying:
Test project /home/ryan/GitHub/linalg/build
No tests were found!!!
Is there something I am missing? Or have I just misunderstood how ctest works with gtest?
The crux of the problem is that enable_testing should be called from your top-level CMakeLists.txt in this case. Adding include(CTest) to your top-level CMakeLists.txt should fix this for you.
This would allow you to remove the enable_testing call in test/CMakeLists.txt, since the CTest submodule calls enable_testing internally.
Just to update this.
cmake in version 3.9 added support for GoogleTest integration with CTest.
So you can now get CTest to scrape all of the test macros in your test executable, not just the whole executable.
Example here:
https://gist.github.com/johnb003/65982fdc7a1274fdb023b0c68664ebe4

CMake + Qt + GTest files linking

I have a simple CMake + Qt + GTest project:
.
├── CMakeLists.txt
├── src
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── utils
│   ├── calculator.cpp
│   └── calculator.h
└── tests
├── calculator_test.cpp
└── CMakeLists.txt
Root CMakeFiles.txt
cmake_minimum_required(VERSION 3.5)
project(random_project)
# Place binaries and libraries according to GNU standards.
include(GNUInstallDirs)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
# Add source folder.
add_subdirectory(src)
# Add GTest.
include(cmake/googletest.cmake)
fetch_googletest(
${PROJECT_SOURCE_DIR}/cmake
${PROJECT_BINARY_DIR}/googletest
)
enable_testing()
# Add tests folder.
add_subdirectory(tests)
And I want to reach calculator.h in calculator_test.cpp which uses GTest:
#include <gtest/gtest.h>
#include "utils/calculator.h" // <- Want to reach this in that path format.
TEST(example, add)
{
EXPECT_EQ(8, Calculator::sum(3, 5));
}
I have tried to link but then test is not found and the path is releative:
tests/CMakeFiles.txt
# Find the Qt libraries.
find_package(Qt5Widgets REQUIRED)
# Qt5 libraries.
set(QT5_LIBRARIES
Qt5::Widgets)
# Source files.
set(SOURCE_FILES
calculator_test.cpp
../src/utils/calculator.cpp
../src/utils/calculator.h
../src/main.cpp) # If I link like this, test is not found.
# Tell CMake to create the executable.
add_executable(unit_tests ${SOURCE_FILES})
# Use the Widgets module from Qt5.
target_link_libraries(unit_tests ${QT5_LIBRARIES} gtest_main)
# Add tests.
add_test(
NAME unit_tests
COMMAND ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/unit_tests
)
How to link calculator.h in calculator_test.cpp test with CMakeLists.txt?
My Qt project with CMake project file cannot resolve the path to
"someHeader.h". What can I do to fix it?
You can specify the include path:
include_directories("${PROJECT_SOURCE_DIR}/relativePathToHeader")
and likely the path needed:
include_directories("${PROJECT_SOURCE_DIR}/src/utils") or maybe
include_directories("${PROJECT_SOURCE_DIR}/utils") depending on where the source directory actually is.
You need to re-run CMake, of course.

Framework manage libraries

I have a framework wich depends on multiple third party libraries. I would like to share my framework easily. For example the user needs only my includes and add my lib to use my framework, and not all the dependencies.
I use CMake to create my libs, but I am still trying to understand how it works.
The hierarchy of the project
test
├── CMakeLists.txt
├── libA
│   ├── CMakeLists.txt
│   ├── libA.cpp
│   ├── libA.hpp
├── libB
│   ├── CMakeLists.txt
│   ├── libB.cpp
│   ├── libB.hpp
└── test
├── CMakeLists.txt
└── main.cpp
The libB depends on the libA, and I would like to add only the libB to make the project works.
The content of the main CMakeLists.txt located in test/:
cmake_minimum_required (VERSION 2.8.11)
project (C CXX)
include(CheckCXXCompilerFlag)
add_subdirectory("libA")
add_subdirectory("libB")
add_subdirectory("test")
The content of the main CMakeLists.txt located in test/libA:
cmake_minimum_required (VERSION 2.8.11)
project (A CXX)
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++14")
file(GLOB SOURCES "*.cpp")
add_library(A STATIC ${SOURCES})
The content of the main CMakeLists.txt located in test/libB:
cmake_minimum_required (VERSION 2.8.11)
project (B CXX)
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++14")
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-static")
include_directories("../libA")
link_directories("../libA")
file(GLOB SOURCES "*.cpp")
add_library(B STATIC ${SOURCES})
target_link_libraries(B A)
The content of the main CMakeLists.txt located in test/test:
cmake_minimum_required (VERSION 2.8.11)
project (C CXX)
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++14")
include_directories(../libA)
include_directories(../libB)
link_directories(../build/libB)
link_directories(../build/libA)
add_executable(C main.cpp)
target_link_libraries(C B)
If I run the main CMake all works fine, the standalone is well generated.
But if I want to create only the exe by going into test/test and running "cmake . && make", I have an undefined reference to addL(int, int). To make it works I have to add target_link_libraries(C A) at the end of the CMakeLists. Is it normal ? Is it possible to add only the main library without its dependencies ?
Command invocation
target_link_libraries(C B)
have different meanings in your use-cases.
In "all" use-case 'B' is (previously) defined as a CMake target, so CMake knows location of the library (link_directories is not used in that case), and automatically propagates all dependencies of library 'B' to executable 'C'.
In "test-only" use case there is no CMake target named 'B', so it is just transformed to linker option -lB. Linker searches appropriate library file under link directories (link_directories is needed in that case). But information about 'B' dependencies is lost, so automatic linking with A isn't performed.
Your project may provide a standalone CMake script which can be included by a user of your library. The script should define all needed dependencies. Common "types" of such scripts are FindXXX.cmake and XXXConfig.cmake, which can be included via find_package(XXX) command.

Building with libfreenect2

Would anyone be able to post a simple example of how to compile code which uses libfreenect2? After installing the library, the following structure is created in my home directory:
→ tree freenect2
freenect2
├── include
│   └── libfreenect2
│   ├── config.h
│   ├── export.h
│   ├── frame_listener.hpp
│   ├── frame_listener_impl.h
│   ├── libfreenect2.hpp
│   ├── logger.h
│   ├── packet_pipeline.h
│   └── registration.h
└── lib
├── cmake
│   └── freenect2
│   └── freenect2Config.cmake
├── libfreenect2.so -> libfreenect2.so.0.2
├── libfreenect2.so.0.2 -> libfreenect2.so.0.2.0
├── libfreenect2.so.0.2.0
└── pkgconfig
└── freenect2.pc
I attempted to compile with the .pc file using a line similar to this found on the pkg-config wikipedia page:
gcc -o test test.c $(pkg-config --libs --cflags libpng)
But came with up with this error:
./test: error while loading shared libraries: libfreenect2.so.0.2: cannot open shared object file: No such file or directory
Obviously, I messed up the compilation process somewhere, but I'm not sure where to look since this is error occurs on runtime and not at compile time. There's also a .cmake file created with the library install, which I'm sure would lead to a more robust and proper solution, but I'm not entirely sure how to use that and haven't been able to find a simple guide showing how to do so. Any links to beginner-friendly documentation are also appreciated. In the documentation for libfreenect2, it says to use this line when compiling cmake -Dfreenect2_DIR=$HOME/freenect2/lib/cmake/freenect2 -- is this something that I'd have to use when making the library or when making my application?
Another tangentially related question, would it be better to move the /include and /lib directories to /usr/local/include and /usr/local/lib respectively? I believe that would "install" the library system-wide, but I imagine there's some reason that libfreenect2 doesn't do it automatically and I'm not sure what that is.
Well, I just use cmake with a CMakeLists.txt file that I create. Do like this:
Create a CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project("My Project")
set(CMAKE_CXX_FLAGS "-std=c++11")
find_package(freenect2 REQUIRED)
include_directories("/usr/include/libusb-1.0/")
INCLUDE_DIRECTORIES(
${freenect2_INCLUDE_DIR}
)
add_executable(main ./main.cpp)
target_link_libraries(main ${freenect2_LIBRARIES})
In this file, I assume we want to compile the main.cpp file that uses libfreenect2. So, in your local directory create a build folder, using the terminal:
mkdir build && cd build
Then, run the command in the terminal:
cmake -Dfreenect2_DIR=$HOME/freenect2/lib/cmake/freenect2 .. && make
this should create main executable in the build folder. Please, note that this cmake command specifies the freenect2 directory. In this case I assume it was placed in the /home directory.
However, I understand that having to type that long cmake command or search for it on the terminal history may be boring for some people. So, it is possible to embed the command like this:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project("My Project")
set(CMAKE_CXX_FLAGS "-std=c++11")
# Set cmake prefix path to enable cmake to find freenect2
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{HOME}/freenect2/lib/cmake/freenect2)
find_package(freenect2 REQUIRED)
include_directories("/usr/include/libusb-1.0/")
INCLUDE_DIRECTORIES(
${freenect2_INCLUDE_DIR}
)
add_executable(main ./main.cpp)
target_link_libraries(main ${freenect2_LIBRARIES})
After, just run this in the terminal:
mkdir build && cd build && cmake .. & make
This answer was my source for this second way of compiling the code.
Hope this helps!