From executable to libraries in CMake

Harshit Bargujar
The Startup
Published in
8 min readApr 26, 2020

In this post we will be creating an executable and will get detailed information of every step. (Part-1)

Possibilities of CMake Build Systems

CMake is one of the most used build system and is easy to use. As i have already introduced to you guys to CMake in my previous post this time we will be configuring and building a simpler project. This project contains only one source file which is written in C++.

/*FILE hello-world.cpp*/#include <iostream>
int main()
{
std::cout<<"Hello World"<<std::endl;
std::cin.get();
}

Alongside the source file, we need to provide CMake with a description of the operations to perform and to configure the project for the build tools. The description is done in the CMake language will place the CMake instructions into a file called CMakeLists.txt.

Follow these steps to make your first executable in CMake:

  • Open a text file with your favorite editor. The name of this file will be CMakeLists.txt.
  • The first line sets a minimum required version for CMake. A fatal error will be issued if a version of CMake lower than that is used:
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
  • The second line declares the name of the project (hello) and the supported language (CXX stands for C++):
project(hello LANGUAGES CXX)
  • Here CMake is instructed to create a new target: the executable hello-world. This executable is generated by compiling and linking the source file hello-world.cpp. CMake will use default settings for the compiler and build automation tools selected:
add_executable(hello-world hello-world.cpp)
  • Save the file in the same directory as the source file hello-world.cpp. Remember that it can only be named CMakeLists.txt.
  • We are now ready to configure the project by creating and stepping into a build directory:
$ mkdir build && cd build
$ cmake ..
— The CXX compiler identification is GNU 9.2.0
— Check for working CXX compiler: C:/MinGW/bin/g++.exe
— Check for working CXX compiler: C:/MinGW/bin/g++.exe — works
— Detecting CXX compiler ABI info
— Detecting CXX compiler ABI info — done
— Detecting CXX compile features
— Detecting CXX compile features — done
— Configuring done
— Generating done
— Build files have been written to: E:/PROJECTS/YouTube/TutoriaL 1/build
  • If everything went well, the configuration for the project has been generated in the build directory. We can now compile the executable:
$ cmake --build .Scanning dependencies of target hello-world
[ 50%] Building CXX object CMakeFiles/hello-world.dir/hello- world.cpp.obj
[100%] Linking CXX executable hello-world.exe
[100%] Built target hello-world

Now go to the build , search for the hello-world.exe and see the output.

hello-world.exeHello World

How did it worked?

# FINAL CMakeLists.txtcmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(hello LANGUAGES CXX)
add_executable(hello-world hello-world.cpp)

The CMake language is case insensitive , but the arguments are case sensitive. Also in CMake the default programming language is C++.

Well to configure the project and generate the build system we have to run CMake through the command-line interface (CLI). To get more help while building the project use

cmake --help

to get a full help menu listing of all the available switches.

Running a CMake commands output a series of status message to inform us about the configurations.

CMake is a build system generator. We can describe what type of operations does build system, such as Unix Makefiles, Ninja, Visual Studio, and so on, will have to run to get code compiled.On Windows, Visual Studio is the default generator.

  • Makefile: The set of instructions that make will run to build the project.
  • CMakeFiles: Directory which contains temporary files, used by CMake for detecting the operating system, compiler, and so on. In addition,depending on the chosen generator, it also contains project-specific files.
  • cmake_install.cmake: A CMake script handling install rules, which is used at install time.
  • CMakeCache.txt: The CMake cache, as the filename suggests. This file is used by CMake when re-running the configuration.

After building the executable in using CMake scripts it’s time to look at the different arguments that can be used while building the CMake scripts.

The build system generated by CMake , the Makefile in the (above example) will contain targets and rules to build executables, libraries and object files for the project. Hello-world is the only executable in our project i.e our only target, but if we run the following command :

$ cmake --build . --target helpThe following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... edit_cache
... rebuild_cache
... hello-world
... hello-world.obj
... hello-world.i
... hello-world.s

reveals that CMake generates more targets than those strictly needed for building the executable itself. The syntax for specifying these targets is:

cmake --build . --target <target name>
  • all(or ALL_BUILD with the Visual Studio generator): is the default target and will build all other targets in the project.
  • clean: is the target to choose if one wants to remove all generated files.
  • depend: will invoke CMake to generate the dependencies, if any, for the source files.
  • rebuild_cache: will once again invoke CMake to rebuild the CMakeCache.txt.This is needed in case new entries from the source need to be added.
  • edit_cache: this target will let you edit cache entries directly

When we get into more complex projects with test stages and installation rules CMake can generate additional convenience targets:

  • test(or RUN_TESTS with the Visual Studio generator): will run the test suite with the help of CTest.
  • install: will execute the installation rules for the project.
  • package: this target will invoke CPack to generate a redistributable package for the project.

After seeing these options to generate projects CMake let’s heads to CMake

Generators

