Undefined reference when using Cmake and QtCreator - c++

I'm running the basic OpenCV example with OpenCV3.0.0 dev:
project(ImageDenoise)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(. SRC_LIST)
find_package(OpenCV REQUIRED)
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
MESSAGE(${OpenCV_LIBS})
MESSAGE(${OpenCV_INCLUDE_DIRS})
Source code:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main(int argc, char* argv[] )
{
if ( argc != 2 )
{
printf("usage: DisplayImage.out <Image_Path>\n");
return -1;
}
Mat image;
image = imread( argv[1], IMREAD_COLOR );
if ( !image.data )
{
printf("No image data \n");
return -1;
}
namedWindow("Display Image", WINDOW_AUTOSIZE );
imshow("Display Image", image);
waitKey(0);
return 0;
}
When I import this project into QtCreator, I got the following linking errors when building project:
[100%] Building CXX object CMakeFiles/ImageDenoise.dir/main.cpp.o
Linking CXX executable ImageDenoise
CMakeFiles/ImageDenoise.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x7c): undefined reference to `cv::imread(cv::String const&, int)'
main.cpp:(.text+0xf5): undefined reference to `cv::namedWindow(cv::String const&, int)'
main.cpp:(.text+0x144): undefined reference to `cv::imshow(cv::String const&, cv::_InputArray const&)'
However when I run cmake from command line and using make, then it works perfectly. What is the reason behind this?
dzung#Cronus:~/kSVD/build$ make
Scanning dependencies of target ImageDenoise
[100%] Building CXX object CMakeFiles/ImageDenoise.dir/main.cpp.o
Linking CXX executable ImageDenoise
[100%] Built target ImageDenoise
dzung#Cronus:~/kSVD/build$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake ImageDenoise Makefile
dzung#Cronus:~/kSVD/build$ ./ImageDenoise
usage: DisplayImage.out <Image_Path>

I had exactly the same issue. I think this is some sort of a Qt-creator bug.
I solved this by:
Remove everything except *.cpp and CMakeLists.txt in the project
folder.
Before creating anything with Qt-creator do: cmake . && make
Now open existing project in Qt-creator.
Now you can run cmake/compile/run etc just fine.

Related

CMake & C++ : linker error : undefined reference to function

I am trying to compile a simple C++ program with CMake, but I am getting a linker error :
[2/2] Linking CXX executable bin/MY_PROGRAM
FAILED: bin/MY_PROGRAM
: && g++ -g CMakeFiles/MY_PROGRAM.dir/src/main.cpp.o -o bin/MY_PROGRAM && :
/usr/bin/ld: CMakeFiles/MY_PROGRAM.dir/src/main.cpp.o: in function `main':
/home/user/Code/root/src/main.cpp:27: undefined reference to `str_toupper(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
I have tried looking at some questions with similar issues but couldn't find what I did wrong. There must be a problem with my directory structure and CMake files. I could change the directory structure to make things easier, but I may be missing something important and I'd like to figure out why. Also, I am new to C++ so I might be doing something wrong in the code itself, but my IDE doesn't find any issue.
My directory structure is :
root
|-- CMakeLists.txt
|-- src
|-- main.cpp
|-- utils
|-- CMakeLists.txt
|-- src
|-- strutils.cpp
|-- include
|-- strutils.h
The top-level CMakeLists.txt is :
// general stuff (standard, etc...)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
set(MY_PROGRAM_SRC src/main.cpp)
add_executable(MY_PROGRAM ${MY_PROGRAM_SRC})
include_directories(utils/include)
link_libraries(MY_LIBRARY)
and utils/CMakeLists.txt :
set(MY_LIBRARY_SRC include/strutils.h src/strutils.cpp)
add_library(MY_LIBRARY STATIC ${MY_LIBRARY_SRC})
// This is to include strutils.h in strutils.cpp
// (but is it needed ? I could just #include <string> in strutils.cpp, I guess)
target_include_directories(MY_LIBRARY PUBLIC include)
Finally, the source files :
// strutils.h
#include <string>
void str_toupper(const std::string &in, std::string &out);
// strutils.cpp
#include <algorithm>
#include <strutils.h>
void str_toupper(const std::string &in, std::string &out) {
std::transform(in.begin(), in.end(), out.begin(), [](char c){return std::toupper(c);});
}
// main.cpp
#include <strutils.h>
#include <cstdlib>
#include <cstdio>
#include <string>
int main(int argc, char *argv[]) {
// ...
std::string arg_in;
for (int i = 0; i < argc; i++) {
str_toupper(std::string(argv[i]), arg_in);
}
}
Does anyone have an idea of what's going on ? Thanks !
The first sentence in the manual link_libraries
Link libraries to all targets added later.
You use this directive after the target MY_PROGRAM is added - the target MY_PROGRAM is added prior link_libraries.
Prefer use target_link_libraries(MY_PROGRAM MY_LIBRARY) - other targets can require different dependencies and it's better not use a global set of dependencies for all targets.

CLIon - Undefined reference using SDL_TTF

I'm coding a small game and I'm using SDLs libraries for the graphics (with a CLion IDE). I've already downloaded SDL2, SDL2_image and SDL2_ttf. In the code, I include the three libraries and use TTF to make some text:
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
bool foo() {
if(SDL_Init(SDL_INIT_EVERYTHING)) {
return false;
}
if (TTF_Init() == -1){
cerr << "Error ." << endl;
}
TTF_Font* font = TTF_OpenFont("Sans.ttf", 20);
SDL_Color color = {100, 0, 0};
SDL_Surface* text;
...
Also, I've the following makefile linking this libraries:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
set(CLIENT_FILES core/client.h core/client.cpp)
set(CONFIGURATION_FILES configuration/configurationClient.cpp configuration/configurationClient.h)
file(GLOB_RECURSE GAME_FILES "game/*.cpp" "game/*.h")
file(GLOB_RECURSE MENU_FILES "menu/*.cpp" "menu/*.h")
add_executable(client main.cpp ${CLIENT_FILES} ${MENU_FILES} ${CONFIGURATION_FILES} ${GAME_FILES})
include(FindPkgConfig)
PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
PKG_SEARCH_MODULE(SDL2IMAGE REQUIRED SDL2_image>=2.0.0)
PKG_SEARCH_MODULE(SDL2TTF REQUIRED SDL2_ttf>=2.0.0)
include_directories(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIRS} ${SDL2TTF_INCLUDE_DIRS})
target_link_libraries(client common SDLPrimitives ${SDL2_LIBRARIES} ${SDL2IMAGE_LIBRARIES} ${SDL2TTF_LIBRARIES})
My problem is that the IDE recognize the SDL_ttf library (it doesn't mark in red as an error the TTF functions), but when I try to compile the code, I got many undefined references.
CMakeFiles/client.dir/menu/menuClientVisual.cpp.o: In function `foo()':
source/client/menu/foo.cpp:137: undefined reference to `TTF_Init'
source/client/menu/foo.cpp:141: undefined reference to `TTF_OpenFont'
source/client/menu/foo.cpp:145: undefined reference to `TTF_RenderText_Solid'
source/client/menu/foo.cpp:152: undefined reference to `TTF_RenderText_Solid'
source/client/menu/foo.cpp:157: undefined reference to `TTF_SetFontStyle'
source/client/menu/foo.cpp:160: undefined reference to `TTF_RenderText_Solid'
Any idea?
try including:
find_library(SDL2TTF_LIBRARIES SDL_ttf)

