When using CMake + CTest + CDash can I have an optional test fixture? - cmake

I am using CMake FIXTURES_SETUP/FIXTURES_REQUIRED to only run tests if an external resource is available. However, the external resource is optional (available on some test machines, but not others) so when the fixture that checks for the resource fails I do not want to consider the tests suite to have failed, I simply do not want to run any tests that require the fixture. Is there a way to mark a test fixture as 'allowed to fail'. I know there is WILL_FAIL but this inverts the sense of the test so that it would be marked as failure when it passes.

No. When you add a test that means you expect that test to pass. When a prerequisite of that test fails, CMake skips that test (does not actually run it) and counts it as failed because it did not succeed.
e.g.
# CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(example)
enable_testing()
add_test(NAME failIfUnavail COMMAND false)
add_test(NAME dependentTest1 COMMAND true)
add_test(NAME dependentTest2 COMMAND true)
add_test(NAME cleaner COMMAND true)
set_tests_properties(failIfUnavail PROPERTIES FIXTURES_SETUP example_case)
set_tests_properties(dependentTest1 dependentTest2 PROPERTIES FIXTURES_REQUIRED example_case)
set_tests_properties(cleaner PROPERTIES FIXTURES_CLEANUP example_case)
$ cmake -H. -Bbuild
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /bin/gcc
-- Check for working C compiler: /bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /bin/g++
-- Check for working CXX compiler: /bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /build
$ cmake --build build/ --target test
Running tests...
Test project /home/pamini/cmake_test1/build
Start 1: failIfUnavail
1/4 Test #1: failIfUnavail ....................***Failed 0.00 sec
Start 2: dependentTest1
Failed test dependencies: failIfUnavail
2/4 Test #2: dependentTest1 ...................***Not Run 0.00 sec
Start 3: dependentTest2
Failed test dependencies: failIfUnavail
3/4 Test #3: dependentTest2 ...................***Not Run 0.00 sec
Start 4: cleaner
4/4 Test #4: cleaner .......................... Passed 0.00 sec
25% tests passed, 3 tests failed out of 4
Total Test time (real) = 0.02 sec
The following tests FAILED:
1 - failIfUnavail (Failed)
2 - dependentTest1 (Not Run)
3 - dependentTest2 (Not Run)
Errors while running CTest
gmake: *** [test] Error 8
What you can do is:
If the resource's availability is known at configuration time then check and only add the tests when you expect them to pass.
If the resource's availability is not known at configuration time then modify the tests themselves to account for this uncertainty. For example, unit tests avoid this issue by using mock objects that imitate the behavior of the resources they depend on.

Related

cmake cannot find an existing directory on mingw64 (msys2)

I am trying to compile a project under MSYS2 and CLANG64 environment.
I have previously compiled dependencies in /usr/local.
$ ls /usr/local/include
boost compat-5.3.c cryptopp lauxlib.h libmongoc-1.0 lua.hpp luajit.h mongocxx yaml-cpp
bsoncxx compat-5.3.h gtest libbson-1.0 lua.h luaconf.h lualib.h tsl
$ ls /usr/local/lib
cmake libboost_filesystem-mt-s-x64.a libbson-static-1.0.a libmongoc-1.0.dll.a
libboost_atomic-mt-s-x64.a libboost_program_options-mt-s-x64.a libbsoncxx-static.a libmongoc-static-1.0.a
libboost_atomic-mt-x64.a libboost_regex-mt-s-x64.a libcryptopp.a libmongocxx-static.a
libboost_chrono-mt-s-x64.a libboost_system-mt-s-x64.a libgtest.a libyaml-cpp.a
libboost_container-mt-s-x64.a libboost_thread-mt-s-x64.a libgtest_main.a pkgconfig
libboost_context-mt-s-x64.a libbson-1.0.dll.a liblua-compat.a
But when I create the project, I explicitly set the location of binaries with interface libraries as I don't want to rely on the find mechanism that has hurt me badly in the past - linking to unintended, old system libraries.
project(test)
cmake_minimum_required( VERSION 3.0 )
add_library( cryptopp STATIC IMPORTED GLOBAL )
set_target_properties( cryptopp PROPERTIES
IMPORTED_LOCATION "/usr/local/lib/libcryptopp.a"
INTERFACE_INCLUDE_DIRECTORIES "/usr/local/include"
INTERFACE_COMPILE_DEFINITIONS "HAVE_CRYPTOPP"
)
add_executable( test test.cpp )
target_link_libraries( test cryptopp )
This works perfect under all Linux distros - Redhat, Ubuntu, etc but fails in MSYS2.
However when I run cmake, I get an error stating that /usr/local/include does not exist.
$ cmake ..
-- Building for: Ninja
-- The C compiler identification is Clang 14.0.4
-- The CXX compiler identification is Clang 14.0.4
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: G:/msys64/clang64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: G:/msys64/clang64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
CMake Error in CMakeLists.txt:
Imported target "cryptopp" includes non-existent path
"/usr/local/include"
in its INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:
* The path was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and references files it does not
provide.
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
I just cannot figure out why this is happening. Any clues?
Maybe it's a Windows path issue. Try replacing /usr/local with the output of cygpath -m /usr/local.

