So, unfortunatly I am unsure how to properly describe the error message.
Essentially I am trying to get used to google test, - I want to use it to test my C++ project in CLion. I create a new library project, with the following classes:
#include "gtest/gtest.h"
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
and also:
#include "gtest/gtest.h"
TEST(MyTestCategory, Vec2DAdditionTest){
EXPECT_EQ(1, 1);
}
Of course these tests are not useful at all - but its just to see if everything works the way it should.
Now when I tried to run them, I am prompted the following error:
6:46 PM Error running 'MyTestCategory.Vec2DAdditionTest': Cannot run 'MyTestCategory.Vec2DAdditionTest' on '<default>'
6:47 PM Error running 'All in main.cpp': Cannot run 'All in main.cpp' on '<default>'
What am I missing? I can't get the tests to run, - neither individually, nor directly over the main function?
Also after this, the build/run button gets greyed out in CLion and I have to right click on the main.cpp to force it to run/compile..
Essential I have a project structure like so:
src/
a.cpp
b.cpp
CMakeLists.txt
test/
main.cpp
atests.cpp
CmakeLists.txt
CMakeLists.txt
My run configuration for the test project looks like so:
Here is an example on how you can add GTests in your CLion project:
Consider a project structure very similar to what you have presented, however, with an additional file CMakeLists.txt.in in the test folder.:
src/
a.cpp
b.cpp
CMakeLists.txt
test/
main.cpp
atests.cpp
CMakeLists.txt
CMakeLists.txt.in
CMakeLists.txt
The CMakeLists.txt.in helps to download and add the GTest libraries to your project while building your project.
The content of CMakeLists.txt.in looks as below:
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
The test/CMakeLists.txt file looks as below:
cmake_minimum_required(VERSION 3.10)
### START OF CONFIGURING GTEST
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
### END OF CONFIGURING GTEST
# Now simply link against gtest or gtest_main as needed. Eg
add_executable(test_${PROJECT_NAME} main.cpp atest.cpp)
target_link_libraries(test_${PROJECT_NAME} ${PROJECT_NAME} gtest gtest_main)
add_test(NAME test_PROJECT_NAME COMMAND test_${PROJECT_NAME})
CMakeLists.txt in the root folder has the following content:
cmake_minimum_required(VERSION 3.10)
project(gtestTest)
set(CMAKE_CXX_STANDARD 14)
add_subdirectory(src)
add_subdirectory(test)
Now reload the CMake configuration and try running the test_gtestTest target to run the unit tests.
You can also create custom run configurations using gtest template of CLion to get user friendly test reports.
For more information on GTests with CLion, please refer to:
Google Test Support in Clion
Building Google Tests with CMake
Related
I want to integrate CasADi into a CMake-based C++ codebase as an ExternalProject. For this purpose, I would like to use pre-compiled libraries because building from source is not recommended. So far, I have only managed to write the following:
ExternalProject_Add(
casadi-3.5.5
URL https://github.com/casadi/casadi/releases/download/3.5.5/casadi-linux-py39-v3.5.5-64bit.tar.gz
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
PREFIX ${CMAKE_BINARY_DIR}/external/casadi)
and I noticed that all the binaries are correctly downloaded in the specified folder. However, I do not know how to link my targets to CasADi, nor how to find the package.
There is a natural problem with ExternalProject_Add:
ExternalProject_Add executes commands only on build.
Hence, download will not happen at the configure stage of your project which makes it difficult to use find_package, because the files cannot be found during your first configure run.
Take this CMakeLists.txt:
cmake_minimum_required(VERSION 3.21)
project(untitled)
set(CMAKE_CXX_STANDARD 17)
add_executable(untitled main.cpp)
include(ExternalProject)
ExternalProject_Add(
casadi-3.5.5
URL https://github.com/casadi/casadi/releases/download/3.5.5/casadi-linux-py39-v3.5.5-64bit.tar.gz
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
PREFIX ${CMAKE_BINARY_DIR}/external/casadi)
find_package(casadi HINTS ${CMAKE_BINARY_DIR}/external/casadi/src/casadi-3.5.5/casadi)
target_link_libraries(untitled casadi)
In order to use it you have to do the following:
Configure your project
mkdir build
cd build
cmake ..
Build (download) casadi-3.5.5
cmake --build . --target casadi-3.5.5
Reconfigure your project, because now find_package will find the needed files
cmake ..
Build your targets
cmake --build .
If you want a one step build, there are ways to get around this problem
Use FetchContent
Create a sub-cmake-project in a subfolder with all the ExternalProject_Add commands and execute the approriate build (download) steps manually in your own CMakeLists.txt via execute_process calls: https://stackoverflow.com/a/37554269/8088550
Here is an example for the second option, which might be better since FetchContent doesn't have the full functionality of ExternalProject.
main.cpp
#include <casadi/casadi.hpp>
int main()
{
casadi_printf("This works!");
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(untitled)
set(CMAKE_CXX_STANDARD 17)
# some default target
add_executable(untitled main.cpp)
# Configure and build external project
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/external)
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/external
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/external
)
execute_process(
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/external
)
# find and link externals
find_package(casadi REQUIRED HINTS ${CMAKE_BINARY_DIR}/external/external/casadi/src/casadi-3.5.5/casadi)
target_link_libraries(untitled casadi)
external/CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(external)
include(ExternalProject)
ExternalProject_Add(
casadi-3.5.5
URL https://github.com/casadi/casadi/releases/download/3.5.5/casadi-linux-py39-v3.5.5-64bit.tar.gz
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
PREFIX ${CMAKE_BINARY_DIR}/external/casadi)
The point is to have another cmake project under external/CMakeLists.txt, which gets configured and build via execute_process calls from the main cmake project. Do note, that you can now have find_package(casadi REQUIRED ...) at configure stage, because the download will happen just before.
I was making use of gtest to test my c++ project. I followed the steps from here
Everything went well but when I ran the cd build && ctest command i'm getting the output as Test project C:/Users/admin/Desktop/last/build No tests were found!!!
My CMakeLists.txt file
cmake_minimum_required(VERSION 3.14)
project(last)
# GoogleTest requires at least C++11
set(CMAKE_CXX_STANDARD 11)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
enable_testing()
add_executable(
hello_test
fact.cpp
header.h
main.cpp
testt.cpp
)
target_link_libraries(
hello_test
gtest_main
)
include(GoogleTest)
gtest_discover_tests(hello_test)
I changed a line in my CMakeLists file
add_executable(
hello_test
header.h
main.cpp
)
And added a line
add_test(testt.cpp hello_test)
This gave me the output correctly and ran the tests
This question already has answers here:
How to start working with GTest and CMake
(11 answers)
Closed 2 years ago.
I am developing a C/C++ app using CMake. I want to use GTest in my project for unit testing. For this I have decided to use GTest as a git submodule in my repository.
My directory hierarchy is as follows:
/
--include
--lib
--GoogleTest
--src
--Tests
The GoogleTest subdirectory in lib contains the source code of GTest from their official repository.
But I am unable to use it to test my source. The CMakeLists.txt file at the root of my repository is as follows:
OPTION (BUILD_UNIT_TESTS "Build unit tests" ON)
if (BUILD_UNIT_TESTS)
enable_testing ()
find_package (GTest REQUIRED)
add_subdirectory (Tests)
endif ()
But I receive the error:
Error:Could NOT find GTest (missing: GTEST_LIBRARY GTEST_INCLUDE_DIR
GTEST_MAIN_LIBRARY)
When I searched for this, there were many questions similar to mine, but none of them addressed my problem. And their manual is very limited and does not tell much about its usage properly.
CMake is successfully able to build the target GTest but fails to recognise it when I try to use it as an external package.
You don't have to manually download the Gtest git. Just add the following lines to your CMakeLists.txt
# -------- GOOGLE TEST ----------
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
# The gtest/gtest_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include")
endif()
# -------------------------------------------------------------------------
enable_testing()
include_directories("${gtest_SOURCE_DIR}/include")
And add the following lines to another file, named CMakeLists.txt.in, in the same directory your CMakeLists.txt file is
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.10.0
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
What does it do ?
The things you added to your main CMakeLists will download GTest and GMock git projects at the version specified in the CMakeLists.txt.in file. Then it will build these, and include the build path in your main project.
Source : GoogleTest Git
I'm trying to add gtest to an existing UWP project that is being built by CMake.
The build process seems fine and I'm able to create and build the project using:
cmake ../ -G "Visual Studio 15 2017 Win64" -T v141 -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.14393.0 -Dgtest_disable_pthreads=ON -DCMAKE_USE_WIN32_THREADS_INIT=ON
However when I run the test I get:
E:\Test-Gtest\build>ctest -C Debug
Test project E:/Test-Gtest/build
Start 1: example_test
1/1 Test #1: example_test .....................Exit code 0xc0000135
***Exception: 0.03 sec
0% tests passed, 1 tests failed out of 1
Total Test time (real) = 0.05 sec
The following tests FAILED:
1 - example_test (Exit code 0xc0000135
)
Errors while running CTest
Trying to run the executable example.exe results in:
VCRUNTIME140D_APP.dll was not found
followed by
MSVCP140D_APP.dll was not found
This is a link to a MCVE on github for convenience which has the following structure (mostly based on the guidelines in the docs):
│ CMakeLists.txt
│
└───src-test
│ CMakeLists.txt
│ CMakeLists.txt.in
│
└───src-integration
basic_logon.cpp
main CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(TestGtest CXX C)
set (CMAKE_CXX_STANDARD 14)
enable_testing()
add_subdirectory(src-test)
src-test CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
# Now simply link against gtest or gtest_main as needed. Eg
message(STATUS "CMAKE_CURRENT_LIST_DIR: ${CMAKE_CURRENT_LIST_DIR}")
file(GLOB SRC_TEST_INTEGRATION_FILES ${CMAKE_CURRENT_LIST_DIR}/src-integration/*.cpp)
add_executable(example ${SRC_TEST_INTEGRATION_FILES})
target_link_libraries(example gtest_main)
add_test(NAME example_test COMMAND example)
CMakeLists.txt.in
cmake_minimum_required(VERSION 3.12)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.8.1
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
basic_logon.cpp
#include "gtest/gtest.h"
#include <cmath>
TEST(Pow, Two)
{
EXPECT_EQ(4, std::pow(2,2));
}
I am trying to incorporate GTests in my project using CMake. I followed this instruction and I get following error:
Undefined symbols for architecture x86_64:
"SomeClass::someMethod()", referenced from:
someMethod_TrivialTest_Test::TestBody() in SomeClassTest.cpp.o
ld: symbol(s) not found for architecture x86_64
Here is my CMake file:
cmake_minimum_required(VERSION 3.11)
project (someProject)
set(CMAKE_CXX_STANDARD 17)
#Include headers
include_directories("../include")
#Add source files
file(GLOB SOURCES "src/*.cpp")
add_executable(someProject ${SOURCES})
################################
# GTest
################################
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
${CMAKE_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
# The gtest/gtest_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include")
endif()
# Add test cpp file
add_executable( someTests ./test/SomeClassTest.cpp)
# Link test executable against gtest & gtest_main
target_link_libraries(someTests gtest gtest_main)
add_test( someTests someTests )
My project structure (CMakeLists.txt.in is used to download the GTest library, added from the instruction mentioned above):
.
├── CMakeLists.txt
├── CMakeLists.txt.in
├── include
│ └──SomeClass.hpp
├── src
│ ├── Main.cpp
│ └── SomeClass.cpp
└── tests
└── SomeClassTest.cpp
If I manually create and link objects, it works.
g++ -c ./src/SomeClass.cpp
g++ -c ./test/SomeClassTest.cpp
g++ SomeClassTest.o SomeClass.o ./build/googletest-build/googlemock/gtest/CMakeFiles/gtest.dir/src/gtest-all.cc.o -o myTests
The object of the test class seems to be there:
./build/CMakeFiles/someTests.dir/test/SomeClassTest.cpp.o
But the directory for the someProject object is empty:
./build/CMakeFiles/someProject.dir/src/
So I am missing something in the CMake file and it is not linking properly. All the answers I could find so far were related to specifying target_link_libraries but I am not sure if that is the problem here. I am new to CMake and linking issues. Would reeeally appreciate any advice!
All the answers I could find so far were related to specifying target_link_libraries but I am not sure if that is the problem here.
You were right on track with this assumption.
Currently, you're telling CMake that there is an executable to be built from some sources and a test to be built from some other sources and linked with gtest. CMake doesn't know that the executable and your test are in any way related, though!
I see two possible solutions:
add the sources of the executable (except the one with the main function) as sources to the test.
build all of the sources from the executable (except the one with the main function) as library and link both the executable and the test to that library.
I prefer the later one, which would - roughly - look like:
add_library(someProgram_lib ${SOURCES})
add_executable(someProgram src/main.cc)
target_link_libraries(someProgram someProgram_lib)
add_executable(someTests ./test/SomeClassTest.cpp)
target_link_libraries(someTests gtest gtest_main someProgram_lib)