reference dynamic libraries using relative path in CMakeLists - c++

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.

Related

How to install a Library for C++ like Eigen and sharkML at vs code?

I am trying to install libraries like eigen, sharkMl, xtensor, and others in VSCode for C++.
Please if anyone can help me to know the right way to do that.
All of these libraries use CMake for their build system so what I do is use CMake as my build system. My favorite way to do this is to use the libraries build systems to install them and then inlcude them with cmakes find_package function. This you can do by cloning the git repository for the library then build it and install it with cmake. On linux you do this by:
git clone https://gitlab.com/libeigen/eigen.git
cd eigen
mkdir build
cd build
cmake ..
sudo make install
VSCode has good integration for cmake so if you have the C/C++ Extension pack you will be able to build with cmake. In your project folder make a CMakeLists.txt file and add the packages you want:
add_executable(main main.cpp)
find_package(Eigen3 3.4 NO_MODULE)
target_link_libraries(main Eigen3::Eigen)
(This example assumes the main cpp file is main.cpp and creates an executable called main) Then when you press ctr+shift+p and perform CMake: Configure you can select your compiler and build the executable.

installing dll which exist in target directory to install directory using cmake

I have a target in CMake which is a shared library (.dll) and it depends on some other dlls which is added to system using find_packages.
the came is used mainly in Windows with VS (1029)
other dlls are copied to target directory (for example release or debug) during a build on VC.
Now I want to add an install target.
I have this code:
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/win-Install)
install(TARGETS myDLL RUNTIME DESTINATION bin CONFIGURATIONS Release)
This copy my dll to install directory but not the dependent libraries.
How can make sure that the install also copies all dependent libraries to install directory?
I tried to use a FILE(GLOB_RECURSE All_DLLS "${CMAKE_RUNTIME_OUTPUT_DIRECTORY }/*.dll")
but it did not work.
How can make sure that install copies all dependent libraries (*.dlls) to install directory?
Apparently,
FILE(GLOB_RECURSE All_DLLS "${CMAKE_RUNTIME_OUTPUT_DIRECTORY }/*.dll")
is run during cmake execution, but I need a command that works and detect *.dlls in build directory when install target in VS is runs.

How to use CPack to pack several cmake build results?

As I have to build both static and shared library for x86 and arm platform. So with the same CMakeLists.txt, I have to run it four times with different configuration. I want to use CPack to pack those libraries to one tar file. However, it seems that only the last cmake build results will be included in the tar file.
Is there any idea for this problem?
Here is part of my CMakeLists.txt:
install(FILES api_cpp.h api_c.h DESTINATION api_lib/include)
install(TARGETS lib
ARCHIVE DESTINATION api_lib/${lib_folder}
LIBRARY DESTINATION api_lib/${lib_folder})
INCLUDE(CPack)
SET(CPACK_GENERATOR "TGZ")
Obviously, you use a single-configuration generator -- meaning that you can't have more than one particular build configuration in the same build directory. Actually the problem exists even for the multi-configuration generators as well (at least for CMake < 3.16).
To make a package one ought to run CMake, which generates build files, then build a project, and finally can make a package (e.g., w/ make package). The last action runs CPack, which performs make install DESTDIR=<some-temporary-dir>, and then cpack just compress the directory into an archive. So, having a build directory with the only configuration it's impossible to have an archive with few of them.
To make your need possible you ought to run CMake 4 times doing install into the same location and then pack that directory into a package. It can be done with CMake+CPack, but IMHO easier to do w/ a trivial shell script :)

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

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 )

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.