kdevelop Unit-Tests with gtest - c++

I have a gtest cmake project that can be compiled and debugged with kdevelop. Since version 4.5 kdevelop can handle unit tests. I do not find a way to integrate the tests to kdevelop "Unit-Tests". Does anybody know how to do it?

For test binaries to show up in the Unit-Tests tab in Kdevelop (tested on 5.3) you need to make your testcases be recognized by CTest.
If you have a dedicated CMakeLists.txt for your test-executable a minimal configuration could look like this:
set (SOURCES
testsource.cpp
)
add_executable(testexecutable ${SOURCES})
target_link_libraries(testexecutable
gtest
)
add_test(
NAME test
COMMAND testexecutable )
Additionally for it to be working with a standard CMake configuration run you need to add
enable_testing()
somewhere in your CMake project, eg. your main CMake file.
I found further documentation here:
https://cmake.org/cmake/help/latest/command/add_test.html
https://gitlab.kitware.com/cmake/community/wikis/doc/ctest/Testing-With-CTest
Be aware that this only adds basic execution of the testcase binaries to the KDevelop GUI. There is no customisation or/filtering in the GUI that I know of.
You may also have a look at the gtest specific defintions for cmake/ctest. I didn't try any of these as I'm stuck on a CMake version which does not support these yet.
https://blog.kitware.com/dynamic-google-test-discovery-in-cmake-3-10/

Related

Include googletest into CMake installation process

I have a C++ project that I am able to compile into a static library using CMake. I am also testing this project using googletest but after sifting through previous answers on getting the utility working with CMake projects I am stuck.
The root dir of my project contains the necessary code to compile my project into a static lib in the standard paths. Here is an example of the CMakeLists.txt file in my tests/ directory :
# Download and install GoogleTest
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
FetchContent_MakeAvailable(googletest)
# TESTS
add_executable(
bin test.cpp
)
# enable testing
enable_testing()
target_link_libraries(
bin
lib
# GTest::gtest
GTest::gtest_main
pthread
)
include(GoogleTest)
gtest_discover_tests(bin)
This successfully build the googletest library and my tests but doesn't run them automatically. I had to run ctest manually after my process to see the result of my tests. I want my typical cmake.. , make, make install process to build my project upon successful tests. Is there a way to do this? I think it makes sense for tests to pass as the first step before installing the library itself. Is there also a way to check for an installation of googletest on the system before installing the package from source?
To my understanding - both gtest_discover_tests() and gtest_add_tests() are only for replacing CMake's add_test() i.e. they discover and add tests to the ctest executable .
It is also not standard that you run tests during cmake <...>, make <...>, make install. So a good thing to think about is, to make an option that allows the end-user to decide if he/she wants to run tests.
That being said the easiest way on how to get your tests to run let's say - post build. Is to add_custom_command(), e.g.:
if(RUN_MTPK_TESTS)
add_custom_command(TARGET test_openMTPK
POST_BUILD
COMMAND ctest --output-on-failure)
endif()
Then by running: cmake -S[source] -B[build] -DRUN_MTPK_TESTS=TRUE you will, after running make, execute your tests through ctest.
To answer your last question, is there a way on how to check if googletest is already installed? Yes there is and it requires some additional conditions in your CMakeLists.txt. Example:
find_package(GTest)
if(NOT GTest_FOUND)
#FetchContent, etc...
endif()
#rest of your cmakelists
EDIT: Check find_package() for more information regarding the use of find_package and what variables it sets and how can you customize the behavior of said command.

Unknown command : QT5_ADD_TRANSLATION in Qt cmake project

I'm developing Qt application and now I want to do some I18N stuff. First problem I meet is that cmake doesn't know about command QT5_ADD_TRANSLATION(we are using cmake for building our project). I refer to QtLinguist Manual. When I met that problem, I also read threads like Unknown CMake command "QT5_CREATE_TRANSLATION" and qt4 to qt5 migration, but unluckily, I still stuck here.
My cmake version is 3.16 for Qt 5.15.2. If you need more informations, please let me know.
Besides, If there is an alternative way to accomplish I18N work in Qt with cmake, that is also fine. For example, I come up with add_custom_command with lupdate from qt, but don't success yet.
add_custom_command(OUTPUT ${TRANSLATIONS}
DEPENDS ${SOURCES}
COMMAND lupdate)
command won't execute. I'm still try it.
It should be something like this:
find_package(Qt5 COMPONENTS LinguistTools)
qt5_add_translation(OUTPUT_VAR your_translation.ts)
CMake functions/macros provided by Qt itself belong to some particular module so you need to find that module before using its functioncs.

How to use pkg-config in CMake (juCi++)

