---
name: build-errors-cpp
description: >
  Resolución de errores de compilación C++: g++/clang++, CMake, linker y
  templates. Incluye errores de ODR, ABI compatibility, headers no encontrados
  y mensajes de instanciación de templates.
  Cargar cuando un build C++ falle o haya errores de compilación o linkeo.
version: "1.0.0"
herramientasPermitidas: [Read, Bash, Grep]
exclusiones:
  - "No cargar para errores de runtime C++ (segfaults, memory leaks detectados en ejecución) — esos requieren herramientas como Valgrind, AddressSanitizer o GDB; no son errores de compilación."
  - "No cargar para diseñar la arquitectura del sistema de build CMake desde cero — si la pregunta es cómo estructurar un proyecto C++ multi-módulo con CMake, eso es diseño de proyecto, no diagnóstico de error."
  - "No cargar para errores de tests unitarios C++ (GoogleTest, Catch2 fallando) cuando el código ya compila — si `cmake --build` pasa pero los tests fallan en lógica, es un error de lógica, no de build."
  - "No cargar para configurar cross-compilation desde cero — elegir el toolchain file de CMake para ARM/WASM es configuración de entorno, no diagnóstico de error de compilación."
evolvable: true  # default para skill estandar
---
# Build Errors C++ — Diagnóstico y Solución

## Cuándo NO cargar

- El programa compila pero falla en ejecución (segfault, UB, leak) — esos son errores de runtime; usar Valgrind, ASAN o GDB.
- La pregunta es cómo estructurar un proyecto CMake con múltiples módulos — eso es diseño de proyecto, no diagnóstico.
- Los tests fallan en lógica (assertion failure) aunque el build pasa — no es un error de compilación.

## Cuándo cargar

- `g++`, `clang++` o `cmake --build` falla con errores del compilador
- Errores de linker (`undefined reference`, `multiple definition`)
- Mensajes de error de instanciación de templates (ilegibles por defecto)
- CMake no encuentra paquetes (`find_package` falla) o targets
- Errores de ODR (One Definition Rule) o incompatibilidad de ABI
- Headers no encontrados (`No such file or directory`)

---

## Compilador — Errores Más Frecuentes

### `undefined reference to X` (linker, no compilador)

**Causa**: el símbolo existe en la declaración (header) pero no se linka la librería
que contiene la implementación.

```cmake
# MAL — compilar sin linkear la libreria
add_executable(mi_app main.cpp)
# Si main.cpp usa pthread, math.h, etc.: falta linkear

# BIEN — linkear las librerias necesarias
add_executable(mi_app main.cpp)
target_link_libraries(mi_app PRIVATE pthread m)

# Para librerias del sistema encontradas con find_package:
find_package(OpenSSL REQUIRED)
target_link_libraries(mi_app PRIVATE OpenSSL::SSL OpenSSL::Crypto)
```

### `no matching function for call to X`

**Causa**: no existe ninguna sobrecarga de la función que coincida con los argumentos.

```cpp
// MAL
void procesar(int valor) { }
void procesar(std::string texto) { }

procesar(3.14);  // error: double no convierte a int ni string sin conversión explícita

// BIEN — conversión explícita o nueva sobrecarga
procesar(static_cast<int>(3.14));
procesar(std::to_string(3.14));

// MAL — pasar const ref donde se espera referencia mutable
void modificar(std::vector<int>& v) { v.push_back(1); }
const std::vector<int> datos = {1, 2, 3};
modificar(datos);  // error: no puede pasar const como non-const ref

// BIEN — revisar si la función debe ser const o los datos no deben serlo
void modificar(const std::vector<int>& v);  // si no modifica
```

### `use of undeclared identifier X`

**Causa**: header no incluido, nombre en namespace no calificado, o error tipográfico.

```cpp
// MAL
int main() {
    cout << "hola" << endl;  // error: cout no declarado sin using o std::
    vector<int> v;            // error: vector no declarado
}

// BIEN
#include <iostream>
#include <vector>

int main() {
    std::cout << "hola" << std::endl;
    std::vector<int> v;
}
```

---

## Templates — Descifrar Mensajes de Error

Los errores de templates son notorios por su verbosidad. Estrategia de lectura:

```
Regla: leer el ULTIMO bloque del error, no el primero.
El primer bloque es la cadena de instanciacion.
El ultimo bloque es el error real.
```

```cpp
// MAL — pasar tipo incorrecto a template con requisito implicito
template<typename T>
void ordenar(T& contenedor) {
    std::sort(contenedor.begin(), contenedor.end());
}

std::list<int> lista = {3, 1, 2};
ordenar(lista);  // error gigante: list no tiene random access iterators

// BIEN — agregar concepto/constraint en C++20
#include <concepts>
template<std::ranges::random_access_range T>
void ordenar(T& contenedor) {
    std::sort(contenedor.begin(), contenedor.end());
}
// Ahora el error es claro: "std::list does not satisfy random_access_range"
```

### Errores de implementación de templates en headers

```cpp
// MAL — implementación de template en .cpp (no se instancia en otros .cpp)
// mi_template.h
template<typename T>
class Contenedor {
    T valor;
public:
    T obtener();
};

// mi_template.cpp — PROBLEMA: nadie mas puede instanciar esto
template<typename T>
T Contenedor<T>::obtener() { return valor; }

// BIEN — implementación de templates SIEMPRE en el header o en .hpp incluido al final
// mi_template.h
template<typename T>
class Contenedor {
    T valor;
public:
    T obtener() { return valor; }  // definicion en el header
};
```

---

## CMake — Errores de Configuración

### `find_package(X REQUIRED) could not find X`

