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
## Basic Concepts
### Key Terms
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 Structure
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
# 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 Paquete
```cmake
# 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
$<$<CONFIG:Debug>:DEBUG_MODE>
$<$<CONFIG:Release>:RELEASE_MODE>
)
# Platform specific
target_compile_definitions(myapp PRIVATE
$<$<PLATFORM_ID:Windows>:WINDOWS_BUILD>
$<$<PLATFORM_ID:Linux>:LINUX_BUILD>
)
# Compiler specific
target_compile_options(myapp PRIVATE
$<$<CXX_COMPILER_ID:GNU>:-Wall>
$<$<CXX_COMPILER_ID:MSVC>:/W4>
)
```### Expresiones Generadoras Avanzadas
```cmake
# Target properties
target_include_directories(myapp PRIVATE
$<TARGET_PROPERTY:mylib,INTERFACE_INCLUDE_DIRECTORIES>
)
# Conditional linking
target_link_libraries(myapp
$<$<BOOL:$\\\\{BUILD_SHARED_LIBS\\\\}>:$\\\\{CMAKE_DL_LIBS\\\\}>
)
# File operations
target_sources(myapp PRIVATE
$<$<PLATFORM_ID:Windows>:windows_main.cpp>
$<$<PLATFORM_ID:Linux>:linux_main.cpp>
)
```## Uso de Línea de Comandos
### 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ón
```bash
# 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 Avanzado
```bash
# 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 Modernos
```cmake
# Use target-based approach
target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:$\\\\{CMAKE_CURRENT_SOURCE_DIR\\\\}/include>
$<INSTALL_INTERFACE: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 Errores
```cmake
# 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 Problemas
```bash
# 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](https://cmake.org/documentation/)
- **Tutorial de CMake**: [cmake.org/cmake/help/latest/guide/tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/)
- **CMake Moderno**: [cliutils.gitlab.io/modern-cmake](https://cliutils.gitlab.io/modern-cmake/)
- **Ejemplos de CMake**: [github.com/ttroy50/cmake-examples](https://github.com/ttroy50/cmake-examples)