linking opencv libraries included as an external project via cmake [duplicate] - c++

This question already has answers here:
Configuring an c++ OpenCV project with Cmake
(2 answers)
Closed 8 years ago.
I'm relatively new to cmake and after days of struggling couldn't figure out the following thing:
I have a project that depends on opencv (which is a cmake project on its own) and I want to statically link opencv libraries. What I'm doing is I have a copy of opencv source code in my project and include it into my CMakeLists.txt via
ExternalProject_Add(my_copy_of_opencv_project
CMAKE_ARGS -D BUILD_SHARED_LIBS=NO ...
CMAKE_INSTALL_PREFIX=${MY_OPENCV_INSTALL_DIR}
SOURCE_DIR ${PATH_TO_OPENCV_SRCS}
)
All built nicely and where I have problem is that I cannot reliably determine where the opencv libraries will be. E.g. on linux/mac there are in ${MY_OPENCV_INSTALL_DIR}/lib and are named as libopencv_core.a whereas on 32-bit Windows with VS 2012 installed the libs are in ${MY_OPENCV_INSTALL_DIR}/lib/x86/vc11/staticlib and for the Debug configuration the libs named like opencv_core247d.lib.
So the question is can I somehow obtain a list of all libraries produced by the OpenCV build (and the root lib folder) and link them via something like target_link_libraries(mylib opencv_core ...)?
Maybe I'm doing something wrong or overcomplicated. So what I basically want is to compile my embedded opencv source tree statically and link against its libraries in a "cross-plaformish" way.
Any pointers are highly appreciated! Thanks!

The best solution to use cmake with OpenCV project is:
Compile OpenCV as shared / static libraries with OpenCV's cmake build system.
In your project's CMakeLists.txt
For example (CMakeLists.txt):
cmake_minimum_required(VERSION 2.8.12)
project(test_project)
# OpenCV_DIR could also be read from system environment variable.
if(WIN32)
set(OpenCV_DIR "d:/libs/opencv-2.4.8/build")
else()
set(OpenCV_DIR "/usr/lib/opencv")
endif()
find_package(OpenCV REQUIRED COMPONENTS core imgproc highgui)
include_directories(${OpenCV_INCLUDE_DIRS}) # not needed for opencv>=4.0
add_executable(test main.cpp)
target_link_libraries(test ${OpenCV_LIBS})
It works in cross-platforms.

Related

C++ external libraries issue [duplicate]

This question already has answers here:
CMake link to external library
(6 answers)
Closed 2 years ago.
I have installed an external library named metis which resides at "/usr/local/opt/" in my system and I want to link this library to my existing make project, which seems to be difficult. I have tried a few reference links here on stackoverflow but they don't seem to work.
My CMakeLists.txt looks like this:
project(Multi)
cmake_minimum_required (VERSION 2.6)
find_package(CGAL QUIET COMPONENTS Core )
include( ${CGAL_USE_FILE} )
include_directories (BEFORE "/include")
include_directories (BEFORE "/dt")
find_package(MPI)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
SET(CMAKE_C_COMPILER mpicc)
SET(CMAKE_CXX_COMPILER mpicxx)
SET(MPIEXEC_MAX_NUMPROCS "4" CACHE STRING "Maximum number of processors available to run MPI applications.")
find_package(METIS)
include_directories("/usr/local/opt/metis/include")
add_subdirectory("/usr/local/opt/metis/include/bin")
add_executable(example example.cpp)
I have tried to add the location of the library by using add_subdirectory and include_directories tags but they don't seem to work.
Any help on this will be appreciated.
find_package() searches for the library in a set of predefined directores, and /usr/local/opt is very likely not among those. In this case, since you already know where your library is located, you can tell find_package() where to look for it:
find_package(METIS REQUIRED PATHS /usr/local/opt/metis)
Also, add_subdirectory() works only if the specified directory contains a CMakeLists.txt. You need this only if you want to build the library metis as part of your build process, and if that directory is the root of the metis library, and it used CMake for building too. If you only have the header files and pre-build library files, then you do not need this.

Using CMake to create an executable that can run independently on other machines

