Hoja de referencia de CMake¶
Descripción general¶
CMake es un generador de sistemas de compilación multiplataforma que utiliza archivos de configuración independientes de la plataforma para generar archivos de herramientas de compilación nativos (Makefiles, proyectos de Visual Studio, proyectos de Xcode, etc.).
Instalación¶
Gestores de paquetes¶
Would you like me to continue with the remaining sections? Please provide the specific texts you want me to translate.```bash
Ubuntu/Debian¶
sudo apt install cmake
macOS¶
brew install cmake
CentOS/RHEL¶
sudo yum install cmake
Windows (Chocolatey)¶
choco install cmake
From source¶
wget https://cmake.org/files/v3.25/cmake-3.25.0.tar.gz tar -xzf cmake-3.25.0.tar.gz cd cmake-3.25.0 && ./bootstrap && make && sudo make install
CMakeLists.txt # Configuration file Target # Executable, library, or custom target Generator # Tool that creates build files Cache # Stored configuration variables Out-of-source # Build directory separate from source project/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ └── utils.cpp ├── include/ │ └── utils.h └── build/ # Out-of-source build directory## Basic CMakeLists.txt
### Minimal Example
```cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)
set(CMAKE_CXX_STANDARD 17)
add_executable(myapp main.cpp)
Simple Library¶
cmake_minimum_required(VERSION 3.10)
project(MyProject VERSION 1.0.0)
# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Add library
add_library(mylib utils.cpp network.cpp)
# Add executable
add_executable(myapp main.cpp)
# Link library to executable
target_link_libraries(myapp mylib)
Variables¶
Built-in Variables¶
# Project information
$\\\\{PROJECT_NAME\\\\}
$\\\\{PROJECT_VERSION\\\\}
$\\\\{PROJECT_SOURCE_DIR\\\\}
$\\\\{PROJECT_BINARY_DIR\\\\}
# System information
$\\\\{CMAKE_SYSTEM_NAME\\\\} # Linux, Windows, Darwin
$\\\\{CMAKE_SYSTEM_VERSION\\\\}
$\\\\{CMAKE_SYSTEM_PROCESSOR\\\\}
# Compiler information
$\\\\{CMAKE_CXX_COMPILER\\\\}
$\\\\{CMAKE_CXX_COMPILER_ID\\\\} # GNU, Clang, MSVC
$\\\\{CMAKE_CXX_COMPILER_VERSION\\\\}
# Build information
$\\\\{CMAKE_BUILD_TYPE\\\\} # Debug, Release, RelWithDebInfo
$\\\\{CMAKE_CURRENT_SOURCE_DIR\\\\}
$\\\\{CMAKE_CURRENT_BINARY_DIR\\\\}
Setting Variables¶
# Set variable
set(SOURCES main.cpp utils.cpp)
set(MY_VAR "value")
# List operations
list(APPEND SOURCES network.cpp)
list(REMOVE_ITEM SOURCES main.cpp)
list(LENGTH SOURCES NUM_SOURCES)
# String operations
string(TOUPPER $\\\\{PROJECT_NAME\\\\} PROJECT_NAME_UPPER)
string(REPLACE "old" "new" NEW_STRING $\\\\{OLD_STRING\\\\})
# Cache variables
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries")
Targets¶
Executables¶
# Simple executable
add_executable(myapp main.cpp)
# Executable with multiple sources
add_executable(myapp
main.cpp
utils.cpp
network.cpp
)
# Executable with variable sources
set(SOURCES main.cpp utils.cpp)
add_executable(myapp $\\\\{SOURCES\\\\})
Libraries¶
# Static library
add_library(mylib STATIC utils.cpp network.cpp)
# Shared library
add_library(mylib SHARED utils.cpp network.cpp)
# Header-only library
add_library(mylib INTERFACE)
target_include_directories(mylib INTERFACE include/)
# Object library
add_library(mylib OBJECT utils.cpp network.cpp)
add_executable(myapp main.cpp $<TARGET_OBJECTS:mylib>)
Target Properties¶
# Set target properties
set_target_properties(myapp PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
OUTPUT_NAME "my_application"
)
# Include directories
target_include_directories(myapp
PRIVATE include/
PUBLIC $\\\\{CMAKE_CURRENT_SOURCE_DIR\\\\}/public_include/
)
# Compile definitions
target_compile_definitions(myapp
PRIVATE DEBUG_MODE
PUBLIC API_VERSION=2
)
# Compile options
target_compile_options(myapp
PRIVATE -Wall -Wextra
PUBLIC -fPIC
)
# Link libraries
target_link_libraries(myapp
PRIVATE mylib
PUBLIC pthread
)
Finding Packages¶
find_package¶
# Find required package
find_package(Threads REQUIRED)
target_link_libraries(myapp Threads::Threads)
# Find optional package
find_package(OpenSSL)
if(OpenSSL_FOUND)
target_link_libraries(myapp OpenSSL::SSL OpenSSL::Crypto)
target_compile_definitions(myapp PRIVATE HAVE_OPENSSL)
endif()
# Find package with components
find_package(Boost REQUIRED COMPONENTS system filesystem)
target_link_libraries(myapp Boost::system Boost::filesystem)
# Find package with version
find_package(Qt5 5.10 REQUIRED COMPONENTS Core Widgets)
target_link_libraries(myapp Qt5::Core Qt5::Widgets)
pkg-config¶
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
target_include_directories(myapp PRIVATE $\\\\{GTK3_INCLUDE_DIRS\\\\})
target_link_libraries(myapp $\\\\{GTK3_LIBRARIES\\\\})
target_compile_options(myapp PRIVATE $\\\\{GTK3_CFLAGS_OTHER\\\\})
Conditional Logic¶
if/else/endif¶
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(myapp PRIVATE DEBUG_MODE)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
target_compile_definitions(myapp PRIVATE RELEASE_MODE)
endif()
# Platform-specific code
if(WIN32)
target_sources(myapp PRIVATE windows_specific.cpp)
elseif(UNIX)
target_sources(myapp PRIVATE unix_specific.cpp)
endif()
# Compiler-specific options
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(myapp PRIVATE -Wall -Wextra)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(myapp PRIVATE /W4)
endif()
option¶
option(BUILD_TESTS "Build test programs" ON)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
Functions and Macros¶
Functions¶
function(add_my_executable name)
add_executable($\\\\{name\\\\} $\\\\{ARGN\\\\})
target_compile_features($\\\\{name\\\\} PRIVATE cxx_std_17)
target_compile_options($\\\\{name\\\\} PRIVATE -Wall -Wextra)
endfunction()
# Usage
add_my_executable(myapp main.cpp utils.cpp)
Macros¶
macro(set_default_build_type)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
endif()
endmacro()
# Usage
set_default_build_type()
Advanced Functions¶
function(add_library_with_alias target_name)
set(options SHARED STATIC)
set(oneValueArgs ALIAS)
set(multiValueArgs SOURCES HEADERS)
cmake_parse_arguments(ARG "$\\\\{options\\\\}" "$\\\\{oneValueArgs\\\\}" "$\\\\{multiValueArgs\\\\}" $\\\\{ARGN\\\\})
if(ARG_SHARED)
add_library($\\\\{target_name\\\\} SHARED $\\\\{ARG_SOURCES\\\\})
else()
add_library($\\\\{target_name\\\\} STATIC $\\\\{ARG_SOURCES\\\\})
endif()
if(ARG_ALIAS)
add_library($\\\\{ARG_ALIAS\\\\} ALIAS $\\\\{target_name\\\\})
endif()
endfunction()
# Usage
add_library_with_alias(mylib
SHARED
ALIAS MyNamespace::mylib
SOURCES utils.cpp network.cpp
)
Testing¶
CTest Integration¶
enable_testing()
# Add test executable
add_executable(test_utils test_utils.cpp)
target_link_libraries(test_utils mylib)
# Add test
add_test(NAME test_utils COMMAND test_utils)
# Test with arguments
add_test(NAME test_with_args COMMAND myapp --test --verbose)
# Test properties
set_tests_properties(test_utils PROPERTIES
TIMEOUT 30
WORKING_DIRECTORY $\\\\{CMAKE_CURRENT_BINARY_DIR\\\\}
)
Google Test Integration¶
find_package(GTest REQUIRED)
add_executable(unit_tests
test_main.cpp
test_utils.cpp
)
target_link_libraries(unit_tests
mylib
GTest::GTest
GTest::Main
)
# Discover tests automatically
include(GoogleTest)
gtest_discover_tests(unit_tests)
Installation¶
Basic Installation¶
```cmake
Install executable¶
install(TARGETS myapp RUNTIME DESTINATION bin )
Install library¶
install(TARGETS mylib LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin )
Install headers¶
install(DIRECTORY include/ DESTINATION include FILES_MATCHING PATTERN "*.h" )
Install files¶
install(FILES config.txt
DESTINATION etc
)
### Configuración del Paquetecmake
Generate package config files¶
include(CMakePackageConfigHelpers)
Create config file¶
configure_package_config_file( $\\{CMAKE_CURRENT_SOURCE_DIR\\}/Config.cmake.in $\\{CMAKE_CURRENT_BINARY_DIR\\}/MyProjectConfig.cmake INSTALL_DESTINATION lib/cmake/MyProject )
Create version file¶
write_basic_package_version_file( $\\{CMAKE_CURRENT_BINARY_DIR\\}/MyProjectConfigVersion.cmake VERSION $\\{PROJECT_VERSION\\} COMPATIBILITY SameMajorVersion )
Install config files¶
install(FILES $\\{CMAKE_CURRENT_BINARY_DIR\\}/MyProjectConfig.cmake $\\{CMAKE_CURRENT_BINARY_DIR\\}/MyProjectConfigVersion.cmake DESTINATION lib/cmake/MyProject )
Export targets¶
install(EXPORT MyProjectTargets FILE MyProjectTargets.cmake NAMESPACE MyProject:: DESTINATION lib/cmake/MyProject ) ```## Expresiones Generadoras
Expresiones Generadoras Básicas¶
```cmake
Build type specific¶
target_compile_definitions(myapp PRIVATE
\(<\)
Platform specific¶
target_compile_definitions(myapp PRIVATE
\(<\)
Compiler specific¶
target_compile_options(myapp PRIVATE
\(<\)### Expresiones Generadoras Avanzadascmake
Target properties¶
target_include_directories(myapp PRIVATE
$
Conditional linking¶
target_link_libraries(myapp
\(<\)
File operations¶
target_sources(myapp PRIVATE
\(<\)
Comandos Básicos¶
```bash
Configure (generate build files)¶
cmake -S . -B build
Build¶
cmake --build build
Install¶
cmake --install build
Test¶
cd build && ctest
Clean¶
cmake --build build --target clean
### Opciones de Configuraciónbash
Set build type¶
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
Set variables¶
cmake -S . -B build -DBUILD_TESTS=ON -DBUILD_SHARED_LIBS=ON
Set generator¶
cmake -S . -B build -G "Unix Makefiles" cmake -S . -B build -G "Ninja" cmake -S . -B build -G "Visual Studio 16 2019"
Set toolchain¶
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
Parallel build¶
cmake --build build --parallel 4
cmake --build build -j 4
### Uso Avanzadobash
Configure with preset¶
cmake --preset=default
Build specific target¶
cmake --build build --target myapp
Install to custom prefix¶
cmake --install build --prefix /opt/myapp
Run specific test¶
cd build && ctest -R test_utils
Verbose output¶
cmake --build build --verbose ctest --verbose ```## Desarrollo Multiplataforma
Detección de Plataforma¶
cmake
if(WIN32)
# Windows-specific code
target_compile_definitions(myapp PRIVATE PLATFORM_WINDOWS)
elseif(APPLE)
# macOS-specific code
target_compile_definitions(myapp PRIVATE PLATFORM_MACOS)
elseif(UNIX)
# Linux/Unix-specific code
target_compile_definitions(myapp PRIVATE PLATFORM_LINUX)
endif()### Archivos de Cadena de Herramientas
```cmake
toolchain-mingw.cmake¶
set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Usage¶
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=toolchain-mingw.cmake ```## Mejores Prácticas
Estructura del Proyecto¶
```cmake cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0.0 DESCRIPTION "My awesome project" LANGUAGES CXX )
Only do these if this is the main project¶
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(CMAKE_CXX_EXTENSIONS OFF) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
include(CTest)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
endif()
Add subdirectories¶
add_subdirectory(src)
add_subdirectory(external)
### Patrones de CMake Modernoscmake
Use target-based approach¶
target_include_directories(mylib PUBLIC
\(<BUILD_INTERFACE:\)\\{CMAKE_CURRENT_SOURCE_DIR\\}/include>
$
Use imported targets¶
find_package(Threads REQUIRED) target_link_libraries(myapp PRIVATE Threads::Threads)
Use generator expressions¶
target_compile_features(myapp PRIVATE cxx_std_17)
Avoid global commands¶
Don't use: include_directories(), link_directories(), add_definitions()¶
Use target-specific commands instead¶
### Manejo de Errorescmake
Check CMake version¶
cmake_minimum_required(VERSION 3.15)
Validate variables¶
if(NOT DEFINED PROJECT_VERSION) message(FATAL_ERROR "PROJECT_VERSION must be defined") endif()
Check for required files¶
if(NOT EXISTS "$\\{CMAKE_CURRENT_SOURCE_DIR\\}/src/main.cpp") message(FATAL_ERROR "main.cpp not found") endif()
Validate options¶
if(BUILD_TYPE AND NOT BUILD_TYPE MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)$") message(FATAL_ERROR "Invalid BUILD_TYPE: $\\{BUILD_TYPE\\}") endif() ```## Depuración
Salida de Depuración¶
```cmake
Print variables¶
message(STATUS "CMAKE_BUILD_TYPE: $\\{CMAKE_BUILD_TYPE\\}") message(STATUS "CMAKE_CXX_COMPILER: $\\{CMAKE_CXX_COMPILER\\}")
Print all variables¶
get_cmake_property(_variableNames VARIABLES) foreach(_variableName \(\\\\{_variableNames\\\\}) message(STATUS "\)\\{_variableName\\}=\(\\\\{\)\\{_variableName\\}\\}") endforeach()
Print target properties¶
get_target_property(MYAPP_SOURCES myapp SOURCES)
message(STATUS "myapp sources: $\\{MYAPP_SOURCES\\}")
### Resolución de Problemasbash
Verbose makefile¶
cmake -S . -B build -DCMAKE_VERBOSE_MAKEFILE=ON
Debug find_package¶
cmake -S . -B build --debug-find
Trace execution¶
cmake -S . -B build --trace
Debug output¶
cmake -S . -B build --debug-output ```## Recursos
- Documentación Oficial: cmake.org/documentation
- Tutorial de CMake: cmake.org/cmake/help/latest/guide/tutorial
- CMake Moderno: cliutils.gitlab.io/modern-cmake
- Ejemplos de CMake: github.com/ttroy50/cmake-examples