How do you deploy/package a CMake project with Visual Studio? - c++

I'm currently working on a small CMake project with visual studio and I'm wanting to distribute my current build but I have no clue how to, when testing the app on another system it would error saying what I'm guessing were runtime dll's that were missing. I can't find anything online about it, and the official CMake tutorial didn't work for me. Does anyone know a way to do this?

Just like you have been told in the comments, the proper way to distribute an application on Windows is to use VC redistributable package. But if one wants to create an independent "bundle" CMake can help with it. It has a module which helps to bring the necessary dlls wherever needed. You need to understand and plan how your resulting bundle will look like and adapt the paths accordingly. I will just show you how to bring the dlls to the current binary directory with the help of the said module:
set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}")
include(InstallRequiredSystemLibraries)
These 2 lines will make sure that you have an install target by building which the dlls required will be copied (installed) to the ${CMAKE_INSTALL_PREFIX} path. That would be your start from which you can proceed further with any customization you need to make.

Related

How to setup complex project with Visual Studio 2022?

I have project that I was developing for years in Linux.
It depends on MKL, libxml++, GSL and armadillo library.
Its installation structure is done in CMake and project is formed by building a shared library and couple of executables that link to it. There are about 20 classes in the library.
Project structure is:
--src
--executable1.cpp
--executable2.cpp
--mysharedlib
--class1.h
--class1.cpp
--...
My question is how to install and run this code in Visual Studio in Windows.
I never used VS before and am still going through tutorials. I managed to run my code by installing Ubuntu on WSL, but I I'd like a VS solution as it'd be handy to pass to user not familiar with Linux.
I tried opening the project directory with VS, hoping CMAKE would do all the magic, but expectedly it cannot locate the dependent libraries, so I am now going through web looking how to integrate each to VS. I managed to find armadillo and mkl guide, but I am lost on how to link these libraries to my project codes and whether I should abandon its current cmake setup and start building the code structure differently in VS.
Any links to useful VS tutorials and advices how to this are greatly appreciated.
VS does have support for CMake, although I have no idea how well VS integrates CMake. If you're not set on using VS, you might want to look into an IDE that uses CMake at it's core, Clion comes to mind. That being said, when coming from Linux you don't have the (initial) luxury of simply installing all the dependencies via a preinstalled package manager.
In order for CMake to find your dependencies (assuming you've configured them by using find_package()) you should add the sources of your dependencies to your project in a thirdparty folder (name is up to you) and add these dependencies using add_subdirectory() instead. This will compile all your dependencies from source, so you might have to configure these dependencies yourself (look into the documentation of your dependencies on how to build them from source).
Another way is to use a package manager that is available on Windows to download, compile and provide your dependencies to your build tools. vcpkg comes to mind, claiming to integrate well with CMake by providing a toolchain file that you can pass to CMake when building your project. You might even be able to configure VS to automatically pass this toolchain to CMake whenever it's invoked.
From personal experience, there is no need to convert an existing project to the VS project structure. There's plenty of available solutions and tools available on Windows to work with CMake projects. Going with the cross-platform approach should be preferred unless you're only targeting Windows, using VS to it's fullest then might give you some additional quality of life.
If you have more specific questions regarding this, I suggest that you update your original post or to create separate, specific questions regarding the processes involved in setting up an existing CMake project on Windows.

How could one install dependencies using CMake?

I have been trying to figure out the best way to handle dependencies in my C++ projects. For smaller libraries, like fmt, it is not too difficult to just add the following:
include(FetchContent)
FetchContent_Declare(FormatLib
GIT_REPOSITORY "https://github.com/..."
GIT_TAG "..."
)
FetchContent_MakeAvailable(FormatLib)
However, it is undesirable to have the project downloaded into the build directory every time with larger dependencies, for example, the Vulkan Loader which depends on other things.
What I would like would be the ability to do something like, before or at configure time of my main project, to download, configure, build and install a library system wide. I do not know if this is a feature possible with CMake but any help would be appreciated.
I also know that the ExternalProject module has existed in CMake for a long time now, and would be perfect for what I want, I think... if I were able to use it to install a library before I would then call find_package inside the same CMakeLists.txt
I purchased and read a considerable amount of the "Professional CMake 8th Edition" but still don't know if such a feature or technique exists in CMake.
I should clarify that I don't need the Vulkan loader, I was just giving an example. In the case of the Vulkan loader, if you have the SDK already installed, you can use the built in find_package command. My question is whether there's a way to populate such a library before hand. There are specific libraries that I haven't been able to find using package managers such as Conan and it seems like the best possible solution would be to actually just pull the source straight from an online git repo, build and install.
So in conclusion, what I would like to be able to do is the following: Write a CMakeLists.txt that details all the dependencies of a project, possibly searches for the dependencies using find_package, if they're not found, it installs them system wide so that from there on out, every build of said project or similar project on the system has access to the package installed.
Any advice, insight or suggestions on how I can mitigate this problem or even how my desired development strategy is flawed would be appreciated.

How to improve my script and copy program resources on build?

So I got into a problem where I needed to use linux for a while instead of windows, and figured linux doesn't have Visual Studio. I then also realized that I made my project Visual Studio only, which I don't want.
So I looked up some CMake tutorials and try'ed creating some examples that could be loaded in both Visual Studio and CodeBlocks. When I got that to work, I went and code a CMake script for my actual program by piecing together what I learned and what I found in tutorials.
See here:
cmake_minimum_required(VERSION 2.8.9)
add_subdirectory(libraries/glfw)
project (OpenGLEngine3D)
include_directories(libraries/glfw/include)
include_directories(libraries/glm)
include_directories(libraries/glad/include)
include_directories(libraries/whereami/src)
include_directories(libraries/stb)
file(GLOB SOURCES "src/*.cpp" "src/*.h" "libraries/whereami/src/whereami.c" "libraries/glad/src/glad.c")
add_executable(OpenGLEngine3D ${SOURCES})
target_link_libraries(OpenGLEngine3D glfw)
Its dirty(I think) but it works.
So now my first question is, how to improve my CMake script? What is redundant or done in a poor way?
Now my program also requires some resources(like shaders, textures) which I have stored in a directory along with my CMake script, libraries and c++ files.
So my second question is, how would I tell CMake to the ide/compiler to copy the files in a certain directory to the program build directory(where the compiled binaries are) after compiling?(And have it only do it when the files aren't there ofc.)
Thanks!
I recently came across this article, which might be help you with CMake.
Here are a couple suggestions from me:
You're safe to use newer version of CMake. Currently, it's 3.11. There's no point in sticking to old versions.
Consider listing all your sources in a variable (using set command) instead of using file(GLOB). file(GLOB) will be evaluated only once, when generating build files. If you add new sources, you'll have to re-generate it manually, so it doesn't help too much, and is harder to debug (and really, debugging more complex CMake projects can be painful).
Avoid using include_directories (and link_libraries). Prefer using target_include_directories which works per-target. It allows to express dependencies between targets (when you have more than one - which might happen as your project grows)
You might consider using find_package(GLFW), instead of including GLFW in your project. Edit: actually, CMake doesn't came with find module for GLFW, but you can use an external module for this (e. g. this one) as described here.
Edit:
Example below illustrates the idea behind point 2), assuming that sources are placed in "src/" directory on the same level as CMakeLists.txt file:
set(engine_sources
"src/header_1.hpp"
"src/source_1.cpp"
# and so on for reset of files...
)
add_executable(OpenGLEngine3D ${engine_sources})
As for the second question: that's what file(COPY) command is for. Alternatively, you could just leave assets in source directory, and set working directory in IDE.
Side note: if you choose the second options, there appears to be a way to set this from CMake for Visual Studio, by setting VS_DEBUGGER_WORKING_DIRECTORY property:
set_target_properties(OpenGLEngine3D PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
(I haven't checked if this works as expected, as I rarely use VS. I remember looking for something like that in the past, and just recently came across it.)

C++ how to manage dependencies (use libraries from github for example)

I'm very new to C++ world, so please, sorry for such a dummy question. I googled a little, but wasn't able to find a proper answer.
My question is fairly simple - how should I use libraries in C++ world. For example in Java - there is maven and gradle for this task. In Python - I use pip. In javascript npm and bower do all the stuff. In C# you use nuget or just adding DLL lib to your project. But looks like in C++ things isn't such easy.
I found a tool, called conan but amount of libraries they have is pretty small and does not include any what I'm looking for.
So, for example - I want to use nlp lib meta but it seems like they don't provide any installer files. So I assume I need to get sources from Github. Should I compile them and then try to add the compiled files to my project or do I need to have a lib folder in my project, and put meta's sources in those folder and after operate with meta's sources as they are in my project?
My question isn't about how to install specific meta lib, but more from the source management point of view. If I use Visual Studio on Windows for example, but my colleague will be coding Clion under Linux. And I don't know the proper way of managing dependencies in C++ world.
C++ doesn't have anything like pip or npm/bower. I don't know if maven or gradle can be persuaded to handle C++ libraries.
In general, you are going to have to end up with
Header files in a directory somewhere
library files (either static libraries, or DLLs/shared objects). If the library is a header-only library like some of the boost libraries, then you won't need this.
You get hold of the library files, either by building them on your machine (typical for open source projects, and projects aimed at Linux platforms), or by downloading the pre-compiled binaries (typical for Windows libraries, particularly paid-for).
Hopefully, the instructions for building the library will be included on the library website. As noted in the comments, 'meta' seems to be quite good at that.
When you try to compile with the library, you may need a command line option (eg -I) to specify the directory containing the header files, and you may need a linker option (eg -l) to tell the linker to link against your library.
Cget will install any package that uses standard cmake, and works for linux and windows. It has shorten syntax for getting packages directly from github(such as cget install google/googletest).
In addition, dependencies can be automatically downloaded as well by listing them in a requirements.txt file.
There is also recipes for installing non-cmake packages and the repository here has over 300 libraries(and growing). So you can install curl with just cget install pfultz2/cget-recipes curl.
C++ sadly has no package manager for libraries. Some are out there and try to be one which are still small and scattered though (like conan).
In linux you have some "-dev" packages you can install but they are also not "all".
You most likely end up downloading them yourself. Next though is you have the problem of integrating those libraries. You have different build systems per operating system so you have to see how you build c++ files.
Like in windows with Visual studio you have to get a visual studio project or a nmake compatible makefile to build the libraries and then add them to your project. Same with linux makefiles.
There are several build frameworks who are higher level like cmake. The example you have in your post also works with CMake. So integrating that one into a cmake build environment would be easier but this only applies for other libraries also trying to use/integrate cmake build environments to it (e.g. boost / qt is doing this).
Yeah these are some thoughts to this. Sadly there won't be an easy/definitive answer to this because there is no real central c++ packet repository which is also integrated into a build system.
It appears to me that the Crascit/DownloadProject could be of help in your situation. It provides CMake plugins for downloading projects from a git repository by specifying tags, etc. Then you can use add_custom_target to run commands you need to have the project built.
There are a number of popular C++ released via nuget packages.
You can search on the gallery for them, usually using the native or c++ tags. Obviously you need a nuget manager for your OS, and I'm pretty sure that the C++ nuget packages rely on MSBuild for a lot of the grunt work, so you may have trouble getting a non-Visual Studio oriented setup to work nicely.
Also Gradle actually does have some support for native dependencies as well. I had a look at little while ago but the work on it was curtailed because the support for VS 2015 was lacking.
I recommend vcpkg for cross platform development. It has a number of IDE integrations. GitHub project is here.
I do cross platform development using tools like CMake, Visual Studio, WSL. vcpkg was incredibly helpful.
I started new project... in cureent time it's just "source package manager" you can provide some source code on github and then it will be just copy to you project (based on cmake + auto generating cmake files)
So links here:
https://github.com/wsjcpp/wsjcpp

Compiling a static QT application on Windows

I am new to QT and I am enjoying the experience except for the fact I cannot manage to statically link the QT library to the output binaries. When I run the output file outside of the QT directory, I get The program can't start beacuse QtCored4.dll is missing. Obviously QT is dynamically linking their libraries and requesting a .dll I do not have. Is there a way to statically compile QT's libraries into a static binary so none of QT's dlls are required? I ask this because I am already up to 11 .dlls for my project, and I would really like to cut down the amount of files that have to be distributed with my software. Size is not a problem for me. Thanks.
I have tried adding CONFIG += static to the .pro file, but to no avail.
First off, you can't statically link Qt unless you've bought a commercial license. To do so would put you in violation of the LGPL license under which the non-commercial version is distributed. I feel your pain, I've got many, many DLL's to go with my software.
Thankfully, you probably do have the DLL's if you used the installer: you don't need to build from source, that should have been done automatically. You'll find them in Qt\Version\bin, where Qt is the directory you installed Qt, and version is the version of Qt you installed. For example, mine is found in G:\Libraries\Qt\4.7.1\bin.
I did, however, have some issues with not having one of the DLL's built - one for working with OpenGL - and performed a rebuild to do so. I've also done so when I've switched versions of Visual Studio. I think it's handy to be able to do so, it's easy, Open a terminal in the Qt directory, and execute:
configure.exe -platform XXX'
Where XXX denotes the type of build you want to perform. Valid options include win32-msvc2005, win32-msvc2008, win32-msvc2010. So I use:
configure.exe -platform win32-msvc2010'
Other options are detailed here. These instructions apply if you've downloaded the source code, however you might have to add the current directory to the path variable like so:
set PATH=%cd%\bin;%PATH%
The whole procedure should take about an hour.
You need to download the source packet of QT and compile it. It takes some time but is not really complicated.
Download and unzip QT source
Start a compiler shell (Visual Studio or mingw)
Execute configure in the QT source directory - add a flag for static compile here
execute make (Visual Studio nmake)
Wait some hours depending on the speed of your machine