CMake supports an extensive list of native build tools for different platforms. Both command-line tools, such as Unix Makefiles and Ninja, and integrated development environment (IDE) tools.

We can view the available generators for our platform by typing (scroll down to bottom in CLI and there you can see these options)

$ cmake --helpGeneratorsThe following generators are available on this platform (* marks default):
* Visual Studio 16 2019 = Generates Visual Studio 2019 project files.
Use -A option to specify architecture.
Visual Studio 15 2017 [arch] = Generates Visual Studio 2017 project files.
Optional [arch] can be "Win64" or "ARM".
Visual Studio 14 2015 [arch] = Generates Visual Studio 2015 project files.
Optional [arch] can be "Win64" or "ARM".
Visual Studio 12 2013 [arch] = Generates Visual Studio 2013 project files.
Optional [arch] can be "Win64" or "ARM".
Visual Studio 11 2012 [arch] = Generates Visual Studio 2012 project files.
Optional [arch] can be "Win64" or "ARM".
Visual Studio 10 2010 [arch] = Generates Visual Studio 2010 project files.
Optional [arch] can be "Win64" or "IA64".
Visual Studio 9 2008 [arch] = Generates Visual Studio 2008 project files.
Optional [arch] can be "Win64" or "IA64".
Borland Makefiles = Generates Borland makefiles.
NMake Makefiles = Generates NMake makefiles.
NMake Makefiles JOM = Generates JOM makefiles.
MSYS Makefiles = Generates MSYS makefiles.
MinGW Makefiles = Generates a make file for use with
mingw32-make.
Unix Makefiles = Generates standard UNIX makefiles.
Green Hills MULTI = Generates Green Hills MULTI files
(experimental, work-in-progress).
Ninja = Generates build.ninja files.
Ninja Multi-Config = Generates build-<Config>.ninja files.
Watcom WMake = Generates Watcom WMake makefiles.
CodeBlocks - MinGW Makefiles = Generates CodeBlocks project files.
CodeBlocks - NMake Makefiles = Generates CodeBlocks project files.
CodeBlocks - NMake Makefiles JOM
= Generates CodeBlocks project files.
CodeBlocks - Ninja = Generates CodeBlocks project files.
CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
CodeLite - MinGW Makefiles = Generates CodeLite project files.
CodeLite - NMake Makefiles = Generates CodeLite project files.
CodeLite - Ninja = Generates CodeLite project files.
CodeLite - Unix Makefiles = Generates CodeLite project files.
Sublime Text 2 - MinGW Makefiles
= Generates Sublime Text 2 project files.
Sublime Text 2 - NMake Makefiles
= Generates Sublime Text 2 project files.
Sublime Text 2 - Ninja = Generates Sublime Text 2 project files.
Sublime Text 2 - Unix Makefiles
= Generates Sublime Text 2 project files.
Kate - MinGW Makefiles = Generates Kate project files.
Kate - NMake Makefiles = Generates Kate project files.
Kate - Ninja = Generates Kate project files.
Kate - Unix Makefiles = Generates Kate project files.
Eclipse CDT4 - NMake Makefiles
= Generates Eclipse CDT 4.0 project files.
Eclipse CDT4 - MinGW Makefiles
= Generates Eclipse CDT 4.0 project files.
Eclipse CDT4 - Ninja = Generates Eclipse CDT 4.0 project files.
Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files.

As you can see for me there are large amounts of generators available but it will be different for you. Now if we want to build our target using a specific generator , then we have to pass the generator explicitly with -G CLI switch.

Also if you you have already generated build files and want to generate those build again using different generator then make sure you delete those previously generated files.

$ mkdir build && cd build
$ cmake -G "Visual Studio 16 2019" ..
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.18363.
-- The CXX compiler identification is MSVC 19.25.28610.4
-- Check for working CXX compiler: D:/Softwares/Visual Studio 2019/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe
-- Check for working CXX compiler: D:/Softwares/Visual Studio 2019/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: E:/Medium/Cmake from executables to libraries/build
$ cmake --build .

When you build using Visual Studio as generator you will get 3 projects when you open your visual studio solution (in this case the solution file will be hello.sln) . By default ALL_BUILD will be set as your Start Project and when you run it it will give you error like this:

So to overcome this error make hello-world your Start Project. It can be done by right clicking on hello-world project inside visual studio and then selecting Set as Startup Project.

Now how does all this stuff works?

Well we have changed the output configuration of the project and so the output of the compilation step and the contents of the build directory will be different, as every generator has its own specific set of files:

  • build.ninja and rules.ninja: Contain all the build statements and build rules for Ninja.
  • CMakeCache.txt: CMake always generates its own cache in this file, regardless of the chosen generator.
  • CMakeFiles: Contains temporary files generated by CMake during configuration.
  • cmake_install.cmake: CMake script handling install rules and which is used at install time.

Next time we will be getting ourselves into building static and shared libraries.

--

--