gtest and libtorch undefined reference to `testing::internal:: - c++

I am trying to use gtest with libtorch. Currently, I have a basic test program:
#include <gtest/gtest.h>
TEST(WorldMapTests, FirstTest) {
ASSERT_TRUE(true);
}
And then I have a main make where I get torch in the third-party folder as follows:
set(TORCH_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/third-party/libtorch")
set(Torch_DIR "${TORCH_INSTALL_PREFIX}/share/cmake/Torch")
set(pybind11_INCLUDE_DIR "${TORCH_INSTALL_PREFIX}/include/pybind11")
And then my test make looks like:
cmake_minimum_required(VERSION 3.0)
set(CMAKE_CXX_STANDARD 14)
set(This ${PROJECT_NAME}_test)
set(Sources
cpp/WorldMapTests.cpp
)
############################################################## gtest
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
--- SNIP --- (test configure stuff from the github)
endif()
############################################################## gtest
add_executable(${This} ${Sources})
target_link_libraries(${This} PUBLIC
${TORCH_LIBRARIES}
gtest
gtest_main
${PROJECT_NAME}
)
target_include_directories(${This} PUBLIC ${TORCH_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
target_compile_options(${This} PUBLIC ${TORCH_CXX_FLAGS})
add_test(
NAME ${This}
COMMAND ${This}
)
When I compile in release version it is fine. It is also fine if I don't include "${TORCH_LIBRARIES}" in my link directory. However, when I link to torch and test under debug I get the following:
.../test/cpp/WorldMapTests.cpp:5: undefined reference to `testing::internal::GetBoolAssertionFailureMessage(testing::AssertionResult const&, char const*, char const*, char const*)'
I think it's because torch makes use of test and is compiled under a release build. I manually found a gtest.so in the lib folder under torch and deleted it to see if it would solve it but it did not.

After quite a bit of research I was able to come right. Just wanted to post an update for anyone running into the same issue. The issue comes from libtorch being compiled in release mode rather than debug causing conflicts with the gtest library. On windows this is easy to solve as torch provides pre-compiled development libraries. However, on linux you will need to compile your own from source and then link it. I used the following guide to get torch compiled for c++ "https://kezunlin.me/post/54e7a3d8/".

Related

Adding GoogleTest to existing project give linker errors

I have a project that uses CMake to get built. I wanted to test my program using GoogleTest.
So I followed the instructions of the ReadMe file of GoogleTest, and added the marked lines to my CMakeLists.txt (My OS is Ubuntu 20.04.3 LTS) :
cmake_minimum_required(VERSION 3.20)
project(replicatorProject)
set(CMAKE_CXX_STANDARD 14)
### I added the the following lines which I got from the ReadMe of GoogleTest
include(FetchContent)
FetchContent_Declare(
googletest
# Specify the commit you depend on and update it regularly.
URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip
)
# Now simply link against gtest or gtest_main as needed. Eg
add_executable(example test/CrushMapperTest.cpp)
target_link_libraries(example gtest_main)
add_test(NAME example_test COMMAND example)
### until here (above)
find_library(CRUSH_LIBRARY libcrush.so /usr/local/lib/crush/ REQUIRED)
find_package(CppKafka REQUIRED)
add_executable(replicator src/main.cpp src/kafka/KafkaConsumer.cpp src/kafka/KafkaConsumer.h src/crush/CrushMapper.cpp src/crush/CrushMapper.h src/Replicator.cpp src/Replicator.h src/crush/Bucket.cpp src/crush/Bucket.h src/crush/Device.cpp src/crush/Device.h)
target_link_libraries(replicator LINK_PUBLIC ${CRUSH_LIBRARY} CppKafka::cppkafka)
target_include_directories(replicator PRIVATE /usr/local/include)
My Project structure looks like this:
CrushMapperTest.cpp looks like the following:
#include "gtest/gtest.h"
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
TEST(case1, name){
EXPECT_EQ(1,1);
}
However, if I run the test, I get a lot of undefined reference errors from my linker (here are some of them):
/usr/bin/ld: /home/lorik/Uni/Praktikum/Projekt/replicator/test/CrushMapperTest.cpp:13: undefined reference to `testing::internal::AssertHelper::~AssertHelper()'
/usr/bin/ld: /home/lorik/Uni/Praktikum/Projekt/replicator/test/CrushMapperTest.cpp:13: undefined reference to `testing::internal::AssertHelper::~AssertHelper()'
Now I am new to using CMake and I don't get what else I need to add to make the linker find the Google Test functions. I was looking through some other SO posts with similar problems ( like this one) a while ago , but so far no suggested solution helped while trying to dowload google test directly through CMake.
What am I doing wrong? Do I need another CMakeLists.txt for the test directory?
Solution
I had to add FetchContent_MakeAvailable(googletest) after the FetchContent_Declare(...) line