Having problems with mingw32-make to make googletest

This is my current environment.
Windows 10 64bit, MinGW, CMake 3.15.2, Python 3.7.
I downloaded googletest from https://github.com/google/googletest.
I ran cmake and the following is the output.
C:\googletest-master>cd build
C:\googletest-master\build>cmake ../ -G "MinGW Makefiles"
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: C:/MinGW/bin/gcc.exe
-- Check for working C compiler: C:/MinGW/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PythonInterp: C:/Users/sangjin/AppData/Local/Programs/Python/Python37-32/python.exe (found version "3.7.4")
-- Configuring done
-- Generating done
-- Build files have been written to: C:/googletest-master/build
But when I ran mingw32-make I got the following error message.
C:\googletest-master\build>mingw32-make
Scanning dependencies of target gtest
[ 12%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.obj
In file included from C:\googletest-master\googletest\src\gtest-all.cc:41:
C:/googletest-master/googletest/src/gtest.cc:86:11: fatal error: crtdbg.h: No such file or directory
# include <crtdbg.h> // NOLINT
^~~~~~~~~~
compilation terminated.
googletest\CMakeFiles\gtest.dir\build.make:62: recipe for target 'googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.obj' failed
mingw32-make[2]: *** [googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.obj] Error 1
CMakeFiles\Makefile2:171: recipe for target 'googletest/CMakeFiles/gtest.dir/all' failed
mingw32-make[1]: *** [googletest/CMakeFiles/gtest.dir/all] Error 2
Makefile:139: recipe for target 'all' failed
mingw32-make: *** [all] Error 2
C:\googletest-master\build>
Can anyone help me fix this problem.
This version of google test doesn't have that issue, try to build it
https://github.com/google/googletest/tree/216c37f057ae0fff38062984c890df912f40ccf6
Here is a solution for
mingw32-base version 2013072200
mingw32-gcc-g++ version 6.3.0-1
gtest version 1.10.0
In ...\googletest\src\gtest.cc
first at (original) line 86, make header inclusion conditional to MSC toolchain using #ifdef _MSC_VER ... #endif preprocessor macros.
#ifdef _MSC_VER
# include <crtdbg.h> // NOLINT
# include <debugapi.h> // NOLINT
#endif // _MSC_VER
then at (original) line 4913, make assertion redirection also conditional.
#ifdef _MSC_VER
// In debug mode, the Windows CRT can crash with an assertion over invalid
// input (e.g. passing an invalid file descriptor). The default handling
// for these assertions is to pop up a dialog and wait for user input.
// Instead ask the CRT to dump such assertions to stderr non-interactively.
if (!IsDebuggerPresent()) {
(void)_CrtSetReportMode(_CRT_ASSERT,
_CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
(void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
}
#endif // _MSC_VER
With theese changes, unit tests build and execute as expected.

Cmake is unable to find packages of Gmock

I am new to Cmake and Gtest. I have a problem with in CMake
find_package(GMock REQUIRED)
and
target_link_libraries(runtest ${GMOCK_BOTH_LIBRARIES} pthread).
When I build the project, CMake is unable find the GMock packages.
But when I mentioned the absolute paths of library, it is working fine.
For example:
set(GMOCK_INCLUDE_DIRS /usr/local/include/gmock)
set(GMOCK_BOTH_LIBRARIES /usr/local/lib/libgmock.a /usr/local/lib/libgmock_main.a /usr/local/lib/libgtest.a /usr/local/lib/libgtest_main.a)
Now the problem is my Supervisor recommended me to find the solution to run the code using find packages only. After doing some research, I came to know that FindGMock.cmake file is missing from the Cmake modules. I added it and run code again with find_package(), but still it is not working.
Errors are undefined references to functionalities of Gmock and Gtest.
For instance :
undefined reference to `testing::Message::Message()'.
undefined reference to testing::internal::GetBoolAssertionFailureMessage.
undefined reference totesting::internal::AssertHelper::~AssertHelper()'
Like this there too many errors.
Could anyone please explain me, how to make CMake to find the GMock packages automatically?
Here's a step-by-step example of building and linking to GMock from a CMake project on Linux from scratch. Steps 0-4 cover building and installing GMock while steps 5 and beyond address the question.
These steps are fairly generic and will work with little modification for any project that provides its own CMake package.
Step 0: Create a working directory
From my home folder, I created a blank directory called test:
alex:~$ mkdir test
alex:~$ cd test
alex:~/test$ ls
Step 1: Download GMock
GMock is included in the Google Test repository, so we clone that repository.
alex:~/test$ git clone https://github.com/google/googletest
Cloning into 'googletest'...
remote: Enumerating objects: 24427, done.
remote: Counting objects: 100% (92/92), done.
remote: Compressing objects: 100% (45/45), done.
remote: Total 24427 (delta 44), reused 72 (delta 38), pack-reused 24335
Receiving objects: 100% (24427/24427), 10.32 MiB | 2.68 MiB/s, done.
Resolving deltas: 100% (18062/18062), done.
Step 2: Configure GMock
We'll use the following command to build the googletest repository; GMock is included by default.
$ cmake -S googletest/ -B _build/googletest -DCMAKE_BUILD_TYPE=RelWithDebInfo
The -S flag sets the source directory to the root of the Google Test repository we just cloned. This tells CMake which project it's building. The -B flag sets the binary directory to ~/test/_build/googletest, which is where CMake will store intermediate build outputs before they are installed. This should always be distinct from the source directory. Finally, since we are using a single-configuration generator (Make is the default on Linux), we must specify the build type at this time. I have chosen RelWithDebInfo to keep debugging easy, but also to enable optimizations.
In general, you should always build your project with in the same configuration as its dependencies, so we'll use RelWithDebInfo again later.
For more detail on how to configure generic CMake projects, I'll refer you to this question/answer: How do I build a CMake project?
Finally, here's the output of running the command:
alex:~/test$ cmake -S googletest/ -B _build/googletest -DCMAKE_BUILD_TYPE=RelWithDebInfo
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Python: /usr/bin/python3.10 (found version "3.10.4") found components: Interpreter
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/googletest
Step 3: Build GMock
Now we'll go ahead and run the build. The following command will work with any single-config generator:
alex:~/test$ cmake --build _build/googletest/
[ 12%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 25%] Linking CXX static library ../lib/libgtest.a
[ 25%] Built target gtest
[ 37%] Building CXX object googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
[ 50%] Linking CXX static library ../lib/libgmock.a
[ 50%] Built target gmock
[ 62%] Building CXX object googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o
[ 75%] Linking CXX static library ../lib/libgmock_main.a
[ 75%] Built target gmock_main
[ 87%] Building CXX object googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[100%] Linking CXX static library ../lib/libgtest_main.a
[100%] Built target gtest_main
The build should complete relatively quickly.
Step 4: Installing GMock
At this point, you could run sudo cmake --install _build/googletest/ to install it globally to /usr/local, but I wouldn't recommend this. It's much better to keep a frequently updated dependency like Google Test/GMock tied to the project that's using it.
Instead, we will install it to a project-local prefix, like so:
alex:~/test$ cmake --install _build/googletest/ --prefix _local
-- Install configuration: "RelWithDebInfo"
-- Installing: /home/alex/test/_local/include
-- Installing: /home/alex/test/_local/include/gmock
-- Installing: /home/alex/test/_local/include/gmock/gmock-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-function-mocker.h
-- Installing: /home/alex/test/_local/include/gmock/internal
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-pp.h
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-internal-utils.h
-- Installing: /home/alex/test/_local/include/gmock/internal/gmock-port.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-port.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/gmock-generated-actions.h
-- Installing: /home/alex/test/_local/include/gmock/internal/custom/README.md
-- Installing: /home/alex/test/_local/include/gmock/gmock-more-actions.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-more-matchers.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-nice-strict.h
-- Installing: /home/alex/test/_local/include/gmock/gmock.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-cardinalities.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-spec-builders.h
-- Installing: /home/alex/test/_local/include/gmock/gmock-actions.h
-- Installing: /home/alex/test/_local/lib/libgmock.a
-- Installing: /home/alex/test/_local/lib/libgmock_main.a
-- Installing: /home/alex/test/_local/lib/pkgconfig/gmock.pc
-- Installing: /home/alex/test/_local/lib/pkgconfig/gmock_main.pc
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets-relwithdebinfo.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfigVersion.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake
-- Up-to-date: /home/alex/test/_local/include
-- Installing: /home/alex/test/_local/include/gtest
-- Installing: /home/alex/test/_local/include/gtest/gtest-param-test.h
-- Installing: /home/alex/test/_local/include/gtest/internal
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-port-arch.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-string.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-death-test-internal.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-type-util.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-port.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-internal.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-param-util.h
-- Installing: /home/alex/test/_local/include/gtest/internal/gtest-filepath.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/README.md
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest-port.h
-- Installing: /home/alex/test/_local/include/gtest/internal/custom/gtest-printers.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-matchers.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-death-test.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-spi.h
-- Installing: /home/alex/test/_local/include/gtest/gtest.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-test-part.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-typed-test.h
-- Installing: /home/alex/test/_local/include/gtest/gtest_prod.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-assertion-result.h
-- Installing: /home/alex/test/_local/include/gtest/gtest_pred_impl.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-message.h
-- Installing: /home/alex/test/_local/include/gtest/gtest-printers.h
-- Installing: /home/alex/test/_local/lib/libgtest.a
-- Installing: /home/alex/test/_local/lib/libgtest_main.a
-- Installing: /home/alex/test/_local/lib/pkgconfig/gtest.pc
-- Installing: /home/alex/test/_local/lib/pkgconfig/gtest_main.pc
The --prefix flag tells cmake --install into which directory to install the project. Here, we've chosen a directory named _local in our working directory. The name of this folder is arbitrary. I've chosen this name to mirror the /usr/local prefix naming and to play nicely with a common .gitignore strategy of ignoring top-level directories prefixed with and underscore.
Notice in the command output what's getting installed. Headers, the GTest and GMock static libraries, yes, but also pkg-config files and, most importantly, the CMake package files:
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestTargets-relwithdebinfo.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfigVersion.cmake
-- Installing: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake
These are the files that find_package will use (soon) to load GTest into a dependent project. The two standard files are GTestConfig.cmake and GTestConfigVersion.cmake. The first one is the most important, and it's responsible for actually implementing the CMake package. It will ultimately load GTestTargets.cmake and GTestTargets-relwithdebinfo.cmake, which are specific to GTest. Notice also how RelWithDebInfo appears again in the generated file name; that's because config-specific information is stored there. If you want to support multiple configs, you'll need to redo steps 2-4 with a new CMAKE_BUILD_TYPE (e.g. Debug, Release, MinSizeRel)
Step 5: Creating an example project
Let's create a simple example project now that uses GMock. First, we'll create a directory for it:
alex:~/test$ mkdir example
and now we'll go in and create some files:
alex:~/test$ cd example/
alex:~/test/example$ touch CMakeLists.txt main.cpp
Using your favorite text editor, add the following contents to main.cpp:
#include <gmock/gmock.h>
using namespace testing;
struct Example : public Test {};
TEST_F(Example, AlwaysPass) { ASSERT_THAT(0, Eq(0)); }
TEST_F(Example, AlwaysFail) { ASSERT_THAT(0, Eq(1)); }
This is as basic of a "hello world" for GMock as I could come up with. It has one test that always passes and another that always fails (just so we can see the various outputs).
Now we'll write the build script in CMakeLists.txt:
cmake_minimum_required(VERSION 3.23)
project(example)
find_package(GTest REQUIRED)
add_executable(example main.cpp)
target_link_libraries(example PRIVATE GTest::gmock_main)
Once again, this is as simple as can be.
The first two lines are required boilerplate. They must always1 appear as the first two lines of your project, in that order, with nothing before or in between.
The first command, cmake_minimum_required, tells CMake which set of backwards-compatibility policies to enable. It does not put CMake into an emulation mode or anything like that. You must test your build with the version written there because CMake will not stop you from using features that are too new for the declared minimum version.
The second command, project, names your project and kicks off CMake's compiler detection routines.
Next, we tell CMake that this project depends on the GTest package by issuing find_package(GTest REQUIRED). The REQUIRED argument kills the configure step if the package cannot be found. The name GTest is derived from the GTestConfig.cmake file. For any CMake project XYZ, its main package file must be named either XYZConfig.cmake or XYZ-config.cmake.
Finally, we add our test executable example and link it to the target GTest::gmock_main. This target provides a main function in addition to the GMock standard library. If you want to write your own main, then link to GTest::gmock instead.
1. with very few exceptions that are hardly worth mentioning
Step 6: Building and running the example
Now we're finally ready to build and run the example. Let's go back up to our working directory:
alex:~/test/example$ cd ..
alex:~/test$
And now we'll go ahead and configure the build:
alex:~/test$ cmake -S example -B _build/example -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=$PWD/_local
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found GTest: /home/alex/test/_local/lib/cmake/GTest/GTestConfig.cmake (found version "1.11.0")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/example
Note the -DCMAKE_PREFIX_PATH=$PWD/_local flag. That's telling CMake that there are additional libraries and CMake packages in $PWD/_local and so find_package and the other find_* commands should look there. If you didn't pass this flag, you might see an error like this:
CMake Error at /usr/share/cmake-3.23/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find GTest (missing: GTEST_LIBRARY GTEST_INCLUDE_DIR
GTEST_MAIN_LIBRARY)
Call Stack (most recent call first):
/usr/share/cmake-3.23/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
/usr/share/cmake-3.23/Modules/FindGTest.cmake:270 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
CMakeLists.txt:4 (find_package)
-- Configuring incomplete, errors occurred!
See also "/home/alex/test/_build/example/CMakeFiles/CMakeOutput.log".
Now that we're configured, we can build the example:
alex:~/test$ cmake --build _build/example/
[ 50%] Building CXX object CMakeFiles/example.dir/main.cpp.o
[100%] Linking CXX executable example
[100%] Built target example
and then run it:
alex:~/test$ _build/example/example
Running main() from gmock_main.cc
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from Example
[ RUN ] Example.AlwaysPass
[ OK ] Example.AlwaysPass (0 ms)
[ RUN ] Example.AlwaysFail
/home/alex/test/example/main.cpp:8: Failure
Value of: 0
Expected: is equal to 1
Actual: 0 (of type int)
[ FAILED ] Example.AlwaysFail (0 ms)
[----------] 2 tests from Example (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
[ FAILED ] 1 test, listed below:
[ FAILED ] Example.AlwaysFail
1 FAILED TEST
As you can see, our passing test passed, and our failing test failed, as expected!
Step 6: CTest integration (optional)
If we want, we can integrate this with CTest for easier running of multiple GMock binaries down the line. Here's the new CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(example)
enable_testing() # ------------------------ ADDED 1
find_package(GTest REQUIRED)
include(GoogleTest) # ------------------------ ADDED 2
add_executable(example main.cpp)
target_link_libraries(example PRIVATE GTest::gmock_main)
gtest_discover_tests(example) # ------------------------ ADDED 3
Aside from the three lines marked ADDED, nothing has changed. The first added line simply enables CTest support. The second added line imports CMake's native support for Google Test. Finally, the third line tells CTest that the example executable contains GTest tests.
After making these edits, an incremental build will automatically re-run CMake.
alex:~/test$ cmake --build _build/example/
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/example
Consolidate compiler generated dependencies of target example
[ 50%] Linking CXX executable example
[100%] Built target example
And now we can use the CTest runner on our build directory:
alex:~/test$ ctest --test-dir _build/example/
Internal ctest changing into directory: /home/alex/test/_build/example
Test project /home/alex/test/_build/example
Start 1: Example.AlwaysPass
1/2 Test #1: Example.AlwaysPass ............... Passed 0.00 sec
Start 2: Example.AlwaysFail
2/2 Test #2: Example.AlwaysFail ...............***Failed 0.00 sec
50% tests passed, 1 tests failed out of 2
Total Test time (real) = 0.00 sec
The following tests FAILED:
2 - Example.AlwaysFail (Failed)
Errors while running CTest
Output from these tests are in: /home/alex/test/_build/example/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
And once again, we can see that our passing test passed and our failing test failed. Hooray!

add_custom_command not working

I am trying to understand add_custom_command usage, I wrote a minimal make file (CMakeLists.txt)
like shown below
When I run the make file using
$cmake.
$make
I don't see perfecthash.cpp being created and the build breaks
cmake_minimum_required(VERSION 2.8)
# Call add_custom_command() with appropriate arguments for generate output file
# Note, that *gperf* will work in the build tree,
# so for file in the source tree full path should be used.
function(gperf_generate_new input output)
MESSAGE("debugging function")
add_custom_command(
OUTPUT ${output}
COMMAND gperf -L c++ ${input} > ${output}
DEPENDS ${input}
COMMENT "printing ${output}" # Just for nice message during build
)
endfunction()
# Generate *example.hpp* file ...
gperf_generate_new(command_options.new.gperf pefecthash.hpp)
# ... for use it in executable
add_custom_target(my_target
ALL # Force target to be built with default build target.
DEPENDS perfecthash.hpp
)
$cmake .
$make
give the below error
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
debugging function
-- Configuring done
-- Generating done
-- Build files have been written to: /home/srinivas
Scanning dependencies of target my_target
make[2]: *** No rule to make target `perfecthash.hpp', needed by `CMakeFiles/my_target'. Stop.
make[1]: *** [CMakeFiles/my_target.dir/all] Error 2
make: *** [all] Error 2
Just a typo:
gperf_generate_new(command_options.new.gperf pefecthash.hpp)
...
DEPENDS perfecthash.hpp

Calling Unittest++ from cmake created makefile

I recently started learning cmake, and have run into a small issue. I got both my executable and the unit tests to compile from the generated makefile without issue. If I run ./test in the build directory, the tests created in UnitTest++ run and complete as expected, printing the results. Is there any way to get make test to simply run the test executable rather than running it inside ctest framework or should I go about this a different way?
Here is a minimal working example of my code:
src/main/main.c is a simple empty main function
src/test/testMain.cpp:
#include <UnitTest++/UnitTest++.h>
TEST(FailSpect)
{
CHECK(false);
}
int main()
{
UnitTest::RunAllTests();
}
CMakeLists.txt:
cmake_minimum_required( VERSION 2.6 )
project( myProject)
enable_testing()
set( myProjectMain
src/main/main.c
)
set( myProjectSrc
)
set( myProjectTestSrc
src/test/testMain.cpp
)
add_executable( myExecutable ${myProjectMain} ${myProjectSrc} )
add_executable( testSuite ${myProjectTestSrc} ${myProjectSrc} )
target_link_libraries( testSuite UnitTest++ )
add_test( testExe testSuite )
make test output:
Running tests...
Start processing tests
Test project /myProjectDir/build
1/ 1 Testing testExe Passed
100% tests passed, 0 tests failed out of 1
./testSuite output:
/myProjectDir/src/test/testMain.cpp:5: error: Failure in FailSpect: false
FAILURE: 1 out of 1 tests failed (1 failures).
Test time: 0.00 seconds.
I have sorted out how to do this. First remove the lines:
enable_testing()
and
add_test(testExe testSuite)
and replace them by the line:
add_custom_target(test ./testExe
DEPENDS ./testExe)
at the end of the CMakeLists.txt file. Now make (all) builds both the tests and the main program. If everything is built already, then make test will just check that the tests are built and run them, producing:
[100%] Built target testExe
/myProjectDir/src/test/testMain.cpp:5: error: Failure in FailSpect: false
FAILURE: 1 out of 1 tests failed (1 failures).
Test time: 0.00 seconds.
[100%] Built target test
If the tests are out of date (after a make clean for instance), then make test will produce:
[100%] Building CXX object CMakeFiles/testExe.dir/src/test/testMain.cpp.o
Linking CXX executable testExe
[100%] Built target testExe
/myProjectDir/src/test/testMain.cpp:5: error: Failure in FailSpect: false
FAILURE: 1 out of 1 tests failed (1 failures).
Test time: 0.00 seconds.
[100%] Built target test