How to set up OpenCV with cmake to enable dynamic and static builds? - c++

I've built and make installed opencv on my mac with SHARED_LIBS.
I want to be able to choose for each project if I built with or without shared libs.
When I compile an additional OpenCV build with -DBUILD_SHARED_LIBS=OFF how can I reference it in my project's CMakeLists and chose the build type I want?
I have the source with shared libs in my ~/opencv and I've already compiled it in ~/opencv/build followed by make install.
When I create another dir like ~/opencv/static_build how would I have to adapt my CMakeLists in order to make a static build app? So far I've used:
find_package( OpenCV REQUIRED )
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(test ${OpenCV_LIBS})
But if I'm not mistaken, these lines all depend variables which have been added to cmake during my inital make install.

It works by configuring a different install location with the cmake flag -D CMAKE_INSTALL_PREFIX for each build and make install will then install them to their respective locations.
In order to distinguish between the specific builds and to allow cmake to find the library if it not in its path, one has to add the following line to the project's CMakeLists.txt:
set(OpenCV_DIR /path/to/build/lib/cmake)
before:
find_package( OpenCV REQUIRED )

Related

reference dynamic libraries using relative path in CMakeLists

I have a project using some dynamic libraries. The generated executable runs well on my local machine. However, if I share it with others, the executable will still try to find dynamic libraries with the absolute path in my local machine, which of course do not exist in other machines. How can I resolve this issue by changing CMakeLists?
My current CMakeLists.txt file:
cmake_minimum_required(VERSION 3.24)
project(MyProject)
link_directories("libs/mac_arm64")
add_executable(MyProject main.cpp)
target_link_libraries(MyProject expat bz2 z geos_c)
When CMake builds libraries and executables, it (by default) embeds absolute RPATH into them. This allows to successfully find all libraries when run those executables on the build machine.
But those libraries and executables, which are created in the build tree, are not intended to be copied to other machine.
Instead, you should install those libraries and executables. Upon installation CMake strips their hardcoded RPATHs, which allows to distribute them.
Add to your CMakeLists.txt:
install(TARGETS MyProject DESTINATION bin/)
and build it with
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../install
make
make install
This will install your project into install directory near the build. After installation you could pack content of install directory and send it to your customers/friends/whoever. CMake even provides cpack tool for easy packaging an installed project.
More about RPATH settings in CMake can be found in their wiki.

Switching build configuration from cmake link to proper version of boost library

I am using Cmake to build my C++ project and I am using conan to maintain my boost libraries.
My conanfile.txt is very simple,
[requires]
boost/1.71.0#conan/stable
[generators]
cmake
When I install boost from conan, I can use following commands,
conan install ..
Or,
conan install .. -s build_type=Debug
Both command install bost libraries in two different folders in my C:/.conan foler.
In CMakeLists.txt I have following lines to find boost
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_DEBUG_LIBS ON)
set(Boost_USE_RELEASE_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost REQUIRED COMPONENTS program_options)
However, When I configure cmake,
cmake .. -DBoost_DEBUG=ON
it doesn't find the debug version of boost library. It always shows that it it pointing to release version. So naturally, the following command works,
cmake --build . --config Release
However, following command failed,
cmake --build . --config Debug
as it is still trying to link ot release version.
How can I reconfigure my cmake and conan setup so that I can easily switch between debug and release version? Any suggestion?
Cheers,
M
If you want to consume the libraries with find_package(Boost) you need to generate the corresponding files. Use the cmake_find_package generator (you need different folders for Debug and Release) or the cmake_find_package_multi one (both Debug and Release can live in the same folder). Just add them to your conanfile.txt:
[requires]
boost/1.71.0
[generators]
cmake_find_package_multi
Now, you can call CMake from the command line, but you need to tell where to find the generated FindBoost.cmake files (or the BoostConfig.cmake if you are using the multi generator):
cmake .. -DCMAKE_MODULE_PATH=<path/to/dir/with/findcmake> [...more arguments]
Take into account that, if you are not using the cmake generator and the call to conan_basic_setup, you need to be sure that the configuration used to build the Boost binaries you are getting from Conan matches the one you are using to build your project (otherwise you might get linker errors).
If you aren't already I'd recommend using https://github.com/conan-io/cmake-conan it makes life easier in some areas.
Unless you want to be able to build your project without conan there is no real need to use find_package with conan. See https://docs.conan.io/en/latest/integrations/build_system/cmake/cmake_generator.html. You can either use:
conan_basic_setup()
target_link_libraries(<target> ${CONAN_LIBS})
Or:
conan_basic_setup(TARGETS)
target_link_libraries(<target> CONAN_PKG::boost)
If you want to use find_package you need to use the cmake_find_package generator and add the following to your conanfile.txt:
[generators]
cmake_find_package
cmake_paths

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.

How do I use cmake to build external libraries as well as my own application?

I am trying to build a cross platform OpenGL application, which means building and including multiple libraries (glfw, glbinding, glm, etc.) Because my application is cross platform, it makes sense to use cmake to generate all the build scripts and not have to muck about with them myself. I am attempting to target Windows and Linux specifically.
A main feature that I need is that the libraries I need are not installed on the host system. Furthermore, they cannot be installed (due to administrative reasons). What I need is to build these libraries and then build my application.
I am mostly working on Windows using Visual Studio 2017, which has cmake support included. Currently, I have attempted to build these libraries myself, however I am having many issues getting find_package to do the right thing.
My directory structure looks like this:
project/
|-src/
|- my sources for my application
|-include/
|- my header files
|-external/
|-glfw-3.2.1/
|-glbinding-2.1.4/
|-glfw-build/
|-glbinidng-build/
So I am attempting to build the external libraries and use them in my application. I am also attempting to follow cmake best practices. My CMakeLists.txt currently looks like this:
cmake_minimum_required(VERSION 3.5)
project(glTestProj)
set(CMAKE_PREFIX_PATH "external/")
find_package(glfw3 3.2 REQUIRED)
find_package(glbinding REQUIRED)
add_executable(glTest src/main.cpp)
target_compile_features(glTest PRIVATE cxx_std_17)
target_compile_options(glTest PRIVATE -Wall -Wextra)
target_link_libraries(
glTest
glfw
glbinding::glbinding
)
The libraries in question (glfw and glbinding) both have instructions on including them via cmake, however I am running into this issue:
CMake Error at CMakeLists.txt:6 (find_package):
By not providing "Findglfw3.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "glfw3", but
CMake did not find one.
Could not find a package configuration file provided by "glfw3" (requested
version 3.2) with any of the following names:
glfw3Config.cmake
glfw3-config.cmake
Add the installation prefix of "glfw3" to CMAKE_PREFIX_PATH or set
"glfw3_DIR" to a directory containing one of the above files. If "glfw3"
provides a separate development package or SDK, be sure it has been
installed.

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