OpenCV: undefined reference to `cv::imread when using cmake - c++

I have to use OpenCV on two systems, both Linux. My setup works on the first system, but fails on the second. For both systems I have installed OpenCV in a custom location using:
cd myBuildDir
cmake -DWITH_VTK=OFF -DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=~/Software/OpenCVLibs/opencv-3.1.0/release
~/Software/opencv-3.1.0
make && make install
and similar for debug. The directories are different. One is with my user on my laptop, the other with a different user on a multiuser system.
I then used the example given in the OpenCV documentation to test my setup:
http://docs.opencv.org/2.4/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.html
To build the example using my custom OpenCV location I used
cmake -DCMAKE_BUILD_TYPE=Release -DOpenCV_DIR=~/Software/OpenCVLibs
/opencv-3.1.0/release/share/OpenCV exampleSourceDir
This works on the first system (gcc version 5.3.0) but fails on the second (gcc version 4.6.3). Don't think the gcc version matter here, but stating them for completeness. I think it might be related to that on the first system there is no OpenCV in the system path installed, while in the second system there is. However the build fails with:
/usr/bin/cmake -E cmake_link_script CMakeFiles/DisplayImage.dir/link.txt --verbose=1
/usr/bin/c++ -O3 -DNDEBUG CMakeFiles/DisplayImage.dir/DisplayImage.cpp.o -o DisplayImage -rdynamic /home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_videostab.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_videoio.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_video.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_superres.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_stitching.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_shape.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_photo.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_objdetect.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_ml.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_imgproc.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_imgcodecs.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_highgui.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_flann.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_features2d.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_core.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_calib3d.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_features2d.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_ml.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_highgui.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_videoio.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_imgcodecs.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_flann.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_video.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_imgproc.so.3.1.0
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib/libopencv_core.so.3.1.0 -Wl,-rpath,
/home/me/Software/OpenCVLibs/opencv-3.1.0/release/lib
CMakeFiles/DisplayImage.dir/DisplayImage.cpp.o: In function `main':
DisplayImage.cpp:(.text.startup+0xb8): undefined reference to `cv::imread(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)'
DisplayImage.cpp:(.text.startup+0x1d7): undefined reference to `cv::namedWindow(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)'
DisplayImage.cpp:(.text.startup+0x1f4): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
DisplayImage.cpp:(.text.startup+0x223): undefined reference to `cv::imshow(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cv::_InputArray const&)'
collect2: ld returned 1 exit status
From this call, I figure that the libraries in the custom location should have been used. Why does it fail then? I ran opencv_test_imgcodecs on both machines, which works fine.
Any ideas how to fix my problem? Is it because of the other OpenCV installation on the second system?
Thank in advance for any help!

I could solve my problem by changing the CMakeList.txt. I know have
find_package( OpenCV HINTS "~/Software/OpenCVLibs/opencv-3.1.0/release/share/OpenCV/" )
in it. Before it was just
find_package( OpenCV Required )
Now I also do not need to specify OpenCV_DIR any longer and can build with:
cmake -DCMAKE_BUILD_TYPE=Release exampleSourceDir
make

Most of the time though I think this a more general CMake mistake.
I just got the same error:
undefined reference to 'cv::imshow(cv::String const&, cv::_InputArray const&)'
And the fix that worked for me was changing my CMakeLists.txt from:
add_executable(rekf
src/rekf/rekf_node.cpp
src/rekf/ros_rekf.cpp
src/rekf/rekf.cpp)
add_dependencies(rekf ${catkin_EXPORTED_TARGETS})
target_link_libraries(rekf ${catkin_LIBRARIES})
To:
add_executable(rekf
src/rekf/rekf_node.cpp
src/rekf/ros_rekf.cpp
src/rekf/rekf.cpp)
add_dependencies(rekf ${catkin_EXPORTED_TARGETS})
target_link_libraries(rekf ${OpenCV_LIBS} ${catkin_LIBRARIES})

Related

Compiling boost flags with explicit location on boost binaries

I am compiling a project that needs boost::filesystem. I have included the following flags in my compilation step:
g++ -Wall -ggdb -Werror -std=c++11 -lboost_system
-lboost_filesystem -I /custom/path/to/boost_1_67_0
-o build/main build/cp.o build/walk.o build/diff.o build/main.o
and I get an error:
build/cp.o: In function `boost::filesystem::relative(boost::filesystem::path const&, boost::filesystem::path const&)':
/custom/path/boost_1_67_0/boost/filesystem/operations.hpp:690: undefined reference to `boost::filesystem::detail::relative(boost::filesystem::path const&, boost::filesystem::path const&, boost::system::error_code*)'
build/cp.o: In function `boost::filesystem::weakly_canonical(boost::filesystem::path const&)':
/custom/path/boost_1_67_0/boost/filesystem/operations.hpp:728: undefined reference to `boost::filesystem::detail::weakly_canonical(boost::filesystem::path const&, boost::system::error_code*)'
collect2: error: ld returned 1 exit status
make: *** [build] Error 1
I suspect that this is due to the fact that I have various other boost::filesystem binaries, some of which don't have relative and weakly_canonical in their versions. I don't really know where to supply the argument to specify the location of the binaries either. I suspect it's something to do with the flags lboost_system and lboost_filesystem where I can supply the location.
I am currently in process of building the .so's but I can see that the filesystem .so is already successfully built at /custom/path/boost_1_67_0/bin.v2/libs/filesystem/build/gcc-4.8.5/release/threading-multi/libboost_filesystem.so.1.67.0, so I want to point to that in the mean time. Building the library is taking a really long time.
So is it the -lboost_{libname} flags that I can extend upon? Is it the -I flag?
EDIT: Now that the binary location specified by --prefix during build is done, I tried the same thing, even with -L and it didn't work. Refer to my answer below for the LD_LIBRARY_PATH solution.
I have a solution, but it's not pretty:
I suspect it's because the other boost library binary is specified in $LD_LIBRARY_PATH, I could not load my own library in precedence using -L /custom/path/....
Thus, I did:
export LD_LIBRARY_PATH=/custom/path/...:$LD_LIBRARY_PATH
And it works.
This is by no means a good answer because it doesn't really make this build process portable to users without the LD_LIBRARY_PATH flag. Better answers will be approved instead of this.
Looks like you still need to provide the -L GCC option.
Use -L to tell the compiler where to look for the boost libraries.
Also, make sure you used bjam/b2 to install boost in a proper place. That bin.v2 directory is used to build boost libraries and not install.

Boost:;program_options 1.49 - can't link with -lboost_program_options

I'm attempting my first use of Boost anything so I thought I'd start with program_options. I'm developing on a Raspberry Pi running Debian Wheezy. I started by "apt-get install libboost1.49-all" and everything seemed to install correctly. I can see .a and .so libraries in /usr/lib.
/usr/lib/libboost_program_options.a
/usr/lib/libboost_program_options-mt.a -> libboost_program_options.a
/usr/lib/libboost_program_options-mt.so -> libboost_program_options.so.1.49.0
/usr/lib/libboost_program_options.so -> libboost_program_options.so.1.49.0
/usr/lib/libboost_program_options.so.1.49.0
I can compile some example source I found here by using
g++ boost_program_options.cpp -c
but I cannot get anything to link. I've tried explicitly specifying the library path using no -l and got nothing but several pages of undefined reference errors. I tried another example code and got a compile problem that indicated to me that I wasn't using "g++ -std=c++0x" but that's not the problem either. I'm stuck. I've also tried
g++ -std=c++0x boostme.cpp -o boostme -L/usr/lib -lboost_program_options
I'm just banging my head against the wall at this point. Among the stackoverflow posts I've seen so far, I'm doing everything correctly. My head hurts. ;-)
Just some sample error messages below. Still poking around.
/tmp/ccTbmurt.o: In function `boost::program_options::error_with_option_name::~error_with_option_name()':
boostme.cpp:(.text._ZN5boost15program_options22error_with_option_nameD2Ev[_ZN5boost15program_options22error_with_option_nameD5Ev]+0x118): undefined reference to `vtable for boost::program_options::error_with_option_name'
/tmp/ccTbmurt.o: In function `boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)':
boostme.cpp:(.text._ZN5boost15program_options16validation_errorC2ENS1_6kind_tERKSsS4_i[_ZN5boost15program_options16validation_errorC5ENS1_6kind_tERKSsS4_i]+0x30): undefined reference to `boost::program_options::validation_error::get_template(boost::program_options::validation_error::kind_t)'
Because the signature of that destructor really should be
~error_with_option_name() throw() {}
I'm going to look into my crystal ball and say that - maybe - somewhere you might have #define throw() or similar hidden in your codebase.
That, or you might have conflicting version of the header files in your include paths, which do not correspond to the version of the libraries found at link time

Can't get googletest running with ubuntu (linker errors)

I've built googletest using make under linux, the resulting files are libgtest.a libgtest_main.a.
I referenced the include files from my application and added the following lib dependencies (in the given order):
-lgtest
-lpthread
However I get the following two linker errors when I try to compile:
more undefined references to `testing::internal::EqFailure(char const*, char const*, testing::internal::String const&, testing::internal::String const&, bool)
undefined reference to `testing::internal::String::ShowCStringQuoted(char const*)
From what I've seen within the googletest source, the EqFailure function is directly implemented within gtest.cc. I don't understand why I should get a linker error here, the other definitions from googletest could obviously also be found (if I remove -lgtest, I get alot of more linker errors).
What am I missing? Thank you in advance.
Make sure you do not accidentally mix your own gtest and the one shipped with ubuntu.
I use cmake to build and got the same errors due to cmake opting for /usr/include over my own custom built version (which is what I linked with).

Compiling Box2D HelloWorld on Ubuntu 12.04

I am planning to use Box2D in my C++ project. I have downloaded the latest version (v2.3.0.7 when asking this question) of Box2D and built it successfully. I can run the Testbed without any errors.
Now, I am trying to build the HelloWorld.cpp example, which resides in HelloWorld folder in Box2D source files but I can't compile this example.
Below is my command for compiling:
g++ -g -Wall -L/home/viki/Desktop/collision_test/Box2D_v2.3.0/Box2D/Build/Box2D -lBox2D -I/home/viki/Desktop/collision_test/Box2D_v2.3.0/Box2D HelloWorld.cpp -o Hello
And this is the output I get:
/tmp/cc2U314E.o: In function `main':
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:37: undefined reference to `b2World::b2World(b2Vec2 const&)'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:46: undefined reference to `b2World::CreateBody(b2BodyDef const*)'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:52: undefined reference to `b2PolygonShape::SetAsBox(float, float)'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:55: undefined reference to `b2Body::CreateFixture(b2Shape const*, float)'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:61: undefined reference to `b2World::CreateBody(b2BodyDef const*)'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:65: undefined reference to `b2PolygonShape::SetAsBox(float, float)'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:78: undefined reference to `b2Body::CreateFixture(b2FixtureDef const*)'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:92: undefined reference to `b2World::Step(float, int, int)'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:104: undefined reference to `b2World::~b2World()'
/home/viki/Desktop/collision_test/test/HelloWorld.cpp:104: undefined reference to `b2World::~b2World()'
/tmp/cc2U314E.o: In function `b2PolygonShape':
/home/viki/Desktop/collision_test/Box2D_v2.3.0/Box2D/Box2D/Collision/Shapes/b2PolygonShape.h:87: undefined reference to `vtable for b2PolygonShape'
/tmp/cc2U314E.o: In function `~b2PolygonShape':
/home/viki/Desktop/collision_test/Box2D_v2.3.0/Box2D/Box2D/Collision/Shapes/b2PolygonShape.h:28: undefined reference to `vtable for b2PolygonShape'
collect2: ld returned 1 exit status
I'm using
-L flag for searching for libBox2D.a
-l flag for linking Box2D
-I flag for pointing to the Box2D headers directory
What am I missing? Is there any specific library or command argument I am supposed to add?
Put the -lBox2D behind the HelloWorld.cpp
If you have built your project properly the HelloWorld example will be automatically built for you. There's a CMakeLists.txt file in the example folder just run cmake CMakeLists.txt in the folder and then run make. Prior to this you must have built and installed Box2D library. Here is what I did:
I entered the Build directory within the Box2D and typed the following command:
cmake -DBOX2D_INSTALL=ON -DBOX2D_BUILD_SHARED=ON -DCMAKE_INSTALL_PREFIX=/opt/Box2D ..
Then I went one level up to Box2D directory and ran make then sudo make install.
Then I entered the HelloWorld directory and it was automatically built. I didn't have to build it manually. Also this is the output from make that showed the example was built:
Linking CXX static library libBox2D.a
[ 42%] Built target Box2D
[ 43%] Building CXX object HelloWorld/CMakeFiles/HelloWorld.dir/HelloWorld.cpp.o

Armadillo installation

Hi I installed Armadillo3.0.1 in my own working directory /home/me/package/armadillo3.0.1/ as the README.txt said. But when I try an example:
g++ -I /home/me/package/armadillo3.0.1/usr/include/ example.cpp -o example -O1
It always shows the error:
/tmp/ccZAE9pj.o: In function void arma::gemm<false, false, false, false>::apply_blas_type<double>(arma::Mat<double>&, arma::Mat<double> const&, arma::Mat<double> const&, double, double)':
example.cpp:(.text._ZN4arma4gemmILb0ELb0ELb0ELb0EE15apply_blas_typeIdEEvRNS_3MatIT_EERKS5_S8_S4_S4_[void arma::gemm<false, false, false, false>::apply_blas_type<double>(arma::Mat<double>&, arma::Mat<double> const&, arma::Mat<double> const&, double, double)]+0x75e): undefined reference towrapper_dgemm_'
/tmp/ccZAE9pj.o: In function void arma::glue_times_redirect2_helper<true>::apply<arma::Mat<double>, arma::Mat<double> >(arma::Mat<arma::Mat<double>::elem_type>&, arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times> const&)':
example.cpp:(.text._ZN4arma27glue_times_redirect2_helperILb1EE5applyINS_3MatIdEES4_EEvRNS3_INT_9elem_typeEEERKNS_4GlueIS5_T0_NS_10glue_timesEEE[void arma::glue_times_redirect2_helper<true>::apply<arma::Mat<double>, arma::Mat<double> >(arma::Mat<arma::Mat<double>::elem_type>&, arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times> const&)]+0xe69): undefined reference towrapper_dgemv_'
example.cpp:(.text._ZN4arma27glue_times_redirect2_helperILb1EE5applyINS_3MatIdEES4_EEvRNS3_INT_9elem_typeEEERKNS_4GlueIS5_T0_NS_10glue_timesEEE[void arma::glue_times_redirect2_helper::apply, arma::Mat >(arma::Mat::elem_type>&, arma::Glue, arma::Mat, arma::glue_times> const&)]+0x1175): undefined reference to `wrapper_dgemv_'
collect2: ld returned 1 exit status
However if I add the -larmadillo option like:
g++ example.cpp -o example -O1 -larmadillo
It works by calling the old version. If I want to use new features in 3.0.1 like Mat.t(), it will also show the error:
example.cpp: In function ‘int main(int, char**)’:
example.cpp:20: error: ‘struct arma::mat’ has no member named ‘t’
This shows that by adding -larmadillo, it calls the old version armadillo from /usr/include/armadillo_bits/.
Any idea of that? Thanks.
In the first command, you are not linking with libarmadillo. Have you considered using the -L gcc option to add a link directory ? For example:
g++ -I/home/me/package/armadillo3.0.1/usr/include/
-L/home/me/package/armadillo3.0.1/usr/lib example.cpp -o example -O1 -larmadillo
I've also run into this issue. I've fixed it by uninstalling any previous versions of Armadillo, as they can interfere with the new version.
Uninstallation can be done via your package manager. You can also manually remove the old version via the following commands (in a terminal window):
rm /usr/include/armadillo
rm -rf /usr/include/armadillo_bits
You'll need to run the above commands as a super-user (root). On Ubuntu it should be sufficient to preface them with "sudo".
You may also need to remove the old library files, which could be in /usr/lib/ or /usr/lib64/, or something along these lines.
Once the old version has been removed, you can re-install the new Armadillo, via the cmake based installation.
I removed the old one and reinstalled the new one in default directory. It worked!
So it seems when I installed the old version with:
make install DESTDIR=my/own/dir/
it was install incorrectly.
Hence for newbies like me, install by default makes more sense.