Saltar a contenido

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

```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 \(<\):DEBUG_MODE> \(<\):RELEASE_MODE> )

Platform specific

target_compile_definitions(myapp PRIVATE \(<\):WINDOWS_BUILD> \(<\):LINUX_BUILD> )

Compiler specific

target_compile_options(myapp PRIVATE \(<\):-Wall> \(<\):/W4> ) ### Expresiones Generadoras Avanzadascmake

Target properties

target_include_directories(myapp PRIVATE $ )

Conditional linking

target_link_libraries(myapp \(<\)\(\\\\{BUILD_SHARED_LIBS\\\\}>:\)\\\\{CMAKE_DL_LIBS\\\\}> )

File operations

target_sources(myapp PRIVATE \(<\):windows_main.cpp> \(<\):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ó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