How to properly link OpenCV in a C++ cross-platform library for Android and iOS?

I am developing a C++ library, including OpenCV, which will be used in a cross-platform Xamarin solution through a wrapper and the NuGet packaging system (see this guide). I configured a CMakeLists.txt file but I simply cannot get OpenCV to be correctly linked for both static (iOS) and dynamic (Android) libraries.
I tried to change the OpenCV_DIR variable, install and build OpenCV from sources and manually include the content of the OpenCV_INCLUDE_DIRS variable but nothing worked. I also noticed that the linking works when only using cv::Point. But the linking does not work when using cv::Mat, which I do not understand the reason.
The following is the CMakeLists.txt that I am using :
cmake_minimum_required (VERSION 3.2)
project (MyLib C CXX)
enable_testing()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
MESSAGE(STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS})
# Source and headers files
set(SOURCES File1.cpp File2.cpp)
set(HEADERS File1.h File2.h)
# Library
if(BUILD_SHARED_LIBS)
add_library (MyLib SHARED ${SOURCES} ${HEADERS})
target_compile_definitions(MyLib PUBLIC IS_BUILDING_SHARED)
else()
add_library (MyLib STATIC ${SOURCES} ${HEADERS})
endif()
# Dependencies
set(OpenCV_DIR /usr/local/Cellar/opencv/4.5.0_1/lib/cmake/opencv4)
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV_INCLUDE_DIRS = ${OpenCV_INCLUDE_DIRS}")
message(STATUS "OpenCV_LIBS = ${OpenCV_LIBS}")
message(STATUS "OpenCV_DIR = ${OpenCV_DIR}")
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(MyLib ${OpenCV_LIBS})
The following shows the location of OpenCV's files that are used during the build process. Everything seems alright.
-- OpenCV_INCLUDE_DIRS = /usr/local/Cellar/opencv/4.5.0_1/include/opencv4
-- OpenCV_LIBS = opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio;opencv_alphamat;opencv_aruco;opencv_bgsegm;opencv_bioinspired;opencv_ccalib;opencv_datasets;opencv_dnn_objdetect;opencv_dnn_superres;opencv_dpm;opencv_face;opencv_freetype;opencv_fuzzy;opencv_hfs;opencv_img_hash;opencv_intensity_transform;opencv_line_descriptor;opencv_mcc;opencv_optflow;opencv_phase_unwrapping;opencv_plot;opencv_quality;opencv_rapid;opencv_reg;opencv_rgbd;opencv_saliency;opencv_sfm;opencv_shape;opencv_stereo;opencv_structured_light;opencv_superres;opencv_surface_matching;opencv_text;opencv_tracking;opencv_videostab;opencv_viz;opencv_xfeatures2d;opencv_ximgproc;opencv_xobjdetect;opencv_xphoto
-- OpenCV_DIR = /usr/local/Cellar/opencv/4.5.0_1/lib/cmake/opencv4
Android
The following is the commands that I am using to build the Android dynamic library (.so). I have installed the NDK and am building for each ABI (x86, x86_64, armeabi-v7a, arm64-v8a).
cmake ../.. -DCMAKE_TOOLCHAIN_FILE=/Users/$USER/Library/Android/sdk/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=21 -DANDROID_ABI=$abi_name -DBUILD_SHARED_LIBS=ON
cmake --build . --config Release
I directly get an error when building the library which is the following.
ld: error: /usr/local/Cellar/opencv/4.5.0_1/lib/libopencv_gapi.4.5.0.dylib: unknown file type
ld: error: /usr/local/Cellar/opencv/4.5.0_1/lib/libopencv_stitching.4.5.0.dylib: unknown file type
[...]
ld: error: /usr/local/Cellar/opencv/4.5.0_1/lib/libopencv_rapid.4.5.0.dylib: unknown file type
ld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors)
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
iOS
The following is the commands that I am using to build the iOS static library (.a). I am using leetal's ​cmake toolchain file from this repository.
cmake ../.. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../../ios.toolchain.cmake -DPLATFORM=OS64COMBINED -DBUILD_SHARED_LIBS=OFF
cmake --build . --config Release
The compilation of the static library seems to work because no error message is printed. However, when the library is used in the final Xamarin solution, the linked library cannot be found and the following error is shown.
Native linking failed, undefined symbol: cv::Mat::deallocate(). Please verify that all the necessary frameworks have been referenced and native libraries are properly linked in. (MT5210)
Question
What am I missing in order to properly compile and link OpenCV into my C++ library ?
I am working on macOS Big Sur and uses the following tools versions:
cmake : 3.20.0-rc5
ndk : 23.0.7196353
apple clang : 12.0.0
I hope that the description of my problem is clear enough and I thank you in advance for any help.
We had same problems, including Xamarin's DllNotFoundException with message from last comment, which led me to this topic. What fixed the exception for us in the end was linking statically to OpenCV *.a libs instead of linking to the shared libopencv_java4.so file. So we now have a huge 30MB nativelib.so file for each android ABI in build output, instead of a pair of small nativelib.so and libopencv_java4.so per ABI. CMakeLists looks like this:
set( OpenCV_DIR "~/opencv/build/OpenCV-android-sdk/sdk/native/jni" )
find_package( OpenCV REQUIRED )
target_link_libraries( # Specifies the target library.
nativelib
${OpenCV_LIBS})
Another thing in our project is we use OpenCV optional modules and had to create a custom OpenCV build, which I guess ensures our native library and OpenCV are compiled against same NDK version. I suppose using the prebuilt OpenCV distribution and compiling against a different NDK version could lead to problems too otherwise.

