find_package(OpenCV REQUIRED) # REQUIRED asegura que el paquete sea obligatorio
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
# Con estas líneas, el proyecto puede utilizar las funcionalidades de OpenCV.
La documentación oficial de CMake describe la sintaxis completa de find_package() de la siguiente manera:
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
[GLOBAL]
[NO_POLICY_SCOPE]
[BYPASS_PROVIDER])
Los parámetros entre corchetes [] son opcionales. A continuación, explicaremos el mecanismo interno de find_package().
Cómo Opera find_package()
En esencia, cuando se ejecuta find_package(<NombrePaquete>), CMake busca en rutas predefindias una serie de archivos con nombres específicos:
Find<NombrePaquete>.cmake<NombrePaquete>Config.cmake<nombrepaqueteenminúsculas>-config.cmake<nombrepaqueteenminúsculas>-config-version.cmake(para información de versión)<NombrePaquete>ConfigVersion.cmake(para información de versión)
Estos archivos .cmake son scripts escritos en el lenguaje de CMake. Su propósito es definir variables clave, como <NombrePaquete>_INCLUDE_DIRS y <NombrePaquete>_LIBRARIES. Una vez que find_package() localiza y procesa uno de estos archivos, las variables definidas en él se integran en el entorno CMake actual.
Para buscar estos archivos .cmake, find_package() emplea dos estrategias distintas.
Modo de Módulo de find_package()
En este modo, CMake busca un archivo llamado Find<NombrePaquete>.cmake. Primero, la búsqueda se realiza en las rutas especificadas por la variable CMAKE_MODULE_PATH. Si no se encuentra allí, continúa buscando entre los módulos Find que vienen instalados con CMake. Si se localiza el archivo, CMake lo lee y lo procesa. Este script es responsable de encontrar el paquete, verificar la versión (si aplica) y generar los mensajes pertinantes. Es importante tener en cuenta que algunos módulos Find ofrecen un soporte limitado o nulo para el control de versiones; siempre es recomendable consultar la documentación específica del módulo.
Los archivos FindXXX.cmake son generalmente proporcionados por CMake o creados por los usuarios, y no directamente por el paquete de terceros (que a menudo ofrece archivos XXXConfig.cmake, como se verá más adelante). Representan una forma más simple de localización. CMake prioriza la búsqueda en CMAKE_MODULE_PATH (que por defecto suele estar vacío) y luego en sus propios módulos Find. Puedes listar los módulos integrados de CMake con cmake --help-module-list.
Para paquetes ligeros que no proporcionan sus propios archivos de configuración (XXXConfig.cmake o FindXXX.cmake) y que quizás usen otros sistemas de gestión como pkg-config, es común que el desarrollador cree un archivo FindXXX.cmake personalizado. Alternativamente, se puede usar pkg_check_modules() directamente en CMake. A continuación, se muestra un ejemplo simplificado de un archivo FindFFMPEG.cmake para la biblioteca FFmpeg:
# FindFFMPEG.cmake
# Define la ubicación base de la instalación de FFmpeg
set(RUTA_BASE_FFMPEG "/opt/ffmpeg/4.4")
# Define las rutas de inclusión y librerías
set(FFMPEG_RUTAS_INCLUIDAS ${RUTA_BASE_FFMPEG}/include)
set(FFMPEG_RUTAS_LIBRERIAS ${RUTA_BASE_FFMPEG}/lib)
# Busca las librerías individuales
find_library(FFMPEG_LIB_AVCODEC NAMES avcodec HINTS ${FFMPEG_RUTAS_LIBRERIAS})
find_library(FFMPEG_LIB_AVFORMAT NAMES avformat HINTS ${FFMPEG_RUTAS_LIBRERIAS})
find_library(FFMPEG_LIB_AVUTIL NAMES avutil HINTS ${FFMPEG_RUTAS_LIBRERIAS})
find_library(FFMPEG_LIB_SWSCALE NAMES swscale HINTS ${FFMPEG_RUTAS_LIBRERIAS})
find_library(FFMPEG_LIB_SWRESAMPLE NAMES swresample HINTS ${FFMPEG_RUTAS_LIBRERIAS})
# Combina todas las librerías encontradas en una sola variable
set(FFMPEG_DEPENDENCIAS ${FFMPEG_LIB_AVCODEC} ${FFMPEG_LIB_AVFORMAT}
${FFMPEG_LIB_AVUTIL} ${FFMPEG_LIB_SWSCALE}
${FFMPEG_LIB_SWRESAMPLE})
# Si todas las librerías esenciales se encontraron, marca el paquete como encontrado
if (FFMPEG_LIB_AVCODEC AND FFMPEG_LIB_AVFORMAT AND FFMPEG_LIB_AVUTIL)
set(FFMPEG_FOUND TRUE)
endif()
# Mensajes de depuración (opcional)
if (NOT FFMPEG_FOUND)
message(STATUS "FFmpeg no encontrado en ${RUTA_BASE_FFMPEG}.")
endif()
Como se observa, este script se encarga de definir variables que apuntan a las rutas de cabecera y librerías de FFmpeg, utilizando find_library() para localizar los archivos de biblioteca individuales.
Para usar este módulo, se puede especificar su ubicación a través de CMAKE_MODULE_PATH. Si el script está en el directorio actual del proyecto, se usaría:
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}")
find_package(FFMPEG REQUIRED)
# Ahora se pueden usar ${FFMPEG_RUTAS_INCLUIDAS} y ${FFMPEG_DEPENDENCIAS}
Modo de Configuración de find_package()
En este modo, CMake busca archivos denominados <nombrepaqueteenminúsculas>-config.cmake o <NombrePaquete>Config.cmake. Si se especifica información de versión, también buscará <nombrepaqueteenminúsculas>-config-version.cmake o <NombrePaquete>ConfigVersion.cmake (para detalles, consulte la documentación sobre la selección de versiones). A diferencia del modo módulo, el modo de configuración permite proporcionar una lista de nombres de paquetes para buscar. Las ubicaciones de búsqueda en este modo son considerablemente más complejas y extensas.
Los archivos de configuración y versión son comúnmente instalados como parte del paquete de software, lo que los hace generalmente más robustos que los módulos Find. Estos archivos suelen contener conocimiento directo sobre el contenido del paquete, eliminando la necesidad de búsquedas o heurísticas dentro de los propios archivos de configuración.
Cuando el modo módulo no encuentra el paquete, CMake automáticamente intenta el modo de configuración. Este modo es muy exhaustivo en su búsqueda. Algunos de los métodos de búsqueda más comunes y comprensibles incluyen:
- Búsqueda de
<NombrePaquete>Config.cmakeen la ruta especificada por la varible o variable de entorno<NombrePaquete>_DIR. - Búsqueda en las rutas listadas en
CMAKE_PREFIX_PATH. - Búsqueda en las rutas definidas en la variable de entorno
PATH. - ... y varias otras rutas estándar del sistema.
Las opciones CMAKE_PREFIX_PATH y PATH permiten especificar una ruta de prefijo donde CMake buscará subdirectorios que puedan contener los archivos de configuración. La regla de coincidencia de prefijos es la siguiente:
<prefijo>/(lib/|lib<arch>/|share/|)/cmake/<nombre>*/
<prefijo>/(lib/|lib<arch>/|share/|)/<nombre>*/
<prefijo>/(share/<nombre>*|<nombre>*)/
Donde <prefijo> es la ruta raíz especificada. CMake iterará a través de estas subrutas. Por ejemplo, para find_package(OpenCV), si PATH incluye /usr/lib/x86_64-linux-gnu/, CMake buscará en rutas como:
/usr/lib/x86_64-linux-gnu/cmake/OpenCV//usr/lib/x86_64-linux-gnu/OpenCV//usr/lib/x86_64-linux-gnu/share/OpenCV/- ... y sus variantes con minúsculas o versiones (ej.
opencv4.5).
El parámetro <name>* se corresponde con el <PackageName> de find_package(), ignorando mayúsculas/minúsculas y permitiendo sufijos (ej. opencv4.5). | indica una opción alternativa, y <arch> se refiere a la arquitectura del sistema (ej. x86_64-linux-gnu o aarch64-linux-gnu).
Uso Flexible de find_package()
Para módulos FindXXX.cmake personalizados:
# Si el módulo está en el directorio de código fuente actual
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}")
# O si está en una ruta específica
set(RUTA_MODULO_PERSONALIZADO "/rutas/mis_modulos_find")
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${RUTA_MODULO_PERSONALIZADO}")
find_package(MiBibliotecaCustom REQUIRED)
Para bibliotecas de terceros que proporcionan archivos de configuración:
find_package(OpenCV REQUIRED) # CMake buscará automáticamente
Si find_package() no encuentra la biblioteca automáticamente, puedes localizar manualmente el archivo de configuración (ej. OpenCVConfig.cmake) y especificar su directorio:
# En la línea de comandos (ejemplo Linux)
# locate OpenCVConfig.cmake
# Salida: /ruta/a/opencv/build/OpenCVConfig.cmake
# En tu CMakeLists.txt
set(OpenCV_DIR "/ruta/a/opencv/build") # Define el directorio que contiene OpenCVConfig.cmake
find_package(OpenCV REQUIRED)
Para proyectos con múltiples versiones o configuraciones de una biblioteca (como Qt), se puede usar CMAKE_PREFIX_PATH para indicar los directorios raíz donde se encuentran las instalaciones:
# Ejemplo para Qt:
# Supongamos que Qt 5.15.2 está instalado en /opt/Qt/5.15.2/gcc_64
set(CMAKE_PREFIX_PATH "/opt/Qt/5.15.2/gcc_64")
# Si se tienen múltiples versiones y se desea buscar en ambas
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};/opt/Qt/5.14.0/gcc_64")
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};/opt/Qt/5.15.2/gcc_64")
# Luego, se puede especificar la versión deseada:
find_package(Qt5 5.15.2 COMPONENTS Core Widgets REQUIRED)
# O para una versión diferente:
# find_package(Qt5 5.14.0 COMPONENTS Core Widgets REQUIRED)
# Utiliza la opción EXACT para requerir una coincidencia de versión precisa
find_package(Qt5 5.15.2 EXACT COMPONENTS Core Widgets REQUIRED)