A Simple Guide to Using CMake

๐Ÿ‘‰ Official Tutorial: https://cmake.org/cmake/help/latest/guide/tutorial/index.html

Why do we need CMake?

Although we already have Make, why should we use CMake?

1. Cross-platform support: It works not only on Linux but also on Windows, macOS, and other platforms.

2. Easy configuration: Describe the build process with simple scripts, avoiding the need to repeatedly write complex Makefiles.

3. Automated dependency management: Automatically updates build rules based on changes to source and header files.

4. Strong extensibility: Supports modular builds and management of large projects.

5. Good IDE integration: CMake can generate project files for various IDEs such as Visual Studio, Xcode, Ninja, etc.

6. Support for multiple compilers: Such as GCC, Clang, MSVC.

Alright, let’s first take a look at Make

Makefile syntax

target: dependencies          commands

Where:

ยท ($@ is the target)

ยท ($<): is the name of the first dependency file for the current rule (e.g., hello.cpp)

ยท %.o: %.cpp โ†’ Automatic generation rule

Code example

.PHONY: clean allCFLAGS = -std=c++14 -Wall -g -O2targets = mainsources = hello.cpp main.cppobjects = hello.o main.o
all: $(targets)          @echo Successful # @ indicates that the command will not print itself, only the output result$(targets): $(objects)          gcc $(objects) -o $@%.o: %.cpp          gcc $(CFLAGS) -c $&lt;clean:          rm *.o $(targets)

<span>.PHONY</span> indicates phony targets, telling <span>make</span>:

  • <span>clean</span> and <span>all</span> are not file names, but command targets.

  • Thus, even if there are files with the same name in the directory, it will not mistakenly think that the target already exists.

# Define clean target: clean up generated .o files and executable files.clean:      rm *.o $(targets)  

Execute the command make to generate the main executable file<code><span>Executing `</span>make clean` will execute๏ผšrm *.o ($targets)

Common compilation options:

  • -std=c++14 โ†’ Use C++14 standard

  • -Wall โ†’ Enable common warnings to help write safer code

  • -g โ†’ Enable debug symbols for easier gdb debugging

  • -O2 โ†’ Enable medium-level optimization to improve execution efficiency

Now let’s take a look at CMake

CMakeLists.txt file

cmake_minimum_required(VERSION 3.10)   # Set the minimum required version of CMakeproject(MyProject C CXX)               # Define project name and supported languageset(CMAKE_C_STANDARD 99)               # Specify C language standardset(CMAKE_CXX_STANDARD 17)             # Specify C++ language standard
add_executable(myapp main.cpp hello.cpp) # Define executable file and dependent source files# add_library(mylib STATIC lib.cpp)      # Define static library# add_library(mylib SHARED lib.cpp)    # Use SHARED to generate a dynamic library
# target_link_libraries(myapp PUBLIC mylib) # Link library to executable# target_include_directories(myapp PUBLIC include) # Specify header file search path include support

Run the command cmake -B build to generate a /build folder in the current directory

cmake -B build            # Create build folder and generate build files in the current directory

We can see the Makefile generated by cmake in the build folder, and we can build it using make

Other common options for targets

In addition to <span>target_include_directories</span>, CMake also provides many common options.<span>PUBLIC</span> and <span>PRIVATE</span> have the same meaning:

  • PUBLIC: Effective for the current target and any target that depends on it

  • PRIVATE: Effective only for the current target

Example:

target_include_directories(myapp PUBLIC /usr/include/eigen3) # Add header file search directorytarget_link_libraries(myapp PUBLIC hellolib)                 # Add libraries to linktarget_compile_definitions(yapp PUBLIC MY_MACRO=1)          # Add a macro definitiontarget_compile_definitions(myapp PUBLIC -DMY_MACRO=1)        # Equivalent writingtarget_compile_options(myapp PUBLIC -fopenmp)                # Add compiler command line optionstarget_sources(myapp PUBLIC hello.cpp other.cpp)             # Add source files to compile

Leave a Comment