I've been happily programming in C++ and compiling with g++ for quite a while. Not long ago, I'd decided to get an IDE, and I came accross juCi++.
This IDE is absolutely brilliant, but it uses CMake (or Meson) to build projects. This wasn't a problem, until I had to include a library (GTK+ 3.0 if you're wondering) using pkg-config. This could be done quite easily when compiling with g++, but, as I am completely new to CMake, I have no idea how to do it in the new IDE.
Can somebody please explain?
If your IDE handles CMake and Meson, it should be able to detect your project files. I'd say go for Meson, it's the future, and CMake syntax has a few quirks that Meson doesn't.
Meson:
Meson documentation
He's a basic meson.build that expects to find your application code in main.c and produces a binary named gtk3-test.
project('gtk3-test', 'c')
cc = meson.get_compiler('c')
deps = dependency ('gtk+-3.0')
sources = ['main.c']
executable('gtk3-test', sources, dependencies: deps)
CMake
CMake documentation
For CMake, just give a look at my answer to How do I link gtk library more easily with cmake in windows? (which also works under Linux). It was for GTK+2, but adapting it to GTK+3 is easy, so here's the CMakeLists.txt to use:
project (gtk3-test)
cmake_minimum_required (VERSION 2.4)
find_package (PkgConfig REQUIRED)
pkg_check_modules (GTK3 REQUIRED gtk+-3.0)
include_directories (${GTK3_INCLUDE_DIRS})
link_directories (${GTK3_LIBRARY_DIRS})
add_executable (gtk3-test main.c)
add_definitions (${GTK3_CFLAGS_OTHER})
target_link_libraries (gtk3-test ${GTK3_LIBRARIES})

How can I use CMake to both build wxwidgets on-demand and link with it

