CMake : add_executable not generating an executable under windows OS - c++

I am trying to generate an executable with CMake under windows by command line.
This is what I do:
I enter testprog directory then do
cd build
cmake ..
I also tried this:
cd build
cmake -G"Visual Studio 16 2019" ..
same result as earlier attempt.
This builds bunch of files in build directory but no executable is ever created.
It creates files to be opened in visual studio.
This is how my folder look like;
testprog
-build
-src
-main.cpp
-call.h
-include
-main.h
-call.h
-CMakeLists.txt
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
project(testprog)
include_directories(include)
file(GLOB SOURCES "src/*.cpp")
add_executable(testprog ${SOURCES})

This builds bunch of files in build directory but no executable is ever created. It creates files to be opened in visual studio.
That's it.
That's exactly what CMake does; CMake is a meta build system where it generates all necessary files that you can open with, say, Visual Studio on Windows since you've given:
-G "Visual Studio 16 2019"
and build the projects with Visual Studio.
add_executable does not magically build your source files. It only tells the given tool to do so.
It's all same in Unix-like platforms as well; CMake drops Makefile, and then you build with make. (Or other tools like Ninja can be a good candidate instead of make)
EDIT
I understand, but is there no way to build the executable from command line without the need of say Visual studio
Yes, you can! Microsoft provides Build Tools for Visual Studio for those who don't want the whole heavy IDE.
This is quite common when it comes to establishing a build server.

In order to build you have to call cmake --build <dir> [<options>] [-- <build-tool-options>]
Documentation is here

Related

Set cache, build files and binary files directories for Visual Studio in CMake

Current environment
I have the following file structure:
project_root/
__main.cpp # app starting point
__CMakeLists.txt # CMake build starting point
__include/ # header files
__src/ # source files
__lib/ # libraries/dependencies which are also CMake projects
__res/
__build/ # CMake cache, build files
__bin/ # compiled binaries
I've been working with VS Code for both Windows and Linux platforms, but I would like to try out Visual Studio environment.
So far, using CMake Tools extension worked pretty well placing build files in build/ and binaries in /bin with the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
project(OPENGL_TEMPLATE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/build")
# targets, libs and properties setup
The problem
Unfortunately, Visual Studio overrides these variables and creates some project_root/out/Debug/ directory, which does not fit my current directory tree.
There are two ways (to my knowledge) to run CMake project in Visual Studio, which I would like both to be compatible with my current directory tree:
Generate VS solution with CMake from terminal or CMake GUI and open it;
Open directory from File Explorer with "Open with Visual Studio"
So far, I have come up with this CMakeLists.txt:
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build")
set(CMAKE_BINARY_DIR "${CMAKE_SOURCE_DIR}/build")
project(PROJECT_NAME)
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR "In-source builds are forbidden.")
endif()
add_executable(main)
set_target_properties(main PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin"
ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/build"
VS_STARTUP_PROJECT main
FOLDER "App"
)
# other targets, libs and properties setup
And it works when generating .sln solution with CMake (but does not set the VS_STARTUP_PROJECT for some reason, but this is for another SO question), here build files go to build/ and binaries to bin/.
When using the second approach, VS still generates everything into out/Debug/, seemingly completely ignoring CMAKE_BINARY_DIR (which they claim corresponds to buildRoot VS configuration variable) and ARCHIVE_OUTPUT_DIRECTORY, RUNTIME_OUTPUT_DIRECTORY target properties.
The question (finally)
How can I setup CMake variables so that Visual Studio respects them (and does not override) using both approaches? Ideal situation would be to just open a clean project and be ready to configure, build and run, which means no additional tinkering in Visual Studio configuration files/settings. I am using Visual Studio 2022 Community 17.3.3.

How to configure CMake so that the generated Visual Studio project finds the executable?

I'm trying to set up a project with CMake in Visual Studio 2017 on Windows. The CMakeLists.txt is pretty simple. I am just adding an executable with source files and I specify the linker language to C++.
Then I run cmake in my build_64 folder and I get the generated VS solution containing ALL_BUILD, ZERO_CHECK and my actual project of course. I set it to be my start project and try to run it but then I get this error message:
Unable to start program 'C:\Users...\Documents\MyProject\build_64\Debug\Project1.exe'.
The system is unable to find the specified file.
CMakeLists.txt:
cmake_minimum_required(VERSION 3.2)
project(MyProject)
# create Project1
set(PROJECT1_SOURCES ${CMAKE_SOURCE_DIR}/Project1/src/)
add_executable(Project1 ${PROJECT1_SOURCES})
set_target_properties(Project1 PROPERTIES LINKER_LANGUAGE CXX)
cmake command:
cmake .. -G "Visual Studio 15 2017 Win64"
Why can Visual Studio not find my executable? And how can I configure it so that Visual Studio finds it?
Here is my folder structure:
MyProject
- build_64
- ALL_BUILD.vcxproj
...
- MyProject.sln
- Project1.vcxproj
- ZERO_CHECK.vcxproj
- Project1
- src
CMakeLists.txt
CMakeSettings.json
Cmake does not generate executable - cmake creates a build system for you. Then you need to build your project in VS or inside the command line.
If you need to address some executable and later call it here is a snippet for you :
find_program(THRIFT_COMPILER NAMES thrift thrift.exe HINTS ${THRIFT_COMPILER_ROOT} ${THRIFT_ROOT}/compiler/cpp/bin ${THRIFT_ROOT}/bin ${THRIFT_ROOT}/bin/Release /usr/local /opt/local PATH_SUFFIXES bin bin64)
exec_program(${THRIFT_COMPILER}
ARGS -version
OUTPUT_VARIABLE __thrift_OUT
RETURN_VALUE THRIFT_RETURN)
message( STATUS "Thrift compiler version: ${__thrift_OUT}" )

How to build and debug a MSYS2 / MinGW64 / CMake project in Visual Studio 2017?

I have successfully built a C++ project using MSYS2 / MinGW64 / CMake tools. Now I would like to edit it and debug it in Visual Studio, as it is a nice IDE and the default development tool in Windows. Sadly, I am not able to build the project in Visual Studio because it cannot find libraries.
Here is the CMakeLists.txt file I'm using where, among other things, I specify where are the include folders, the link files and link directories:
# src/CMakeLists.txt
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
# Project name and current version
project(rascam VERSION 0.1 LANGUAGES CXX)
# Enable general warnings
# See http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
# Use 2014 C++ standard.
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Must use GNUInstallDirs to install libraries into correct locations on all platforms:
include(GNUInstallDirs)
# Pkg_config is used to locate header and files for dependency libraries:
find_package(PkgConfig)
# Defines variables GTKMM_INCLUDE_DIRS, GTKMM_LIBRARY_DIRS and GTKMM_LIBRARIES.
pkg_check_modules(GTKMM gtkmm-3.0)
link_directories( ${GTKMM_LIBRARY_DIRS} )
include_directories( ${GTKMM_INCLUDE_DIRS} )
# Compile files:
add_executable(rascapp
cpp/main.cpp
cpp/main-window.cpp
)
# Add folder with all headers:
target_include_directories(rascapp PRIVATE hpp)
# Link files:
target_link_libraries(rascapp
${GTKMM_LIBRARIES}
)
To set up my environment I installed MSYS2 on a Windows platform, and added all the following packages via pacman:
pacman -S base base-devel net-utils git ruby wget man
pacman -S msys/openssh msys/vim msys/bc nano msys/tmux
pacman -S gzip zip unzip msys/p7zip tar msys/tree
pacman -S msys/winpty msys/ed msys/pwgen msys/zsh
pacman -S mingw64/mingw-w64-x86_64-jq
pacman -S msys/screenfetch
pacman -S mingw-w64-x86_64-toolchain
pacman -S mingw64/mingw-w64-x86_64-cmake
My project is dependent on Gtkmm, so I added the following dependency:
pacman -S mingw64/mingw-w64-x86_64-gtkmm3
Then I added the C:\Msys2\MinGW64\bin to the path.
Then, I switched to the MSYS2/MinGW64 terminal, and fetched my project, created a build folder and built it. As I'm in Windows, the CMake produces Visual Studio files by default. I would be fine with that, if only I could make it work. Running out of ideas, I specified the Unix Makefiles option:
cd /c/where/your/root/folder/is
git clone https://github.com/cpp-tutorial/raspberry-cpp-gtk-opencv.git
cd raspberry-cpp-gtk-opencv
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -G"Unix Makefiles" ../src/
make
./racapp.exe
And this does build the project. It produces an executable that I can launch from either MinGW64 or a Window Explorer by double clicking on it. I can also gdb it
After checking that the project looks right, I tried to open it in Visual Studio Community 2017 15.9.3 in two different ways:
Use CMake to build a Visual Studio project: Visual studio opens the project and I can see the different targets, but when I launch a debug session it complains that it cannot found Gtk libraries. Looking in the project properties, I can see the that the libraries are taken from the correct path C:\Msys2\MinGW64\bin. And I verified that the library exists, although with a different name: libgtkmm-3.0.dll.a instead of gtkmm-3.0.dll.
Use Visual Studio's Open File feature: Again, project opens, I can see the targets and the source files, but it complains that it doesn't find the include files gtkmm.h. I haven't managed to reach link phase, but my guess is that it wouldn't find libraries.
My question is, what is the correct and standard way to build and debug a MSYS2 / MinGW64 / CMake project in Visual Studio?
As other users commented (thanks, #DavidGrayson), the gcc.exe and g++.exe compilers that are installed in the MSYS2 configuration do not use the format that Visual Studio requires for debug symbols. In consequence, it is not possible to use Visual Studio for debugging executables built with Mingw.
To be able to debug (and build and edit), use some other IDE, more MinGW friendly, like Code::Blocks.
Still, to answer my own question, I describe here the procedure to configure the project in Visual Studio to edit the source files, build and launch the executable. For this procedure, no need to use CMake for anything:
Launch Visual Studio 2017
File -> Open -> Folder...
Select the folder that contains the top CMakeLists.txt.
It should find automatically that this is a CMake project, and try to load it. Maybe it complains about some errors.
CMake -> Change CMake Settings -> Choose your top CMakeLists.txt.
In the dialog, look for Mingw64-Release (actually, there is a *Mingw64-Debug, but you will not be able to debug anyway).
If everything went well, a CMakeSettings.json has appeared on your project, and Visual Studio rebuilds the project, this time without errors.
Choose an executable target.
Launch.
It should build then execute the application.
This is no longer true, you can build and debug projects using MingW gdb by following the steps mentioned below using the latest Visual Studio IDE:
https://devblogs.microsoft.com/cppblog/using-mingw-and-cygwin-with-visual-cpp-and-open-folder/.
I've tried for a bigger project and it works fine apart from the fact that the debugging is not very clean.

How to create an installer with CMake + CPack + NSIS on Windows?

I'd like to create a cross-platform installer for a C++ based system I am building.
I use CMake to build everything, and it would be great if I could use CPack to make the installer. I already have CPack working on OSX, but I cannot get it to work on Windows. To make things easier, I tried to get the example at http://www.cmake.org/Wiki/CMake:Packaging_With_CPack to work with the NSIS installer software. I cannot find the NSIS installer anywhere after configuring (with VS 2010 Win64 generator).
Maybe I am confused, but I thought it would be possible to create the installation package with only the source, CMake, CPack, and NSIS without any need for Visual Studio. Is this possible?
A link to a full tutorial (the one at http://www.cmake.org/Wiki/CMake:Component_Install_With_CPack skips over the relevant information to get NSIS working and doesn't mention generators or compilers) would be very helpful, or a basic explanation of how I can get to this mythical generated NSIS installer would be great.
Here is CMakeLists.txt for the example above:
cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
project(StPMS)
add_library(mylib mylib.cpp)
add_executable(mylibapp mylibapp.cpp)
target_link_libraries(mylibapp mylib)
install(TARGETS mylib
ARCHIVE
DESTINATION lib
COMPONENT libraries)
install(TARGETS mylibapp
RUNTIME
DESTINATION bin
COMPONENT applications)
install(FILES mylib.h
DESTINATION include
COMPONENT headers)
set(CPACK_GENERATOR NSIS)
set(CPACK_PACKAGE_NAME "MyLib")
set(CPACK_PACKAGE_VENDOR "CMake.org")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyLib - CPack Component Installation Example")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_VERSION_MAJOR "1")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example")
SET(CPACK_NSIS_MODIFY_PATH ON)
INCLUDE(CPack)
... I thought it would be possible to create the installation package with only the source, CMake, CPack, and NSIS without any need for Visual Studio. Is this possible?
Kind of. It depends on what you mean by "without any need for Visual Studio". You need a build tool to actually create the lib and exe. On Windows, you need something like Visual Studio's msbuild, especially if you specified "Visual Studio 10 Win64" as the generator.
If you mean "without running Visual Studio", then the answer is yes. You can have CMake execute your chosen build tool using the --build argument.
After running CMake, you end up with a file PACKAGE.vcxproj in your build directory. It is building this which will create the installer. You can either build the PACKAGE project from inside Visual Studio, or you can invoke msbuild directly by doing:
msbuild /P:Configuration=Release PACKAGE.vcxproj
from your build directory in a VS command prompt.
This should yield your installer named MyLib-1.0.0-win64.exe, also in your build directory.
If you want to just use CMake, then an alternative to invoking msbuild is:
cmake --build . --target PACKAGE.vcxproj --config Release
Or you can build the solution first, then invoke CPack to create the installer:
cmake --build . --config Release
cpack -C Release

How do I use CMake?

I am trying to use CMake in order to compile opencv.
I am reading the tutorial but can't understand what is CMakeLists files and how is it connected to the gui of CMake?
Also couldn't understand what are makefiles, are they the same is CMakeLists?
And which file is it which I in the end open with visual-studio?
I don't know about Windows (never used it), but on a Linux system you just have to create a build directory (in the top source directory)
mkdir build-dir
go inside it
cd build-dir
then run cmake and point to the parent directory
cmake ..
and finally run make
make
Notice that make and cmake are different programs. cmake is a Makefile generator, and the make utility is governed by a Makefile textual file. See cmake & make wikipedia pages.
NB: On Windows, cmake might operate so could need to be used differently. You'll need to read the documentation (like I did for Linux)
CMake takes a CMakeList file, and outputs it to a platform-specific build format, e.g. a Makefile, Visual Studio, etc.
You run CMake on the CMakeList first. If you're on Visual Studio, you can then load the output project/solution.
Yes, cmake and make are different programs. cmake is (on Linux) a Makefile generator (and Makefile-s are the files driving the make utility). There are other Makefile generators (in particular configure and autoconf etc...). And you can find other build automation programs (e.g. ninja).
CMake (Cross platform make) is a build system generator. It doesn't build your source, instead, generates what a build system needs: the build scripts. Doing so you don't need to write or maintain platform specific build files. CMake uses relatively high level CMake language which usually written in CMakeLists.txt files. Your general workflow when consuming third party libraries usually boils down the following commands:
cmake -S thelibrary -B build
cmake --build build
cmake --install build
The first line known as configuration step, this generates the build files on your system. -S(ource) is the library source, and -B(uild) folder. CMake falls back to generate build according to your system. it will be MSBuild on Windows, GNU Makefiles on Linux. You can specify the build using -G(enerator) paramater, like:
cmake -G Ninja -S libSource -B build
end of the this step, generates build scripts, like Makefile, *.sln files etc. on build directory.
The second line invokes the actual build command, it's like invoking make on the build folder.
The third line install the library. If you're on Windows, you can quickly open generated project by, cmake --open build.
Now you can use the installed library on your project with configured by CMake, writing your own CMakeLists.txt file. To do so, you'll need to create a your target and find the package you installed using find_package command, which will export the library target names, and link them against your own target.
Cmake from Windows terminal:
mkdir build
cd build/
cmake ..
cmake --build . --config Release
./Release/main.exe
Regarding CMake 3.13.3, platform Windows, and IDE Visual Studio 2017, I suggest this guide. In brief I suggest:
1. Download cmake > unzip it > execute it.
2. As example download GLFW > unzip it > create inside folder Build.
3. In cmake Browse "Source" > Browse "Build" > Configure and Generate.
4. In Visual Studio 2017 Build your Solution.
5. Get the binaries.
Regards.