Trying to add libraries with CMake results in error

I am trying to add an external .lib file to my project in Clion which uses CMake. My code is very simple and is simply to test whether the library gets included:
#include <iostream>
#include "header/test.h"
int main() {
test a; // returns error saying undefined reference to 'test::test()'
return 0;
}
When running this code I get the following error:
undefined reference to `test::test()'
This is because I am trying to make a test object however the library for test is not included.
The test.lib file and the test.h file are both in the "header" folder which is in the root of my project folder. The file path to this is F:\Project\header\
My Cmake text file is as follows:
cmake_minimum_required(VERSION 3.14)
project(Project)
set(CMAKE_CXX_STANDARD 14)
add_executable(Project main.cpp)
target_link_libraries(Project
F:\\Project\\header\\test.lib)
In the cmake text file i use the line:
target_link_libraries(Project F:\Project\header\test.lib)
This should include the library file, however it doesn't seem to because I get the "undefined reference to..." error as mentioned above. The Cmake compiler does not give me an error.
You are conceptually correct, however you are not doing it in the CMake fashion. Check out the following links on how to link an external library.
CMake link to external library
cmake doesn't support imported libraries?
https://gitlab.kitware.com/cmake/community/wikis/doc/tutorials/Exporting-and-Importing-Targets
For your case, it would be as follows):
cmake_minimum_required(VERSION 3.14)
project(Project)
set(CMAKE_CXX_STANDARD 14)
# Import the library into the CMake build system
ADD_LIBRARY(test SHARED IMPORTED)
# Specify the location of the library
SET_TARGET_PROPERTIES(TARGET test PROPERTIES IMPORTED_LOCATION “/path/to/lib/test.dll”)
# create the executable
add_executable(Project main.cpp)
# Link your exe to the library
target_link_libraries(Project test)
The CMake documentation is very good. I recommend checking it out when you run into issues.
https://cmake.org/cmake/help/latest/command/add_library.html#imported-libraries

BOOST_ROOT not respected at link stage after cmake config

Apologies for a lengthy title.
I am struggling linking boost with cmake due to existence of boost libraries in /usr/lib64 directory. My boost is compiled in a different place and I am pointing cmake with BOOST_ROOT. Aware of potential problems I am setting a minimal version and Boost_NO_SYSTEM_PATH. Configure stage works fine, but when linking I get an error:
test.cpp:(.text._ZN5boost15program_options25basic_command_line_parserIcEC2EiPKPKc[_ZN5boost15program_options25basic_command_line_parserIcEC5EiPKPKc]+0xa8): undefined reference to `boost::program_options::detail::cmdline::cmdline(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>, std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>, std::allocator<char> > > > const&)'
This is clearly a problem of picking up the wrong library and I can see with make VERBOSE=2 that the g++ line doesn't respect my previously found boost setting in BOOST_ROOT
g++ CMakeFiles/test.dir/test.cpp.o -o test -rdynamic -lboost_program_options-mt
But I would expect something along these lines:
g++ ... -L/path/to/my/own/boost/lib -lboost_program_options-mt
As a "debug" step I print out a message in cmake with Boost_LIBRARY_DIRS and I can see /path/to/my/own/boost/lib. When I "manually" add the -L flag the linking works, which is how I know that the system libs are still interfering. Also, my *LIBRARY_PATH are pointing only at /path/to/my/own/boost/lib.
Perhaps, it's not unlikely that this is a bug of FindBoost module, but I am finding it hard to believe. It seems to me that there's still something major in cmake I do not understand? Why is the -L flag not generated in this instance or a link to a specific file? Please advise.
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
set(Boost_NO_SYSTEM_PATHS ON)
find_package(Boost 1.67.0 REQUIRED COMPONENTS program_options)
include_directories(${Boost_INCLUDE_DIR})
add_executable(test test.cpp)
target_link_libraries(test LINK_PUBLIC ${Boost_PROGRAM_OPTIONS_LIBRARY})
And my program:
#include <iostream>
#include <string>
#include <boost/program_options.hpp>
namespace po=boost::program_options;
int main( int argc, char* argv[])
{
po::options_description options_description;
po::positional_options_description positional_options_description;
po::variables_map variables_map;
options_description.add_options()
("help,h", "print usage message");
po::store(po::command_line_parser(argc, argv).options(
options_description).positional(positional_options_description).run(),
variables_map);
return 0;
}
Other relevant output
I am using message to pull out varables from cmake config step after find_package:
${Boost_INCLUDE_DIR} /path/to/my/own/boost/include
${Boost_LIBRARY_DIRS} /path/to/my/own/boost/lib
${Boost_LIBRARIES} /path/to/my/own/boost/lib/libboost_program_options-mt.so
${Boost_PROGRAM_OPTIONS_LIBRARY} /path/to/my/own/boost/lib/libboost_program_options-mt.so
I don't know which CMake version you are using but did you try using Boost imported target instead of the old-fashioned CMake variable:
i.e.
replace:
target_link_libraries(test LINK_PUBLIC ${Boost_PROGRAM_OPTIONS_LIBRARY})
by
target_link_libraries(test LINK_PUBLIC Boost::program_options)
After calling in on cmake-developer mailing list and finally leaving a post on cmake gitlab issues I realised that the problem was not so much my cmake version, but rather my cmake_minimum_required which I inherited from an older project.
I was setting:
cmake_minium_required(VERSION 2.8)
After updating it to 3.12 that I got the correct behaviour:
/path/to/g++ -rdynamic CMakeFiles/test.dir/test.cpp.o -o test -lboost_program_options-mt
Reading cmake_minimum_required docs I understood that "command implicitly invokes" cmake_policy. I believe the latter wasn't playing well with FindBoost from my 3.12 `cmake.
I am not sure if this post is useful to SO, but I have certainly learnt my cmake lesson here.

