CMake header only dependency - c++

I am having some trouble running a simple test with catch2 using CMake. Since catch is header only I got the impression that it is easily dropped into any project so i thought I'd just include it like a normal header file.
Project structure:
-build
-external
-Catch2
catch2.hpp
CMakeLists.txt
tester.cpp
CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(Test VERSION 1.0.0)
include_directories(external)
enable_testing()
add_executable(tester tester.cpp)
add_test(Tester tester)
tester.cpp:
#define CATCH_CONFIG_MAIN
#include "Catch2\catch.hpp"
TEST_CASE( "1 is 1" ) {
REQUIRE( 1 == 1 );
}
Output:
0% tests passed, 1 tests failed out of 1
Total Test time (real) = 0.03 sec
The following tests FAILED:
1 - Tester (Exit code 0xc0000139
)
Errors while running CTest
Obviously the test should pass, but it does not. Since I am a beginner both in the realm of CMake and catch2 I am having a hard time to pinpoint the issue. What I can say for certain is that catch.hpp is found and there is no linker errors, it just return some error code.
I looked around and found this:
CMake Header from library not found when implementing in catch test case
But it has no answers, and the author does not seem to have the same problem anyway.
This is how I build and run the tests (standing in the build directory):
cmake .. -G "MinGW Makefiles" && mingw32-make && ctest
Any help is appretiated :)

Alright, i removed catch and just played around with mingw and apparently i get the same error just by using std::string. Someone said that it has to do with missing DLL files. I ran dependency walker on the executable and indeed a bunch of DLLs was missing. I didn't now what to do or where to get these so i ditched mingw and tried the cygwin approach.
But using cmake with cygwin i did not find any compatable generators for my development environment (windows).
I then switched to generating a visual studio project instead (which i was avoiding from the start because i did not want to develop in an IDE). But i found out that i can use msbuild to build the executable from the generated visual studio project and it works like a charm, with catch.

Related

why can CMake Build files not be generated correctly

I am trying a simple test to see if CMake is working on my windows system correctly.
I keep getting a error.
Here is the command with the error.
cmake .
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19044.
-- Configuring done
CMake Error at CMakeLists.txt:5 (add_executable):
No SOURCES given to target: main.cpp
CMake Generate step failed. Build files cannot be regenerated correctly.
code for file named main.cpp
#include <iostream>
int main()
{
std::cout << "hello world\n" << "this is a test" <<std::endl;
}
and my CMake file
cmake_minimum_required(VERSION 3.10)
project(test)
add_executable(main.cpp)
I have used CMake in Linux before so not sure why this is failed.
I used Microsoft package manager to install it.
I am using the command line for this, i tried the GUI it also failed.
I have also deleted the CMake files and cache multiple times.
I have not been able to find anything online.
Can't add a comment since my reputation is too low, so I will write an answer instead. In the last line of your CMakeLists.txt file
add_executable(main.cpp)
you are missing the name of the executable
add_executable(name_exe main.cpp)
CMake is telling you that in the error message. CMake tries to create a target main.cpp without source files, since CMake suggests the name of the executable at the first place in the command add_executable().

gtest/gtest.h: No such file or directory #include "gtest/gtest.h"

I have never encountered a problem with testing my code using gtest a few months ago until recently I encountered a problem where all of a sudden the "gtest/gtest.h" header file can no longer be found. I am using putty to hold all my files and directories and the googletest directory is located in the same filepath as the unit test I am compiling to generate the executable. The gtest GitHub was recently updated so I'm not sure if that might have caused it. I have used git submodule add <gtest URL> and the it says that googletest already exists. I have always built my files using cmake3 ., but now I keep getting errors regarding the TEST() functions within the unit test file. I assume this is because the gtest directory cannot be found. I also tried using cmake . to build but that results in a ton of untrackable errors with the gtest.h header file itself. Apparently it seems that building with cmake . can track the gtest.h header file while building with cmake3 . cannot. I still have no clue on how to solve this error.
Here is my CMakeLists.txt file:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
ADD_SUBDIRECTORY(googletest)
SET(CMAKE_CXX_STANDARD 11)
ADD_EXECUTABLE(test
unit_test.cpp
)
TARGET_LINK_LIBRARIES(test gtest)
TARGET_COMPILE_DEFINITIONS(test PRIVATE gtest_disable_pthreads=ON)
EDIT:: I forgot to include that the initial error in the title post occurs after compiling the unit test file separate to using cmake or make. I use the following command g++ -std=c++11 unit_test.cpp in order to compile and the resulting error is gtest/gtest.h: No such file or directory #include "gtest/gtest.h".