**Causa**: la librería no está instalada o CMake no sabe dónde buscarla.

```cmake
# Diagnostico: agregar HINTS o CMAKE_PREFIX_PATH
find_package(Boost REQUIRED COMPONENTS filesystem)
# Si falla, buscar con:
# cmake --find-package -DNAME=Boost -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST

# SOLUCION: indicar el prefijo de instalacion
cmake -DCMAKE_PREFIX_PATH=/usr/local/boost ..

# O en CMakeLists.txt para librerias no estandar:
list(APPEND CMAKE_PREFIX_PATH "/opt/custom_lib")
find_package(CustomLib REQUIRED)
```

### `target X not found`

**Causa**: `target_link_libraries` referencia un target que no existe con ese nombre exacto.

```cmake
# MAL — nombre de target incorrecto
find_package(OpenCV REQUIRED)
target_link_libraries(mi_app PRIVATE opencv)         # no existe
target_link_libraries(mi_app PRIVATE OpenCV)         # no existe
target_link_libraries(mi_app PRIVATE OpenCV_LIBS)    # no existe

# BIEN — usar el target namespace correcto del paquete
target_link_libraries(mi_app PRIVATE ${OpenCV_LIBS})
# O con targets modernos de CMake:
target_link_libraries(mi_app PRIVATE opencv_core opencv_imgproc)

# Para ver los targets disponibles de un paquete:
# cmake --find-package -DNAME=OpenCV -DMODE=COMPILE -DLANGUAGE=CXX -DCOMPILER_ID=GNU
```

---

## Linker — Errores Avanzados

### `multiple definition of X`

**Causa**: ODR violation — un símbolo definido en un header incluido en múltiples .cpp.

```cpp
// MAL — definición (no solo declaración) en header incluido en múltiples TUs
// utils.h
int calcular(int x) { return x * 2; }  // DEFINICION en header

// BIEN — opción 1: declarar en header, definir en .cpp
// utils.h
int calcular(int x);  // solo declaración

// utils.cpp
int calcular(int x) { return x * 2; }

// BIEN — opción 2: inline para definiciones en headers
// utils.h
inline int calcular(int x) { return x * 2; }

// BIEN — opción 3: static para limitar a la TU (si es intencional)
// utils.h
static int calcular(int x) { return x * 2; }
```

### ABI incompatibility — símbolos raros en errores de linker

```bash
# Sintoma: undefined reference con nombres mangleados como:
# _ZN3Foo3barEv  (C++ mangled name)
# vs
# _foo_bar       (C mangled name)

# Causa: mezclar C y C++ sin extern "C"
# En el header de la libreria C:
#ifdef __cplusplus
extern "C" {
#endif

void funcion_c(int param);

#ifdef __cplusplus
}
#endif
```

---

## Gotchas / Errores comunes no obvios

- **El último bloque del error de template es lo relevante, pero los desarrolladores leen el primero**: con errores de instanciación de templates, g++ imprime una cadena de "required from" de decenas de líneas antes del error real. Causa: el error real está al final de la cadena de instanciación. Solución: ir directamente al último bloque del output del compilador — es el lugar exacto donde el constraint se viola, no las invocaciones intermedias.
- **`-fsanitize=address` no detecta la corrupción de memoria que rompe el build en CI**: el sanitizer detecta la corrupción en runtime pero el bug es un ODR que solo aparece al linkear múltiples TUs. Causa: `nm -C archivo.o | grep símbolo` en dos objetos muestra la misma función definida en ambos, causando `multiple definition`. Solución: compilar con `g++ -fsanitize=address` + `-fsanitize=undefined` en modo debug y buscar el símbolo duplicado con `nm`; la solución es `inline` o mover la implementación al .cpp.
- **`target_link_libraries(mi_app OpenCV)` falla pero el nombre del paquete es correcto**: CMake exporta targets con namespace (ej: `opencv_core`, no `OpenCV`). Causa: los paquetes modernos de CMake exportan targets como `PkgName::Component`, no el nombre del paquete en mayúsculas. Solución: después de `find_package(OpenCV REQUIRED)` ejecutar `cmake --find-package -DNAME=OpenCV -DMODE=COMPILE -DLANGUAGE=CXX -DCOMPILER_ID=GNU` para ver los targets reales exportados.
- **Headers en subdirectorio incluidos con path relativo compilan localmente pero fallan en CI**: el CI construye desde un directorio diferente y el path relativo en `#include "../../utils/helper.h"` apunta a otro lugar. Causa: paths relativos en `#include` dependen del directorio de trabajo y de la estructura de `include_directories`. Solución: usar `target_include_directories(mi_app PRIVATE ${CMAKE_SOURCE_DIR}/utils)` y en el .cpp incluir con `#include "helper.h"` sin paths relativos.

## Checklist de Diagnóstico

- [ ] Separar errores del compilador de errores del linker: compilador = fase de traducción, linker = fase de enlace.
- [ ] Para templates: leer el último bloque del error, ignorar la cadena de instanciación inicial.
- [ ] `g++ -v` o `clang++ -v` para ver flags exactos que se pasan al compilador.
- [ ] `nm -C archivo.o | grep simbolo` para verificar si un símbolo está en el objeto.
- [ ] `cmake --build . --verbose` para ver los comandos exactos de compilación.
- [ ] Usar `-fdiagnostics-color=always` para mensajes de error más legibles.
- [ ] Para ODR: compilar con `-fsanitize=address` y `-fno-inline` puede revelar violaciones.
- [ ] `c++filt _ZN3Foo3barEv` para demanglear símbolos de C++ en errores de linker.
- [ ] Verificar que todos los .cpp del proyecto están incluidos en `CMakeLists.txt`.
