installing dll which exist in target directory to install directory using cmake - c++

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.

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.

CMAKE include src and install directories on different OS

I am learning to use CMake and trying to understand where should I place files from different open-source libraries when I download them. I am talking about install location.
On linux include directory is this by convention: /usr/local/include/
What is default location for Windows and Mac OS?
I know that these locations can change, but what is the most common location I should place them?
Can something like this work?
install(FILES include/sort/sort.hpp DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${CMAKE_PROJECT_NAME}/sort)
On windows usually the install prefix is something like C:/Program Files/<Package Name>, the usual install prefix on Unix being /usr/local. Usually this directory contains subdirectories like include containing the headers, lib containing (import) libraries, ect..
Using MSVC for the Windows targets those include directories are not automatically available to the compiler.
This is the reason why you should try to use find_package, if package configuration scripts or find scripts are provided by the installation which has the added benefit of also adding any dependencies with just 2 commands in your cmake project (find_package and target_link_libraries). If the package is installed in the default location, find_package should be able to locate the scripts to load without specifying the install location manually.
For packages not providing this kind of info, writing a find script of your own creating imported targets allows for easy reuse.
Can something like this work?
install(FILES include/sort/sort.hpp DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${CMAKE_PROJECT_NAME}/sort)
In general you should avoid hardcoding absolute destination paths into your install paths. Instead use destination paths relative to the install prefix, since the install prefix may be overwritten, e.g. if the user runs the installation via cmake --install <build dir> --prefix <install directory> or when using cpack to generate a package.
Usually you place public headers of your library in a separate directory, even in your sources (which you seem to be doing) and install the directory with
install(DIRECTORY include/sort TYPE INCLUDE)
Resulting in cmake choosing the exact location based on its defaults for the include files for the target system.
Use a cross-platform package manager instead of manually managing the included directories. It handles the differences between different platforms.
vcpkg is one of the best package managers currently available. You can easily use it via project_options.

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.

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 )