CMake describes a build; a compiler produces the program
CMake is a build-system generator and a project-configuration tool. A CMakeLists.txt file describes targets, source files and build requirements. During configuration, CMake finds a compiler and generates files for a native build tool such as Ninja, Make or a Visual Studio solution. The native build tool then invokes the compiler and linker. CMake is not itself a C++ compiler, and an IDE such as CLion is another separate tool.
For a single main.cpp, a direct g++ or clang++ command is simpler and remains a good way to learn. CMake becomes useful when projects have several source files, libraries or platforms, because the build description records relationships that you would otherwise repeat in shell commands. This guide is an optional next step after your first program.
Choose the tools before configuring
Install a current supported CMake release from Kitware or your trusted platform package source and check cmake --version. You also need a working C++ compiler and a compatible native build tool or IDE generator. On Windows, Visual Studio with the Desktop development with C++ workload is one complete path; in its Developer Command Prompt the MSVC environment is available. On macOS use Apple Command Line Tools; on Linux use your distribution’s G++ or Clang packages.
If you use CLion, it bundles CMake for its own project workflow, so you may not need another copy solely for the IDE. A separate terminal command still needs cmake to be available there. Check the compiler reported by CMake at configure time, because a successful cmake --version check alone does not establish that a toolchain is installed.
Check the CMake command available in this terminal
cmake --versionCreate the source and CMakeLists.txt
Create a folder named hello-cmake containing main.cpp and CMakeLists.txt side by side. Save the complete greeting program below in main.cpp. Save the second block exactly as CMakeLists.txt, including its capital letters. Do not put these source files in build/: that directory is for generated output.
cmake_minimum_required(VERSION 3.16) states the oldest CMake version this small description is written for. project(HelloCpp LANGUAGES CXX) names the project and enables C++. add_executable(hello main.cpp) creates an executable target from main.cpp. target_compile_features(hello PRIVATE cxx_std_17) requires a compiler capable of at least C++17 for that target; CMake adds a standard flag when needed. It does not promise to force an exact C++17 mode if a compiler already defaults to a newer one.
main.cpp
#include <iostream>
int main() {
std::cout << "Hello, Codectionary!\n";
return 0;
}CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(HelloCpp LANGUAGES CXX)
add_executable(hello main.cpp)
target_compile_features(hello PRIVATE cxx_std_17)Configure a separate build directory
From hello-cmake/, run cmake -S . -B build. -S . points to the current source directory; -B build names a separate output directory. CMake reads CMakeLists.txt, checks the toolchain and generates the build system in build/. Read the configuration output to see which compiler and generator it selected. Configuration creates build instructions; it does not yet mean your C++ source has been compiled into the final program.
CMake chooses a default generator suited to the environment. A generator determines the native build files: for example, Ninja, Unix Makefiles or a Visual Studio solution. You can list locally available generators with cmake --help and select one using -G during a new configuration. An existing build directory remembers its generator and compiler; use a fresh build directory when changing either instead of mixing incompatible cached settings.
From the hello-cmake project folder
cmake -S . -B buildOptional: inspect generators available on this machine
cmake --helpBuild and find the executable
Run cmake --build build. CMake delegates to the generated native build tool, which compiles and links the hello target. On Linux and macOS with a typical single-configuration Make or Ninja generator, run ./build/hello. With a single-configuration Ninja generator on Windows PowerShell, the file is commonly .\build\hello.exe. A multi-configuration generator such as Visual Studio usually puts a Debug build under build\Debug\hello.exe; use cmake --build build --config Debug and run that file. Check the build output or build directory rather than assuming every generator uses the same path.
The terminal should print Hello, Codectionary!. Edit the message, save and run cmake --build build again before rerunning the executable. If a source file is missing from add_executable, CMake will not build it simply because it exists in the folder. CMake does not decide whether your program behaves correctly; verify the output yourself.
Build with the configured generator
cmake --build buildLinux or macOS with a single-configuration generator
./build/helloWindows PowerShell with a single-configuration generator
.\build\hello.exeWindows PowerShell with a Visual Studio Debug generator
cmake --build build --config Debug
.\build\Debug\hello.exeAdd files when the project grows
The optional CMakeLists.txt below builds the two-source-file greeting project from the project-structure guide. add_executable lists both .cpp definitions. target_include_directories gives this target the include/ header location; PRIVATE means that this path is needed while building hello and is not passed to other targets. The compiler still needs both sources, and a header alone cannot repair a missing definition. CMake can also describe a reusable library target and link it to an executable as a later step.
Keep build/ outside the editable source tree in your version-control ignore rules where appropriate. If CMake reports a missing compiler, fix the selected toolchain. If it reports that a source file does not exist, check its spelling and path in CMakeLists.txt. If the compiler reports a C++ error, correct the source. Each error belongs to a different stage.
Optional CMakeLists.txt for the project-structure guide
cmake_minimum_required(VERSION 3.16)
project(HelloProject LANGUAGES CXX)
add_executable(hello src/main.cpp src/greeting.cpp)
target_include_directories(hello PRIVATE include)
target_compile_features(hello PRIVATE cxx_std_17)Syntax
cmake_minimum_required(VERSION 3.16)
project(HelloCpp LANGUAGES CXX)
add_executable(hello main.cpp)
target_compile_features(hello PRIVATE cxx_std_17)Examples
A small C++17 executable target
Save beside main.cpp, then configure with cmake -S . -B build and compile with cmake --build build.
cmake_minimum_required(VERSION 3.16)
project(HelloCpp LANGUAGES CXX)
add_executable(hello main.cpp)
target_compile_features(hello PRIVATE cxx_std_17)- The goal is to describe one executable called hello without writing a platform-specific compiler command into the project.
- The first two commands set a supported CMake baseline and establish a C++ project. add_executable names the output target and its source file.
- target_compile_features asks the selected compiler for C++17 support for hello. CMake generates native build files; it does not execute C++ source itself.
- The matching main.cpp prints the greeting. Configure first, build second, then run the executable from the location used by your generator.
Best practices
- Learn a direct single-file compiler command before introducing a build system.
- Keep source and generated build directories separate.
- Inspect the selected compiler and generator, especially when switching tools or operating systems.
Runtime & versions
Compiled native applications. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
ISO C++ resources