How do I make gtest work

So I'm getting undefined reference to testing::UnitTest::Run() along with some others with gtest. I've compiled the libraries (libgtest.a and libgtest_main.a) and placed them in my lib folder for MinGW and got no where.
Here is my CMakeList.txt:
cmake_minimum_required(VERSION 3.2)
project(proj_tests)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
include_directories("E:/Git/proj")
include_directories("D:/Development/Libraries/gtest-1.7.0/include")
find_package(gtest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(proj_tests ${SOURCE_FILES} containers/proj_test.h)
target_link_libraries(proj_tests ${GTEST_LIBRARIES} pthread)
I have done make on the gtest sample and was able to run that without any issues.
I'm using CLion on Windows 7 for the project. How can I make this Google Test framework thing work properly?
When you build gtest, you should have the following three files:
include_fused/gtest/gtest.h
include_fused/gtest/gtest-all.cc
include_fused/gtest/gtest_main.cc
If you are providing your own main you just need the first two. If you want to use the gtest main, you need the third one too. The recommendation is to add these to each unit test project that you are building.
So after a lot of hurt I switched to Linux and tried it there by downloading and compiling the libgtest-dev and using the configuration from Erik Smistad's blog. It worked within the CLion project without issues meaning something weird was happening to my Windows compiled Google Test library.
For windows/MinGW: Here is the solution I reached for Windows..
I got pre-compiled libraries from Richard Pattis's UCI webpage on how to get the google test framework to work on eclipse.
the gtest folder in include was copied to the mingw32\include folder,
the gtest_main.a and libgtest.a files from the make folder files were copied to mingw32\lib folder.
The final working CMake configuration looks like this for me:
cmake_minimum_required(VERSION 3.2)
project(eadlib_tests)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
#path to project to test
include_directories("E:/Git/eadlib")
#Google test framework stuff
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(eadlib_tests ${SOURCE_FILES} containers/eadlib_test.h)
target_link_libraries(eadlib_tests ${GTEST_LIBRARIES} pthread)
like this (here's a snippet from one of my library projects)
find_package(GTest REQUIRED)
target_link_libraries(cpputil_test cpputil ${CMAKE_THREAD_LIBS_INIT} ${GTEST_BOTH_LIBRARIES} ${Boost_LIBRARIES} )
add_test(NAME cpputil_test COMMAND cpputil_test)
Of course in my case the project is called cpputil_test. You'll need to replace it with your own.
Note also the use of CMAKE_THREAD_LIBS_INIT which allows your code to be portable across all host systems. It hides the dependency on pthreads when building for linux (OSX, iOS and Windows for example, do not have this dependency).