I’m using LibTorch and OpenCV for a program in Cpp. The compilation and building is done on Linux using CMake. The program builds and runs as expected.
I want to use the executable that CMake created on another Linux machine.
The problem is that I don’t want to install either LibTorch nor OpenCV on the other machine. I’d rather supply the user with a single executable if possible.
How can CMake create a single independent executable?
If making just a single file is irrelevant, how can CMake copy all needed libraries to a single directory?
The current CMake file:
cmake_minimum_required(VERSION 2.8)
project(prediction)
list(APPEND CMAKE_PREFIX_PATH “libtorch”) # the folder where libtorch in found
set(CMAKE_BUILD_TYPE Release)
find_package( OpenCV REQUIRED )
find_package( Torch REQUIRED )
if(NOT Torch_FOUND)
message(FATAL_ERROR “Pytorch Not Found!”)
endif(NOT Torch_FOUND)
message(STATUS “Pytorch status:”)
message(STATUS " libraries: ${TORCH_LIBRARIES}")
message(STATUS “OpenCV library status:”)
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
file(GLOB SOURCES ".h" ".cpp") # Link all headers and sources in root dir
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable(entrypoint ${SOURCES})
target_link_libraries(entrypoint ${TORCH_LIBRARIES} ${OpenCV_LIBS})
set_property(TARGET entrypoint PROPERTY CXX_STANDARD 14)
####### EDIT
Thanks for the answers.
Following Phesho_T answer bellow, I got the static compilation of LibTorch, but it won't compile with the set() instruction. It throws C10_LIBRARY NOTFOUND.
I think I'll try to use the shared libraries. How can CMake be instructed to copy the releveant shared libraries to the "build" folder, so I can pack everything in a .zip file and send it to the user.
Like another answer said, you need to link the static libs of Torch and OpenCV in your executable.
There are a few pre-requisites for this:
The two libraries need to have static (.a) libraries installed on your system. If they don't, you may have to manually build them. Steps for this differ between different packages.
You need to tell CMake to search for the static libraries ONLY. This is done via the CMAKE_FIND_LIBRARY_SUFFIXES variable. The chances are the default for this is .so;.a, meaning it will find the shared library first.
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
The fact that you're using variables in your target_link_libraries command, instead of imported libraries (the modern CMake way) makes me think that this should be enough - these variables should expand to full paths to the static libraries, which should then be added to your linker command.
Things are a bit more complicated to explain if imported targets were used, but this might be out-of-scope for this question.
Try it out and let us know how you get on.
To create a single executable you need to statically link the dependencies into your executable. Check your libraries to see if they provide static-libs else you need to recompile libtorch or opencv to make static libraries.

C++ How to run programs in Clion when you need to include OpenGL libraries?

Hello I need to work with OpenGL and want to create my project in Clion. But Clion cannot compile and run my projects because of the libraries I need to include. I can create my own makefile and run the program in terminal, but I want to do it in the IDE. How can I make this happen?
First make sure you installed all libraries correctly using the compiler you configured in clion/cmake. Assuminf you have a fresh CMakeLists.txt like
cmake_minimum_required(VERSION 3.3.2)
project(MyGL CPP)
add_executable(demo-run main.cpp)
For linking your libraries you need two things. First tell the compiler where to find the include files and second which libraries to link. You could just hard code you local installation like
target_link_libraries(demo-run path/to/glfw.lib path/to/opengl.lib path/to/jpeg.lib ...)
target_include_directories(demo-run PRIVATE path/to/glfw/include path/to/opengl/include path/to/jpeg/include ...)
however this is not very portable and if you want to work with another compiler or on another machine your project file will fail. Instead you can use the package system of cmake
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
find_package(JPEG REQUIRED)
find_package(GLEW REQUIRED)
find_package (OpenGL REQUIRED)
find_package (GLM REQUIRED)
target_link_libraries(demo-run ${GLFW_LIBRARIES} ${GLEW_LIBRARIES} ${JPEG_LIBRARIES} ${OPENGL_LIBRARIES})
target_include_directories(demo-run PRIVATE ${GLFW_INCLUDE_DIRS} ${GLEW_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLM_INCLUDE_DIR})
The glfw part is a bit tricky and works only on linux i guess see http://www.glfw.org/docs/3.0/build.html.
This code is not tested at all and you may need to specify some enviroment variables so cmake can find the packages or provide additional find scripts like https://github.com/lighttransport/nanogi/blob/master/cmake/FindGLM.cmake.
I would recommend to use the CMake build tool which does the work generating Makefiles for you and is also directly supported by clion. When you open the directory containing a CMakeLists.txt (CMake Project File) with clion, it should be automatically be loaded and compiled (if not just hit build)
A very simple example CMake project would look like this
cmake_minimum_required (VERSION 2.8.9)
project (OpenGl-Stuff)
include_directories(src)
add_executable(your-binary src/your-code.c src/your-code.h)
target_link_libraries(your-binary opengl)
# target_link_libraries will search for libopengl on standard system paths,
# maybe the library is not called libopengl, then you have to adjust the name above
this cmake project will generate the binary for you and link it against opengl