C++/CMake:Undefined reference to imwrite in OpenCV

This is my CMakeLists.txt:
project(proj)
set(OpenCV_DIR "/usr/lib/opencv")
find_package(OpenCV REQUIRED COMPONENTS core imgproc highgui)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(test test.cpp>
target_link_libraries(test ${OpenCV_LIBS})
and this is part of my code:
#include <opencv/cv.h>
#include <opencv/cv.hpp>
#include <opencv/highgui.h>
#include <opencv/highgui.hpp>
using namespace cv;
using namespace std;
int main(int argv, char **argc)
{
//other code
Mat img(height, width, CV_8UC3);
//other code
imwrite("/path", img);
namedWindow( "Display window", 1 );
imshow("Display window", img);
waitKey(0);
return 0;
}
and the error message I get is:
undefined reference to cv::imwrite(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cv::Mat const&, std::vector<int, std::allocator<int> > const&)`
imshow works correctly, so I have no clue why imwrite is giving me an error.
EDIT:
g++ -o test_1 test_1.cpp `pkg-config opencv --cflags --libs`
gives the same error.
In your find_package() command, you are only selecting some specific modules from the OpenCV package, and the one you need (imgcodecs which provides imwrite()) is not in the list.
Try changing it to:
find_package(OpenCV)

CMakelists.txt for compiling HDF5?

I am trying to compile a simple program to read a HDF5 file. The code compiles correctly with h5c++. However I need a cmakelists.txt for the same
readdata.cpp
#include <iostream>
#include "H5Cpp.h"
#ifndef H5_NO_NAMESPACE
using namespace H5;
#endif
const H5std_string FILE_NAME( "testfile.h5" );
int main (void)
{
H5File openFile( FILE_NAME, H5F_ACC_RDONLY );
}
I tried a cmakelists for it but it didnt work. It gave "not defined errors"
readdata.cpp:(.text+0x1d): undefined reference to `H5::FileAccPropList::DEFAULT'
readdata.cpp:(.text+0x24): undefined reference to `H5::FileCreatPropList::DEFAULT'
readdata.cpp:(.text+0x38): undefined reference to `H5check_version'
readdata.cpp:(.text+0x54): undefined reference to `H5::H5File::H5File(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int, H5::FileCreatPropList const&, H5::FileAccPropList const&)'
readdata.cpp:(.text+0x60): undefined reference to `H5::H5File::~H5File()'
CMakelists.txt
cmake_minimum_required(VERSION 3.1.0)
PROJECT (readhdf5)
find_package(HDF5 REQUIRED)
include_directories(${HDF5_INCLUDE_DIRS})
add_executable( readdata readdata.cpp )
target_link_libraries( readdata ${HDF5_CXX_LIBRARIES} ${HDF5_LIBRARIES})
If i put the HDF5_CXX_LIBRARIES and HDF5_LIBRARIES manually the it works.
target_link_libraries( readdata libhdf5.so libhdf5_cpp.so)
So it is not able to read $HDF5_CXX_LIBRARIES and $HDF5_LIBRARIES.How can I fix this?
The code you attempt to compile depends on the HDF5 C++ bindings, which are not searched for by CMake's HDF5 module by default. Explicitly add the binding to the find_package command:
find_package(HDF5 REQUIRED COMPONENTS C CXX)

Cannot get OpenCV to compile because of undefined references?

The code is simple and is essentially straight from this tutorial. I am running Arch Linux and have the OpenCV library stored at /usr/include/. I have also checked to ensure that /usr/include is in my PATH.
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>
using namespace cv;
int main(int argc, char** argv){
Mat image;
Mat grayImage;
if(!argv[1]){
std::cerr << "No image data!" << std::endl;
return -1;
}
image = imread(argv[1], 1);
cvtColor(image, grayImage, CV_BGR2GRAY);
imwrite("Gray_Image.jpg", grayImage);
namedWindow(argv[1], CV_WINDOW_AUTOSIZE);
namedWindow("Gray Image", CV_WINDOW_AUTOSIZE);
imshow(argv[1], image);
imshow("Gray Image", grayImage);
waitKey(0);
return 0;
}
The compiler process successfully finds and include these header files, but I still get undefined reference errors at compile-time. If you look into the header files I included they further include other files in /usr/include/opencv2. I have checked and such header files do exist.
Any ideas?
/tmp/ccudBcqD.o: In function `main':
test.cpp:(.text+0xc0): undefined reference to `cv::imread(std::string const&, int)'
test.cpp:(.text+0x11f): undefined reference to `cv::_OutputArray::_OutputArray(cv::Mat&)'
test.cpp:(.text+0x138): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
test.cpp:(.text+0x158): undefined reference to `cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int)'
test.cpp:(.text+0x180): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
test.cpp:(.text+0x1ca): undefined reference to `cv::imwrite(std::string const&, cv::_InputArray const&, std::vector<int, std::allocator<int> > const&)'
test.cpp:(.text+0x241): undefined reference to `cv::namedWindow(std::string const&, int)'
test.cpp:(.text+0x291): undefined reference to `cv::namedWindow(std::string const&, int)'
test.cpp:(.text+0x2bf): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
test.cpp:(.text+0x2ff): undefined reference to `cv::imshow(std::string const&, cv::_InputArray const&)'
test.cpp:(.text+0x32d): undefined reference to `cv::_InputArray::_InputArray(cv::Mat const&)'
test.cpp:(.text+0x361): undefined reference to `cv::imshow(std::string const&, cv::_InputArray const&)'
test.cpp:(.text+0x383): undefined reference to `cv::waitKey(int)'
/tmp/ccudBcqD.o: In function `cv::Mat::~Mat()':
test.cpp:(.text._ZN2cv3MatD2Ev[_ZN2cv3MatD5Ev]+0x39): undefined reference to `cv::fastFree(void*)'
/tmp/ccudBcqD.o: In function `cv::Mat::operator=(cv::Mat const&)':
test.cpp:(.text._ZN2cv3MataSERKS0_[_ZN2cv3MataSERKS0_]+0x111): undefined reference to `cv::Mat::copySize(cv::Mat const&)'
/tmp/ccudBcqD.o: In function `cv::Mat::release()':
test.cpp:(.text._ZN2cv3Mat7releaseEv[_ZN2cv3Mat7releaseEv]+0x47): undefined reference to `cv::Mat::deallocate()'
collect2: error: ld returned 1 exit status
[Finished in 1.1s with exit code 1]
[shell_cmd: g++ "/home/branden/Desktop/OpenCV/test.cpp" -o "/home/branden/Desktop/OpenCV/test"]
[dir: /home/branden/Desktop/OpenCV]
[path: /usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/vendor_perl:/usr/bin/core_perl]
This is a linker issue. Try:
g++ -o test_1 test_1.cpp `pkg-config opencv --cflags --libs`
This should work to compile the source. However, if you recently compiled OpenCV from source, you will meet linking issue in run-time, the library will not be found.
In most cases, after compiling libraries from source, you need to do finally:
sudo ldconfig
I have tried all solutions. The -lopencv_core -lopencv_imgproc -lopencv_highgui in comments solved my problem. And now my command line looks like this in geany:
g++ -lopencv_core -lopencv_imgproc -lopencv_highgui -o "%e" "%f"
When I build:
g++ -lopencv_core -lopencv_imgproc -lopencv_highgui -o "opencv" "opencv.cpp" (in directory: /home/fedora/Desktop/Implementations)
The headers are:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
follow this tutorial. i ran the install-opencv.sh file in bash. its in the tutorial
read the example from openCV
CMakeLists.txt
cmake_minimum_required(VERSION 3.7)
project(openCVTest)
# cmake needs this line
cmake_minimum_required(VERSION 2.8)
# Define project name
project(opencv_example_project)
# Find OpenCV, you may need to set OpenCV_DIR variable
# to the absolute path to the directory containing OpenCVConfig.cmake file
# via the command line or GUI
find_package(OpenCV REQUIRED)
# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
if(CMAKE_VERSION VERSION_LESS "2.8.11")
# Add OpenCV headers location to your include paths
include_directories(${OpenCV_INCLUDE_DIRS})
endif()
# Declare the executable target built from your sources
add_executable(main main.cpp)
# Link your application with OpenCV libraries
target_link_libraries(main ${OpenCV_LIBS})
main.cpp
/**
* #file LinearBlend.cpp
* #brief Simple linear blender ( dst = alpha*src1 + beta*src2 )
* #author OpenCV team
*/
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>
using namespace cv;
/** Global Variables */
const int alpha_slider_max = 100;
int alpha_slider;
double alpha;
double beta;
/** Matrices to store images */
Mat src1;
Mat src2;
Mat dst;
//![on_trackbar]
/**
* #function on_trackbar
* #brief Callback for trackbar
*/
static void on_trackbar( int, void* )
{
alpha = (double) alpha_slider/alpha_slider_max ;
beta = ( 1.0 - alpha );
addWeighted( src1, alpha, src2, beta, 0.0, dst);
imshow( "Linear Blend", dst );
}
//![on_trackbar]
/**
* #function main
* #brief Main function
*/
int main( void )
{
//![load]
/// Read images ( both have to be of the same size and type )
src1 = imread("../data/LinuxLogo.jpg");
src2 = imread("../data/WindowsLogo.jpg");
//![load]
if( src1.empty() ) { printf("Error loading src1 \n"); return -1; }
if( src2.empty() ) { printf("Error loading src2 \n"); return -1; }
/// Initialize values
alpha_slider = 0;
//![window]
namedWindow("Linear Blend", WINDOW_AUTOSIZE); // Create Window
//![window]
//![create_trackbar]
char TrackbarName[50];
sprintf( TrackbarName, "Alpha x %d", alpha_slider_max );
createTrackbar( TrackbarName, "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar );
//![create_trackbar]
/// Show some stuff
on_trackbar( alpha_slider, 0 );
/// Wait until user press some key
waitKey(0);
return 0;
}
Tested in linux mint 17
if anyone still having this problem. One solution is to rebuild the source OpenCV library using MinGW and not use the binaries given by OpenCV. I did it and it worked like a charm.
I had the same error after compiling the opencv4 in linux.
I had to link the libraries after my .cpp files not before.
g++ $(pkg-config opencv4 --cflags) -std=c++17 foo.cpp $(pkg-config opencv4 --libs) -o foo.o
Note: I also passed -D OPENCV_GENERATE_PKGCONFIG=ON to the cmake command to generate the pkgconfig/opencv4.pc file - the pkg-config command needs it.
Read here for more info about why the order matters: Why does the order in which libraries are linked sometimes cause errors in GCC?
If you do the following, you will be able to use opencv build from OpenCV_INSTALL_PATH.
cmake_minimum_required(VERSION 2.8)
SET(OpenCV_INSTALL_PATH /home/user/opencv/opencv-2.4.13/release/)
SET(OpenCV_INCLUDE_DIRS "${OpenCV_INSTALL_PATH}/include/opencv;${OpenCV_INSTALL_PATH}/include")
SET(OpenCV_LIB_DIR "${OpenCV_INSTALL_PATH}/lib")
LINK_DIRECTORIES(${OpenCV_LIB_DIR})
set(OpenCV_LIBS opencv_core opencv_imgproc opencv_calib3d opencv_video opencv_features2d opencv_ml opencv_highgui opencv_objdetect opencv_contrib opencv_legacy opencv_gpu)
# find_package( OpenCV )
project(edge.cpp)
add_executable(edge edge.cpp)
For me, this type of error:
mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: mingw-w64-x86_64/x86_64-w64-mingw32/lib/libTransform360.a(VideoFrameTransform.cpp.obj):VideoFrameTransform.cpp:(.text+0xc7c):
undefined reference to `cv::Mat::Mat(cv::Mat const&, cv::Rect_<int> const&)'
meant load order, I had to do -lTransform360 -lopencv_dnn345 -lopencv... just like that, that order.
And putting them right next to each other helped too, don't put -lTransform360 all the way at the beginning...or you'll get, for some freaky reason:
undefined reference to `VideoFrameTransform_new'
undefined reference to `VideoFrameTransform_generateMapForPlane'
...
I just changed the position of paramters:
g++ -o test2.out test2.cpp pkg-config opencv4 --cflags --libs
Before I changed the position I used g++ pkg-config opencv4 --cflags --libs test2.cpp -o test2.out.
You can try to run pkg-config opencv --cflags --libs in terminal or run pkg-config opencv4 --cflags --libs to see if you can obtain any information.