Generate a redistributable project with CMake - c++

I'm looking for generating a redistributable project for Windows and Linux using CMake as project configuration system and gcc-4.8 / VS2012, plus extra thirdparty libraries like Qt5. How can i create a package with all the needed dependencies and make the project running on other machines, without installing on those machines the required packages (i.e. Qt5 setup)?
EDIT
Googling heavily i've found Qt5 requires some files and i've found this discussion
Application deployed with QT5 libraries does not start on Windows 7
which explains the required Qt5 dependencies.

Normally, I would use install to list the desired files and CPack for packaging them. That is, suppose I'd like to create a package consisting of the following components:
my_nifty_library.dll
my_nifty_executable.exe
QtCore.dll
QtGUI.dll
(Disclaimer: I'm not Qt expert so the last two files might not exist at all, but you get the idea.)
Given that both my_nifty_library and my_nifty_executable are part of your project, you have control over them, so simply do the following:
install(TARGETS my_nifty_library my_nifty_executable
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
Now, since Qt won't be built as part of your project, I suggest you use the ExternalProject module.
Now, you can use CPack and create, say, a NSIS installer or a tar.gz out of the installed files.

Related

vcpkg manifest install system wide

Just tried Vcpkg Manifest on my cmake project and it is cool, with exceptions however.
My project depends on opencv and it takes a long time for vcpkg to install opencv. So I realized I don't want vcpkg downloawding/installing opencv every time I clone the project in a different folder.
Is it possible to use Vcpkg Manifest but make it install libraries system wide instead of locally to the project?
Or at least not inside the build directory, so will be possible to reuse it?
No, you can't install libraries system-wide in manifest mode.
But binaries are cached so that if you use a library in multiple projects, you don't have to build it from scratch.
https://github.com/microsoft/vcpkg/blob/master/docs/users/binarycaching.md
I abused vcpkg's --x-install-root to achieve similar results as manifest mode.
--x-install-root= (Experimental) Specify the install root directory
Under your project folder, you can install this project's dependencies into a system global directory by using this parameter, so that all projects can share the installed packages system wide. For example, in my case, I installed all packages into $VCPKG_ROOT/installed directory like this:
vcpkg install --x-install-root=$VCPKG_ROOT/installed
You can even use vcpkg list anywhere if you (ab)use it this way.

Correct way to build OpenCV as a third party library along with your project in CMAKE

I have a C++ project, where I use opencv, VTK. I would like to build and install these dependent libraries (opencv,vtk) automatically, which are situated in my thirdparty project folder. I know that opencv and VTK use cmake build system to build their libraries. I even saw the function ExternalProject to add them to my CMakesLists.txt but I had problem of linking the target with opencv libs.
Searching on stack overflow I could not find a proper defined method to do it to implement this for version 3.0, the proposed solutions where Version < 3.0. I would like to know how you will structure your project to build opencv automatically as a thirdparty library, exports its targets and link it with my project target.
I think that the best way is to look for what's being done on larger project on github. I would advise to look at this repo in which they use opencv version 3.2, automatically download it and compile it. I believe that this is the correct way because you just have to change the version to try the compatibility with the newer versions if you want to update your code.
What you are looking for is probably what is called a superbuild. This post might help.
I would suggest to build and install opencv in a subfolder of your repo or your build directory. Then you could set the OpenCV_DIR environment variable to the <opencv_install_prefix>/lib/cmake/opencv4 folder (or at least point to the folder where OpenCVConfig.cmake is)
Then in your CMakeLists.txt you can directly use :
find_package(OpenCV 4 REQUIRED
COMPONENTS core imgproc ximgproc)
target_link_libraries(${PROJECT_NAME} PUBLIC ${OpenCV_LIBS})
The OpenCV_DIR variable tells CMake where to find the OpenCV configuration files needed for find_package function.
For the build and installation step, you could use ExternalProject or FetchContent (I prefer the later) but since OpenCV could be very long to build, you might want to keep the build artifact outside of your project's build folder. Then you can erase your build folder to rebuild your project without rebuilding the whole OpenCV library.
On my side, I'm using a shell script that build OpenCV if needed before building the project that needs it.

Using CMake to find dependencies in an application-specific subfolder

In spite of many years of coding large-scale C++ applications, I do not understand how find_package is supposed to work in a medium-size CMake project, ASSUMING that I want to build the source to dependent packages myself and not simply rely on large systems like opencv, pcl or boost being installed somewhere in a system folder. I can't can't believe that I'm the only person in the world who has shipped multiple OpenCV and other open-source apps, has worked with meta-build systems like NAnt and SCons on major game projects, yet can't understand the most basic things about how CMake works or find a tutorial answering these questions.
In the past, I have essentially hacked around not understaning find_package by setting all the foo_DIR values by hand as CMake complains until I get a working folder.
I would like to run through a simple example which I'm working on right now, and dearly hope someone can explain what I'm doing so wrong.
Firstly, some assumptions:
I want to build everything for both MacOS and Windows, ideally via CMakeGUI. MacOS should build XCodeProjects and Windows should build Visual Studio Solutions.
Where there are dependencies, I want to compile them myself, so I have debug symbols and can modify the dependency source (or at least debug into it.)
No installation of pre-built binaries into system folders, i.e. no use of sudo port install opencv/pcl, etc on mac.
I have multiple projects, and prefer to keep a project and its dependencies in a single folder.
For the purposes of a concrete example, suppose I am building this project, although it's an arbitrary choice to illustrate the process and confusion I suffer:
https://github.com/krips89/opendetection
This lists dependencies, which I have intentionally reordered here so that I can take them in order, as follows:
find_package(OpenCV REQUIRED)
find_package(Eigen REQUIRED)
find_package(Boost 1.40 COMPONENTS program_options REQUIRED )
find_package(PCL REQUIRED)
find_package(VTK REQUIRED)
I would like to have all of these dependencies downloaded and configured in a single path (let's say c:\src on Windows, and ~\src on Mac for simplicity), NOT in a system path. Assume that the actual folder is a sub-folder for this project, and no a sub-folder for all projects. This should also allow for side-by-side installation of multiple projects on the same computer.
Taking this one step at a time:
(1) I clone openCV from https://github.com/opencv/opencv, sync to tag 3.1, configure into the folder opencv_build folder, build and install into opencv_install. I've done this so many times it's pretty straightforward.
(2) As above, but for eigen (although building for eigen doesn't actually do anything s it's a template library. I install to a folder eigen_install
Taking directory shows a series of folders for downloaded dependencies. I have assumed a convention where , and are source repos, and their following _build folders are the "WHere to build the binaries" folders in CMakeGui.
$ ls
boost_1_40_0 opencv opendetection_build
eigen opencv-build opendetection_data
eigen_build opencv_contrib pcl
eigen_install opendetection
All good so far, now let's try to configure opendetection and generate a solution into opendetection_build, and find pendetection's dependencies from within the ~/src folder, that is for the first two dependencies, I hope to find opencv and eigen in the opencv-build and eigen-build folders.
OpenCV immediately fails, as expected, saying:
Could not find a package configuration file provided by "OpenCV" with any of the following names:
OpenCVConfig.cmake
opencv-config.cmake
Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set "OpenCV_DIR" to a directory containing one of the above files. If "OpenCV" provides a separate development package or SDK, be sure it has been installed.
That's good, because I want to explicitly tell CMake to look for dependent packages under my ~/src folder. Question: Is the use of CMAKE_PREFIX_PATH=/users/foo/src the recommended way to accomplish what I want - looking for all sub-packages under a specific path?
Following this, CMake finds OpenCV (good), and sets OpenCV_DIR = /Users/foo/src/opencv-build.
Question: Given that I have made an "install" to opencv-install (using CMAKE_INSTALL_PREFIX and building the Install Target Of OpenCV, shouldn't it find OpenCV in the opencv-install folder not opencv-build?
Moving on to eigen, I have configured and built eigen, and installed it to ~/src/eigen-install, which since it is a subfolder of CMAKE_PREFIX_PATH (~/src) I might expect to be found. But it doesn't seem to be. Can somebody explain to me what I'm not understanding? Particularly given that Eigen in a template library, and that there are at least three folders (eigen, eigen_build and eigen_install) under CMAKE_PREFIX_PATH which I would have thought CMake would find something in, I assume I must be doing something wrong here. I KNOW from past experience, I can set EIGEN_INCLUDE_DIR by hand in CMakeGUI by hand, and continue hacking forth, but that just seems wrong.
I'm more than willing to write up a web page explaining this for future people as dumb as me if one does not already exist, although I can't understand how use of CMake for basic project configuration and generation is apparently so obvious to everyone but so opaque for me. I have actually been using CMake for some years, usually by just manually setting Boost_INCLUDE_Dir, Foo_INCLUDE_PATH etc manually, but clearly this is not the right solution. Generally, after spending a couple of days fighting through the various packages to generate a solution by manually setting INCLUDE PATHS, LIBRARY PATHS and other options, I just deal with the solution and don't touch CMake again. But I would love to understand what I'm missing about find_package for my (surely not uncommon) use case of wanting to control my project dependencies rather than just using sudo port install * and installing random versions of projects to my global system folders.
As error message says, CMAKE_PREFIX_PATH should be set to installation prefix of the package. E.g., if the package has been built using CMake, this is CMAKE_INSTALL_PREFIX variable's value, if the package has been build using Autotools, this is value of --prefix option used for configure it, and so on.
CMake doesn't search every directory under CMAKE_PREFIX_PATH. That is why specifying it as /users/foo/src is useless if you have the package installed at /users/foo/src/eigen-install.
Instead, you may install all 3d-party packages into /users/foo/src/install, and use that path as CMAKE_PREFIX_PATH in your main project.

Clarification of steps while generating of OpenCV libraries using CMake

I have generated the OpenCV libraries using CMake a couple of times using tutorials available online, albeit without completely understanding the process. Here is the process that I follow
Configure CMake to build the OpenCV binaries (eg with QT, TBB, without CUDA, OpenCL etc)
Generate the binaries using CMake
The folder where the binaries are built has a number of .sln files. I open the file OpenCV.sln and run the project ALL_BUILD for both Debug and Release configurations.
There is a new folder created. bin which contains the libraries (both .lib and .dll for the release and debug versions.
(Optional) Sometimes I have also build the project named INSTALL (in the same solution), just out of curiosity. I noticed that it creates another folder, that contains the library files in almost the same pattern as the prebuilt libraries that come with the OpenCV package. Interestingly, my programs in MSVC or Qt work equally well if I link with either the libraries in the install folder or the bin/lib folder.
My questions are
What is the function of the install solution?
How are the libraries generated by the install solution different from the ones found in the bin and lib folders?
Why is the install solution not built when the ALL_BUILD solution is built
What is the function of the install solution?
It packages/collects the build output into a portable set of libraries and headers that you know you can move around in your pc, or to another machine.
How are the libraries generated by the install solution different from the ones found in the bin and lib folders?
They are not. You have probably built first shared and then (by reconfiguring with cmake) static libraries, but than the target install only installs the one you have currently selected (in your cmake-gui?)
Why is the install solution not built when the ALL_BUILD solution is built
install is a special target for cmake. In fact, by default install triggers all and only actually executes when all has successfully terminated, but the viceversa is not true.

Windows package-manager for C++ libraries

I've been working on various open-source projects, which involve the following C++ libraries (& others):
MuPDF
Boost
FreeType
GTKmm
hummus PDF libraries
LibTiff
LibXML2
Wt xpdf
xpdf
Poppler
ZLib
It often takes a long time to configure these libraries, when setting them up on a clean machine. Is there a way to automate the grabbing of all dependencies on a windows machine?
The closest I've found is CMake, which checks to make sure you have the dependencies installed/extracted before generating your project files. But I haven't found anything for Windows which can parse the list of dependencies and then download+install the required versions.
Please recommend a package manager for Windows with up-to-date C++ libraries.
Vcpkg, a Microsoft open source project, helps you get C and C++ libraries on Windows.
Take a look at the Hunter package manager when you already use CMake to setup your project. It automatically downloads and builds your dependencies whith only a few lines of extra cmake code. Hunter is based on cmake export and import targets.
For example if you want to use the GoogleTest library in your cmake based project you would add the following lines to your root CMakeLists.txt
# file root CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
# To get hunter you need to download and include a single cmake file
# see documentation for correct name
include("../gate.cmake")
project(download-gtest)
# set the location of all your hunter-packages
set( HUNTER_ROOT_DIR C:/CppLibraries/HunterLibraries )
# This call automaticall downloads and compiles gtest the first time
# cmake is executed. The library is then cached in the HUNTER_ROOT_DIR
hunter_add_package(GTest)
# Now the GTest library can be found and linked to by your own project
find_package(GTest CONFIG REQUIRED)
add_executable(foo foo.cpp)
target_link_libraries(foo GTest::main)
Not all the libraries you list are available as "hunter-packages" but the project is open source so you can create hunter-packages for your dependencies and commit them to the project. Here is a list of libraries that are already available as hunter packages.
This will not solve all your problems out of the box because you have to create hunter-packages for your dependencies. But the existing framework already does a lot of the work and it is better to use that instead of having a half-assed selfmade solution.
Biicode is a new dependency manager for C++. It also has a few libraries that you listed. Biicode automatically scans your source files for dependencies, downloads and builds them. See here for a very cool example that includes Freeglut.
What I've found:
Closest thing to what I'm looking for:
NuGET
Unfortunately it doesn't have any of the libraries I require in its repository.
So I ended getting most of the libraries from the KDE4windows project and custom building the rest.
Npackd is a package manager for Windows. There is a default repository for C++ libraries and also a third party repository for Visual Studio 2010 64 bit libraries. Boost and zlib are already in the default repository. If you decide to use Npackd, you could file an issue if you need other libraries.
Windows does not have a package manager. Go to the libraries' website and download the Windows builds if they provide any.
There are some alternatives, but not without drawbacks:
Cygwin: provides a nice package manager, but all binaries are built for Cygwin, which means they run slower than their native equivalent, any apps using them will link to the Cygwin DLL, and you're stuck with that license. Also the use of the native Win32 API is sometimes troublesome due to incompatibility with the POSIX emulation offered. Only for GCC.
MinGW-get: is a package manager for the MinGW.org compiler. These are native Win32 binaries, but only for use with MinGW's GCC.
There is no package manager or slightly equivalent thing for anything Visual Studio or MinGW-w64 related.
There is no package management on Windows. On Windows developers typically use full-blown everything-and-the-kitchen-sink development environments and produce monolithic applications themselves, shipped with all dependencies.