CLion unable to recognize OpenCV libraries (no IntelliSense)

I am trying to solve this thing for quite some time. After a few hours I just decided to post a question because I am out of ideas. I imported a project into CLion with the CMakeLists.txt already inside. I am working on ubuntu and have the newest cmake version (3.5.something, OpenCV is 2.4.x). I use clion just for the IntelliSense, I wont be using it for the compilation anyway (I use terminal for that).
By opening the project I get following warning messages (which I somehow succeeded to reduce to warnings). This happens for every add_library line in OpenCVModules.cmake (I post just one of them):
CMake Warning (dev) at /usr/local/share/OpenCV/OpenCVModules.cmake:53 (add_library):
ADD_LIBRARY called with SHARED option but the target platform does not
support dynamic linking. Building a STATIC library instead. This may lead
to problems.
Has anyone got ideas?
#CMakeLists.txt
# OpenCV:
find_package(OpenCV REQUIRED)
include_directories(${OPENCV_INCLUDE_DIR})
IF(OpenCV_FOUND)
MESSAGE(STATUS "OpenCV_LIBS = ${OpenCV_LIBS}")
ELSE(OpenCV_FOUND)
MESSAGE(STATUS "OpenCV_LIBS not found!")
ENDIF(OpenCV_FOUND)
project(cvtask1a)
file(GLOB SOURCES ${SOURCE_WILDCARDS})
include_directories(${CMAKE_SOURCE_DIR}/cgcvcommon)
add_executable(cvtask1a ${SOURCES})
target_link_libraries(cvtask1a ${OpenCV_LIBS})

How to link shared object in cmake?

How can I link shared object to my own code in cmake ?
I'd like to link OpenCV, I mean libopencv_***.so.3.1 or something like that to my own software package.
In that case, I believe the following lines are the answer of this question.
...
find_package(OpenCV 3.1)
include_directories(${OpenCV_INCLUDE_DIRS})
link_directories(${OpenCV_LIBRARY_DIRS})
...
target_link_libraries(my_node ${OpenCV_LIBRARIES})
But, here's this problem.
I've installed OpenCV 2.4.8 under /usr/include and /usr/lib/x86_64-linux-gnu before, and now I'd like to use OpenCV 3.1.0 installed in local directory "~/Libs/opencv" from code.
So when compiling the codes, OpenCV 2.4.8 takes priority and is used.
In this case, how should I describe CMakeLists.txt ?
Currently I'm writing as the follow.
...
set(CMAKE_PREFIX_PATH ${HOME}/Libs/opencv)
include(${HOME}/Libs/opencv/share/OpenCV/OpenCVConfig.cmake)
find_package(OpenCV 3.1)
set(OpenCV_INCLUDE_DIRS ${HOME}/Libs/opencv/include)
include_directories(${OpenCV_INCLUDE_DIRS)
set(OpenCV_LIBRARY_DIRS ${HOME}/Libs/opencv/lib)
link_directories(${OpenCV_LIBRARY_DIRS})
...
The above CMakeLists.txt kind of helped me.
If executable file is copied to the same directory where libopencv_***.so.3.1 is, the above CMakeLists.txt works.
Otherwise, "make" fails.
But I'd like to make it independent on the directory which contains executable file.
How should I do for this problem ?
Thanks in advance.
See cmake's doc of find_library.
Some predefined paths are used to search for libs. (Platform dependent). It is possible to disable this by options.
Try
find_package(OpenCV 3.1 PATHS ~/Libs/opencv NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH)