How do I use CMake? - c++

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.

Related

How to install a cpp library using cmake on Windows x64?

I'm using CLion with MinGW-GCC on the Windows-x64 platform - This is the background of the problem.
I was trying to install gtest before. But a lot of confusion arose in the middle.
First time I ran those commands(in googletest-release-1.12.1\) according to the instructions of googletest-release-1.12.1\googletest\README.md:
mkdir build
cd build
cmake ..
But I got error messages like:
CMake Error at CMakeLists.txt:51 (project):
Failed to run MSBuild command:
C:/Windows/Microsoft.NET/Framework/v4.0.30319/MSBuild.exe
to get the value of VCTargetsPath:
Then I changed my last command to
cmake -G "MinGW Makefiles" ..
because I use make provided by MinGW. I don't know whether it's right but, it ran properly.
then I called
make
make install
make ran smoothly. But when I ran make install, I got these messages:
Install the project...
-- Install configuration: ""
-- Installing: C:/Program Files (x86)/googletest-distribution/include
CMake Error at googlemock/cmake_install.cmake:41 (file):
file INSTALL cannot make directory "C:/Program Files
(x86)/googletest-distribution/include": No such file or directory.
Call Stack (most recent call first):
cmake_install.cmake:42 (include)
make: *** [Makefile:109: install] Error 1
I have no idea at all this time. So I changed my way. According to this answer, I copied the whole library into my project and edited CMakeLists.txt like this:
cmake_minimum_required(VERSION 3.23)
project(gtest_study)
set(CMAKE_CXX_STANDARD 20)
add_subdirectory(googletest-release-1.12.1)
include_directories(googletest-release-1.12.1/googletest/include)
include_directories(googletest-release-1.12.1/googlemock/include)
add_executable(gtest_study main.cpp)
target_link_libraries(gtest_study gtest gtest_main)
target_link_libraries(gtest_study gmock gmock_main)
So my questions are:
Is there any difference between the two which build it using make and cmake metioned firstly, and just use commands like include_directories and target_link_libraries in CMakeLists.txt? (maybe like .h and .dll file? Or just completely the same? I don't know)
When I use make install to install a library on Windows, what should I do in particular? Specify some directory (I don't know which one) or what?
Although in my system environment I use MinGW-makefile, in CLion which the libraries are eventually used, I use ninja as the generator for CMake (it just comes with CLion, not installed for the system). Do I have to specify it and how? (-G "Ninja"doesn't work in my native env)
The difference between
cmake ..
and
cmake -G "MinGW Makefiles" ..
Is the choice of generator: The former uses the default generator, the latter uses the generator you specified. (cmake --help should put a * next to the default generator.)
Based on the error message I assume this is a visual studio generator and you may not be able to run that one properly from within a MinGW terminal.
In the latter case the default install directory seems to be based on the target OS (Windows) but does not seem to incorporate the fact that you're running from a MinGW terminal where the default install path (C:/Program Files (x86)/googletest-distribution) is not valid.
You could try to fix this by providing it during cmake configuration (passing -D 'CMAKE_INSTALL_PREFIX=/c/Program Files (x86)/googletest-distribution' before the source dir) or by providing the install directory during the installation.
The following process should allow you to install the lib. I'm using my preferred way of building here, i.e. not using build system dependent commands, but using cmake to run the build/install commands. I assume the working directory to be the root directory of the gtest sources:
cmake -G "MinGW Makefiles" -S . -B build
cmake --build build
cmake --install build --prefix '/c/Program Files (x86)/googletest-distribution'
The last command needs to be run with admin privileges, the first 2 I don't recommend running as admin. You could instead install to a directory where you do have the permissions to create directories even without admin privileges.
The difference between using the process described above and using add_subdirectory is that the former results in a installation on the system which can be used via find_package and the google test libs won't be rebuilt for every project where you do this.
...
project(gtest_study)
...
# you may need to pass the install location via -D CMAKE_PREFIX_PATH=<install_location> during configuration for this to work
find_package(GTest REQUIRED)
target_link_libraries(gtest_study PRIVATE GTest::gtest_main GTest::gmock)
The latter builds the google test project as part of your own project build and for every project where you use this approach a seperate version of the google test libs is built. Note: there should be no need to specify the include dirs yourself, since this kind of information is attached to the cmake target and gets applied to the linking target automatically:
#include_directories(googletest-release-1.12.1/googletest/include)
#include_directories(googletest-release-1.12.1/googlemock/include)
add_executable(gtest_study main.cpp)
target_link_libraries(gtest_study PRIVATE gtest_main gmock)
As for 3.: The CMake generator used for building GTest should be independent of the generator of the project using it. The thing that's important is that the compilers used by the build systems are compatible. I cannot go into detail about this, since I've never used CLion and therefore have too little knowlege about the compilers used by it. (Personally I'm working with Visual Studio on Windows.)

LLVM build only selected tools or targets

I am new to c++ & am referring to the llvm project https://llvm.org/docs/GettingStarted.html. There is a guide saying
If you are space-constrained, you can build only selected tools or only selected targets. The Release build requires considerably less space.
But I am unable to find the exact way to do it.
Currently, I am running the following to build all the tools
mkdir build
cmake ../llvm
make
This would create many tools such as llvm-addr2line, llvm-ar, llvm-dwarfdump etc.
How could I build it such that it only gives me 1 tool, eg llvm-dwarfdump (eg https://llvm.org/docs/CommandGuide/llvm-dwarfdump.html)?
Is there an easy way to know the code that makes up these command.
Thank you
CMake generates a target for every add_library, add_executable, and add_custom_target command. These targets can be built separately by calling make <target> or with the build tool independent CMake abstraction cmake --build <builddir> --target <targetname> --config Release. To find out which targets have been defined by LLVM you need to inspect all CMakeLists.txt and *.cmake files.

Unit testing by CTest of Cross-compiled Project

I am developing hobby OS which is cross-compiled to other architecture than my development PC and is run in QEMU emulator.
I am trying to introduce unit testing of the source files I develop for my kernel but to let them run on my development machine rather than in QEMU on my target.
In order to cross-compile my sources, I use the toolchain file which uses my custom GCC toolchain. As coming from CMake principle of toolchain file usage, the toolchain file is set up prior to project(...) definition in my root CMakeLists.txt file.
My question is how to build my test executables for my dev machine (x86_64) using the built-in GCC while cross-compiling my kernel binary for target platform... I do not know how to set CMAKE_CXX_COMPILER / CMAKE_C_COMPILER cmake variables specifically for each use case (testing, target build)
To have a look at my particular project, please feel free to navigate here:https://gitlab.com/revolta/revolta
I would like to add test/ to my project root including selected sources from source/... and manage it somehow from my root CMakeLists.txt
Thanks in advance for any concept ideas and help! Cheers Martin
The rule is - there is one compiler per configuration. Do not try to make to use two compilers per configuration. Instead run cmake two times and configure it twice,. separately for x86 testing and separately for releasing to target build.
So write a small script (you have configure.sh anyway) (I usually write a makefile with all PHONY targets) that would run and build the project twice for two configurations:
# ./compile_and_test_your_project.sh
# build for target host
cmake -DCMAKE_TOOLCHAIN_FILE=the_toolchain -S. -B_build/crosscompiled
cmake --build _build/crosscompiled --target the_main_project_target
( cd _build/crosscompiled && ctest )
# build for native host
cmake -DCMAKE_C_FLAGS="-fsanitize=undefined -ggdb3 -O0" -S. -B_build/native
cmake --build _build/native --target only_testing_targets
( cd _build/native && ctest )
Do not set CMAKE_CROSSCOMPILING_EMULATOR inside cmake config. I advise to try to keep cmake configuration platform agnostic as much as you can and pass platform specific parts using arguments to cofiguration cmake. Such way is scalable - you may use a different toolchain and different environment with ease, or try different compiler options. Inside cmake you can see if you are crosscompiling with just if (CMAKE_CROSSCOMPILING). Also see CMAKE_CROSSCOMPILING_EMULATOR.
ps. My makefile from one of my projects that sets different CMAKE_CROSSCOMPILING_EMULATOR depending on make target.

How to build a project generated by CMake for MinGW makefiles?

I'm trying to build SFML's source code after I've ran the directory through CMake and after CMake generated the makefiles. I have no idea how though.
This is how the directory where I've set CMake to dump it's generation to:
On Linux I use
cmake --build .
to build my project. It calls the according build command. It works with make and ninja. Probably it works on Windows with MinGW.
Remember that cmake doesn't come with a build system. It only calls the commands. You have to install the build system you want to use.

"CMakeLists.txt" seems to be missing

I was trying to build SFML in order to start developing 2d-games in c++. I put the source-code directory inside C: (the directory itself is called 'SFML'). while trying to generate .cbp files using CMake, I ran into an error:
"The source directory "C:/SFML" does not appear to contain CMakeLists.txt"
It seems like there is a missing file that CMake didn't create.
I am using Cmake 3.10.1, the installation file can be found in https://cmake.org/download/ under the title:"Windows win32-x86 Installer".
I tried to build SFML 2.4.2, using the generator of Codeblocks - MinGW makefiles. The version of codeblocks used is: codeblocks-16.01mingw-setup.exe, found in http://www.codeblocks.org/downloads/26
Did someone encounter the same problem before and knows how to overcome it? If not -
Is there an already-built, ready to use, libray of this version? (2.4.2)
If not.. do you know about a version of SFML that is usable in visual studio 2017?
And another question (That is the last one, I promise...) - maybe you can recommend me about another library for c++, that is usable to develop 2d-games?
edt:
note: I am completely new to all this building thing
the containments of SFML:
maybe it's the binary version?
lib contains some static libraries, bin contains some .dll s
You probably downloaded something wrong or potentially extracted the SFML source into a sub folder or something like that.
Since you've mentioned Visual Studio: SFML is 100% compatible with Visual Studio and you can build it from source any time without having to worry about dependencies (everything included in the repository).
The steps to compile are pretty easy. I'd recommend you install Git to clone the latest source from the SFML repository. In addition you'll need CMake, which you obviously got already.
Open a Command Prompt and change your directory to C:\SFML.
Clone the official repository using Git: git clone https://github.com/SFML/SFML.git source (note the trailing .)
Wait for the source to be checked out to the source sub directory.
Create a new directory called build: md build && cd build
Now invoke CMake, pointing to the source directory and also defining your install path: cmake -DCMAKE_INSTALL_PREFIX=C:/SFML ../source
Build and install a debug build of SFML: cmake --build . --target install --config debug
Build and install a release build of SFML: cmake --build . --target install --config release
Alternatively you can just open the generated Visual Studio solution and build the INSTALL project on your own.
(You shouldn't have to define a build tool or anything; CMake should notice Visual Studio being installed and pick it up automatically.)
I have experienced this using cmake version 3.10 when using the -S command line option. On cmake version 3.15.4 it behaves as expected - so if you update cmake then it might just work.
Note that the -S command line option was not supported before version 3.13:
https://cmake.org/cmake/help/v3.13/release/3.13.html#command-line
Normally cmake is called from a "build" subdirectory of a project root, the project root contains CMakelists.txt. So you would create a "build" directory, change to it, and submit "cmake ..". This would pull in CMakelists.txt from the project root, and use the "build" subdirectory that you are in as the build directory. We say "build", what it actually does is generate makefiles which can then used by the "native" build system (e.g. "make" or Visual Studio) to perform the actual compilation and linking. This arrangement is not always convenient, hence the introduction of the -S and -B command line options.