Boost.Test crashes with ***Exception: Other on MSVC

I'm trying to build and run tests using Boost.Test in Microsoft Visual Studio 14 2015 (on AppVeyor). My testcase is defined like this, so it should always pass and never throw:
#define BOOST_TEST_MODULE target_boost_test
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(testcase)
{
BOOST_CHECK(true);
}
In the CMake script I set up linkage for the test as such:
find_package(Boost REQUIRED COMPONENTS unit_test_framework)
include_directories(${Boost_INCLUDE_DIRS})
...
add_executable(${UT_TARGET} ${UT_SOURCE})
target_link_libraries(${UT_TARGET} ${LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
The test compiles fine without any warnings but does not run and fails with a pretty unclear ***Exception: Other.
Test project C:/projects/msvc-boost-test/build
Start 1: target_boost_test
1/1 Test #1: target_boost_test ................***Exception: Other 0.08 sec
To reproduce easily I have set up a repo on GitHub with all the necessary files and an automated build job on AppVeyor to show the issue.
[Many thanks to #sehe for getting me on the right track]
In this case the exception was caused by the Boost.Test DLL not being found. I'm too unfamiliar with Windows as to know why the dynamic linker cannot find DLLs automatically. So far I have found two workarounds/fixes for this situation. The first is my preferred way.
1. Add the DLL path to PATH
In case of my AppVeyor YAML config this looked like this:
environment:
BOOST_LIBRARYDIR: "C:\\Libraries\\boost_1_59_0\\lib64-msvc-14.0"
PATH: "%BOOST_LIBRARYDIR%;%PATH%"
2. Copy the DLL to the same directory
Apparently the dynamic linker always searches the working directory (or the directory of the executable? I don't know). Copying the DLL over also worked, again in my AppVeyor YAML config this looked like this:
after_build:
- cmd: copy "%BOOST_LIBRARYDIR%\boost_unit_test_framework-vc140-mt-gd-1_59.dll" .
This is the less generic solution, as it requires explicitly specifying the name of the DLL. Thus, when switching from debug to release mode one also has to adapt the DLL name.
The contents of the repo from the question are summarized in this Gist in a working version.

CMake's ctest: image not found (possible rpath issue)

A CMake project builds and runs tests OK on Linux and Windows, but running the test program fails on macOS.
dyld: Library not loaded: libfoo.dylib
Referenced from: /some/path/test_foo
Reason: image not found
I can verify that libfoo.dylib is in the same dir as the test program test_foo. Running ./test_foo works OK.
CMake calls test_foo via ctest (located in another path). Calling by ctest seems to be what makes it fail, but if I try a command like this (working dir being /some/path) it works:
DYLD_LIBRARY_PATH=`pwd` /another/path/ctest
I assume that running tests with add_test and ctest without setting DYLD_LIBRARY_PATH is possible since I can just run test_foo with success, but I haven't had luck.
Here are the current relevant contents of CMakeLists.txt
set(TEST_LIBS foo)
set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(test_foo tests/testfoo.cpp)
set_target_properties(test_foo PROPERTIES COMPILE_FLAGS "-DSELF_TEST")
target_link_libraries(test_foo ${TEST_LIBS} ${STUFF})
add_dependencies(build_tests test_foo)
add_test(NAME test_foo COMMAND $<TARGET_FILE:test_foo>
WORKING_DIRECTORY ${TEST_DIR})
I've tried setting/unsetting CMAKE_MACOSX_RPATH and MACOSX_RPATH before these lines, as suggested here:
I've tried adding the following snippet after the lines, as suggested here:
IF(APPLE)
SET(CMAKE_INSTALL_NAME_DIR ${TEST_DIR})
SET(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
ENDIF(APPLE)
I've not tried using install, I'm not sure how to configure that for my project or even what it does.
Any known approaches or any obvious mistakes here? Is install worth looking at? I want to be able to run the test from the CMake generated ctest line in the Makefile.
CMake 3.5.2, macOS 10.12.5
Solved as mentioned in comments, thanks to #Tsyvarev
Original comment pointing to the cause of the issue:
I can verify that 'libfoo.dylib' is in the same dir as the test program 'test_foo'. - Really? Your executable is created under binary tree, do you have the library there? If so, why do you use TEST_DIR as working directory or as a RPATH, while it points to source tree (tests subdirectory)?

Do you only need to build the googletest library once?

So firstly I'm new to testing frameworks and relatively new to C++ but am trying to wrap my head around GoogleTest. I'm working on a Windows machine, running "Git for Windows" (MSYS) and MinGW whilst using Sublime Text as my code editor. I am using make as my build tool, although the more I learn about cmake and its cross-platform focus makes me wonder if I should switch to let cmake create makefiles for me. (that's probably a whole other question)
What I'm struggling to understand is what precisly to do with the GoogleTest source package. I realise that I need to build the source into the library and then include that when compiling my tests, but how should I go about doing this? Google includes a cmake build script that generates env/compilier specific makefiles for building. Should I be using this? I feel like if i do so and it blindly works a lot of what is happening under the hood will go over my head. The readme file isn't eliviating my issues, as it implies that i should be building the library and my tests each time i wish the run them. Shouldn't a library be a standalone archive that needs compiling only once? I'm confused and I'm sure its my fault but i'd appreciate it if someone shed some light on this process for me.
You should keep in mind that make will not rebuild gtest if you don't change anything in gtest source code.
Below is my approach to the usage of cmake and gtest for unit testing.
You can add gtest source code by adding it as subdirectory in the root CMakeLists.txt file.
add_subdirectory(${CMAKE_SOURCE_DIR}/thirdparty/gtest ${CMAKE_CURRENT_BINARY_DIR}/gtest)
include_directories(${CMAKE_SOURCE_DIR}/thirdparty/gtest/include ${CMAKE_SOURCE_DIR}/thirdparty/gtest)
My application consist of individual modules containing test folder for unit testing. I have the following boilerplate loop to add each test to the global scope.
file(GLOB TEST_SRC_FILES *.cpp)
foreach(TEST_SRC_PATH ${TEST_SRC_FILES})
#get filename of your test without extension
get_filename_component(TEST_NAME ${TEST_SRC_PATH} NAME_WE)
add_executable(${TEST_NAME} ${TEST_NAME})
#here you link the test executable with gtest
target_link_libraries(${TEST_NAME} gtest gtest_main)
#-----------------------------
# you can link here your test to external libraries
#-----------------------------
add_test(${TEST_NAME} ${TEST_NAME})
#this is a list of all tests
set(PROJECT_TEST_NAMES ${PROJECT_TEST_NAMES} ${TEST_NAME})
endforeach()
#This assigns the list of tests to a property. This make the list available from the root scope.
get_property(UNIT_TESTS GLOBAL PROPERTY UNIT_TESTS)
set(UNIT_TESTS ${UNIT_TESTS} ${PROJECT_TEST_NAMES})
set_property(GLOBAL PROPERTY UNIT_TESTS ${UNIT_TESTS} )
Finally, in the root scope, I add a custom target named check which runs ctest on my unit tests.
#-----------------------------
# Running unit tests
#-----------------------------
get_property(UNIT_TESTS GLOBAL PROPERTY UNIT_TESTS)
if(DEFINED UNIT_TESTS)
add_custom_target(check COMMAND ctest -VV
DEPENDS ${UNIT_TESTS})
endif()
When I run make check, it runs unit tests from all modules, whereas make compiles without tests.