I have the following situation:
I'm working on an application that depends on a number of third party libs, among them wxwidgets
I build the application for multiple target configurations (x86, arm, Linux, Windows) using Linux as my build host system
Due to the above mentioned multiple target configurations, I have chosen to build those third-party libs from source, using CMake's ExternalProject_Add function.
The third-party libs are built 'on-demand' at a location separate from my application's CMAKE_BINARY_DIR so that I can wipe the build tree for my application without having to rebuild the third-party libs (takes a looooong time).
The location of the third-party libs is different depending on what target configuration I build them for (obviously).
I'm quite new to CMake and the problem I currently face is this:
The source files in my application can't find the wx include files and I need to set the correct linker flags to be able to link my application against wxwidgets.
This seems to be handled by a utility 'wx-config' that provides exactly that info as output when run with either the --cppflags or --libs flag. I can not however, figure out how to catch that output and append it to the include dirs and linked libraries I setup from my CMakeLists.txt files.
So basically what I want is.
Build wxwidgets (if it doesn't exist) for the current target configuration
Run wx-config --cppflags and --libs to find out the correct include dirs and linker flags for the current target configuration
Use the info from step 2 when building targets that are my own application
So far I've tried something like this:
# Set a target-configuration-specific location
set(wxwidgetsTop ${MYPROJECT_EXTERNAL_DIR}/wxwidgets/wxwidgets_${MYPROJECT_CURRENT_TARGET_CFG})
# Build the project
ExternalProject_Add( wxWidgetsExternal
PREFIX ${wxwidgetsTop}
URL ${MYPROJECT_EXTERNAL_DIR}/tarballs/wxWidgets-3.0.2.tar.bz2
SOURCE_DIR ${wxwidgetsTop}/src/wxwidgets
CONFIGURE_COMMAND ${configure_cmdline}
BUILD_COMMAND make -j${MYPROJECT_NCPU}
INSTALL_COMMAND make install
)
# Create a wxwidgets target to be used as a dependency from other code
add_library(wxWidgets IMPORTED STATIC GLOBAL)
add_dependencies(wxWidgets wxWidgetsExternal)
# (non-working) attempt to get the correct include dirs and linker
# flags for wxwidgets
add_custom_command(TARGET wxWidgetsExternal
POST_BUILD
COMMAND ${INSTALL_DIR}/bin/wx-config ARGS --cppflags
COMMENT "Running wx-config"
)
but the above does not provide a way to actually use the result from the custom command to append the cppflags and linker options when building the targets that make up my application.
What is a good way to achieve what I want?
I see three different ways of doing this:
Method 1: use find_package
Use wxWidgets as a standalone requirement for your project, and expect the devs to install it before building your project. In your CMakeLists.txt you will need to call find_package(wxWidgets), like this:
find_package(wxWidgets COMPONENTS net gl core base)
if(wxWidgets_FOUND)
include(${wxWidgets_USE_FILE})
# and for each of your dependent executable/library targets:
target_link_libraries(<YourTarget> ${wxWidgets_LIBRARIES})
endif()
This has the advantage of not rebuilding the lib if you rebuild your project, however it requires some work for your user (they need to handle the installation of wxWidgets by hand) and for you (you need to setup include paths / compile definitions / ... by hand).
Method 2: embed wxWidgets
The second option is to bundle wxWidgets in your repo (svn external or git submodule) and usually (re)write the CMakeLists.txt of this lib to be target-oriented. Then, in your top-most CMakeLists.txt, you can do the following:
# for example, if you just need core and net:
target_link_librairies(my_app PUBLIC wxWidgetsCore wxWidgetsNet)
# No need to manually setup include dirs, etc...
To make a CMakeLists.txt target-oriented, you define include directories and other compilation properties for a target, not a directory. Example:
# When defining wxWidgetsCore, for example
add_library(wxWidgetsCore ...)
target_include_directories(wxWidgetsCore PUBLIC someDir)
target_compile_definitions(wxWidgetsCore PUBLIC -pedantic)
target_link_libraries(wxWidgetsCore PUBLIC someLib)
The drawback of this approach is that rebuilding your project will trigger a rebuild of wxWidgets. However, it is possible to trick this by not using "rebuild" but "clean just my app, then build". Here is some insight on how to achieve this.
Method 3: some sort of hybrid
The big drawback of method 2 leads to the third approach: don't put wxWidgets in your project, but create a CMakeLists.txt that will "import" the lib. The idea: you ask your user for the directory where wxWidgets is installed, then this script will setup everything for your project. First, put the CMakeLists.txt here:
/your-project-root
/thirdparty
/wxWidgets
CMakeLists.txt
/dir-where-wxwidgets-is-installed
...
Now, you define an imported target:
# When defining wxWidgetsCore, for example
set(WX_INCLUDE_DIR ${USER_SPECIFIED_WX_ROOT}/include)
add_library(wxWidgetsCore IMPORTED GLOBAL)
set_property(TARGET wxWidgetsCore APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${WX_INCLUDE_DIR})
See INTERFACE_INCLUDE_DIRECTORIES and INTERFACE_LINK_LIBRARIES. You need your user to have build wxWidgets somewhere in his system, but from your point of view you just do target_link_libraries(your_app PUBLIC wxWidgets...), as in method 2. The advantage is that this approach is interchangeable with method 2 transparently, and you don't put the whole dependency in your project.
Setting cppflags and linker flags has to be done at CMake time, but you are trying to run wx-config at build time and you are not capturing its output anyway, so your add_custom_command() isn't doing anything useful other than printing things to the build tool's output.
Ideally, you would use the FindwxWidgets module CMake already provides. It requires wxWidgets to already be built (but see further below). Have a look at the CMake documentation for it and see if that at least sounds like what you are trying to achieve manually by using wx-config. If you can get FindwxWidgets to do the job for you, that would be a much cleaner approach.
Getting something to build at configure time so you can use it later on in your CMakeLists.txt file is a bit more tricky. ExternalProject_Add() downloads and builds things at build time, but you need wxWidgets to be built earlier at configure time. I wrote an article recently for how to do at least the downloading part at configure time and you should be able to adapt it to do the whole build at configure time instead. The article uses Google Test as its example and can be found here:
https://crascit.com/2015/07/25/cmake-gtest/
It would be trivial to make it put the wxWidgets build wherever you like, not just in the CMAKE_BINARY_DIR area. That would allow you to have different wxWidgets builds for each build configuration and to be able to wipe out your application's build tree independently of the wxWidgets builds.
Hope that points you in the right direction.
The solution I use checks for wxWidgets installation in the system using find_package, if it's not found, then the script downloads wxWidgets from github and links the program against downloaded library. The lib is installed in the build directory, so only the first build is slow - subsequent builds do not even check wxWidgets sources timestamps, so the process is as fast as building using preinstalled wxWidgets library.
Here's how my script does it:
It quietly checks for wxWidgets installation using find_package(wxWidgets QUIET),
If it's found, the script adds a dummy library wxWidgets_external,
If it's not, then it creates an ExternalProject named wxWidgets_external which downloads, builds and installs the library in the build dir, setting wxWidgets_ROOT_DIR to point to the wxWidgets installation dir,
Then we add another ExternalProject pointing to a folder with the main program's source files and CMakeLists.txt build script. This external projects depends on wxWidgets_external which is either a dummy library in case wxWidgets is preinstalled in the system, or an external project set up to download the library from github,
In the aforementioned CMakeLists.txt we again call find_package, this time with REQUIRED parameter and use the library the standard way (https://docs.wxwidgets.org/trunk/overview_cmake.html). Because we set up the dependencies and variables correctly, this call will use either preinstalled wxWidgets (if it's available) or the one downloaded from github.
There are more quirks to it, but that's the gist of it. The full sample code (tested on Linux, Windows and Mac) is available on github (https://github.com/lszl84/wx_cmake_template).
Also see full blog post which explains this in more detail: https://justdevtutorials.medium.com/wxwidgets-cmake-multiplatform-superbuild-4ea86c4e6eda

Building gtest for visual studio using cmake

I'm really new to cmake, I'm using it because I want to build gtest for multiple versions of VS at the same time. I havent been able to generate anything using cmake yet.. maybe its overkill for my application?
How can I build gtest for multiple versions of VS using cmake, either at the same time, or using some kind of parameters?.
Something which may help would be to build gtest as part of your main CMake build. That way, gtest will always use the same compiler and settings as your main build and you then shouldn't need to pre-build it for each of the different compilers you want to support. Making gtest part of your build also has the advantage that it's really easy to link your tests against gtest, since CMake already knows about the gtest library target, so you don't have to use find_package(GTtest) or tell CMake where to find the gtest libraries.
I recently wrote a blog article about how to do this which may help you. You can find it here:
https://crascit.com/2015/07/25/cmake-gtest/
Update: This approach is now also part of the googletest documentation.