Trabajar con objetivos

Visión general

Enseñanza: 10 min
Ejercicios: 15 min
Preguntas

  • ¿Cómo funcionan los objetivos?

Objetivos

  • Saber cómo configurar objetivos

  • Entender la vinculación y propiedades de la INTERFAZ

  • Hacer INTERFAZ de objetivos

Ahora usted sabe cómo compilar un archivo único con tres líneas de CMake. Pero, ¿qué sucede si tiene más de un archivo con dependencias? Necesitas ser capaz de decirle a CMake sobre la estructura de tu proyecto, y te ayudará a construirlo. Para hacerlo, necesitarás objetivos.

ya hemos visto una meta:

add_executable(myexample simple.cpp)

Esto crea un «ejecutable» de destino con el nombre myexample. Los nombres de destino deben ser únicos (y hay una manera de establecer el nombre del ejecutable a algo que no sea el nombre de destino si realmente lo desea).

Los objetivos se parecen mucho a los «objetos» en otros idiomas; tienen propiedades (variables de miembro) que contienen información. La propiedad SOURCES, por ejemplo, tendrá simple.cpp en ella.

Otro tipo de destino es una biblioteca:

add_library(mylibrary simplelib.cpp)

Puede agregar las palabras clave STATICSHARED, o MODULEsi sabe qué tipo de biblioteca desea crear; el valor predeterminado es una biblioteca «automática» que puede seleccionarse por el usuario con BUILD_SHARED_LIBS.

También puede crear bibliotecas no construidas. Más sobre eso más adelante, una vez que veamos qué podemos hacer con los objetivos.

la Vinculación

una Vez que tenga varios objetivos, se puede describir la relación entre ellas con la etiquetatarget_link_libraries y una palabra clave; uno de PUBLICPRIVATE y INTERFACE. ¡No olvide esta palabra clave al hacer una biblioteca! CMake entra en un antiguo modo de compatibilidad para este objetivo que generalmente rompe cosas.

Pregunta

dispone de una biblioteca, my_lib, hecho de my_lib.hpp y my_lib.cpp. Se requiere al menos C++14 para compilar. Si luego agrega my_exe, y necesita my_lib, ¿debería forzar a my_exe a compilarse con C++14 o superior?

Respuesta

Esto depende de la cabecera. Si el encabezado contiene C++14, este es un requisito PÚBLICO, tanto la biblioteca como sus usuarios lo necesitan. Sin embargo, si el encabezado es válido en todas las versiones de C++, y solo las implementaciones dentro de my_lib.cpp requieren C++14, entonces esto es un PRIVATE requisito

  • los usuarios no necesitan ser forzados al modo C++14.

Tal vez necesite que los usuarios tengan C++14, pero su biblioteca puede compilar con cualquier versión de C++.Este sería un requisito INTERFACE.

Ejemplo de lo Público y lo Privado herencia

la Figura 1: Ejemplo de PÚBLICO, PRIVADO e INTERFAZ. myprogram construirá las tres bibliotecas a través de mylibrary; la biblioteca privada no la afectará.

Hay dos colecciones de propiedades en cada destino que se pueden rellenar con valores; las propiedades»privadas» controlan lo que sucede cuando se compila ese destino, y las propiedades de «interfaz» indican los destinos vinculados a este qué hacer al compilar. La palabra clave PUBLIC llena ambos campos de propiedades al mismo tiempo.

Ejemplo 1: Incluir directorios

Cuando se ejecuta , la propiedad INCLUDE_DIRECTORIES de TargetAtiene mydir anexada. Si utiliza la palabra claveINTERFACE en su lugar, entonces INTERFACE_INCLUDE_DIRECTORIES se añade a, en su lugar. Si utilizasPUBLIC, entonces ambas propiedades se anexan al mismo tiempo.

Ejemplo 2: Estándar de C++

Hay una propiedad estándar de C++ – CXX_STANDARD. Puede establecer esta propiedad, y al igual que muchas propiedades en CMake, obtiene su valor predeterminado de una variable CMAKE_CXX_STANDARD si está establecida,pero no hay una versión de INTERFAZ; no puede forzar una variable CXX_STANDARD a través de un destino. ¿Qué haría si tuviera un destino de interfaz C++11 y un destino de interfaz C++14 y estuviera vinculado a ambos?

Por cierto, hay una manera de manejar esto: puede especificar las características de compilación mínimas que necesita para compilar un destino; el cxx_std_11 y metaracterísticas similares son perfectos para esto: su objetivo se compilará con al menos el nivel más alto especificado, a menos que CXX_STANDARD esté establecido (y eso es un error agradable y claro si establece CXX_STANDARD demasiado bajo). target_compile_features puede rellenarCOMPILE_FEATURESy INTERFACE_COMPILE_FEATURES, al igual que los directorios del ejemplo 1.

Pruébelo

Obtenga este repositorio y vaya al ejemplo. Intenta escribir una lista de CMakeLists que se construya correctamente.

git clone https://github.com/hsf-training/hsf-training-cmake-webpage.gitcd hsf-training-cmake-webpage/code/01-simple

Los archivos aquí son:

  • simple_lib.cpp: Debe compilarse con MYLIB_PRIVATE y MYLIB_PUBLIC definidos.
  • simple_example.cpp: Debe compilarse con MYLIB_PUBLIC definido, pero no MYLIB_PRIVATE

Use para establecer las definiciones en simple_lib.

Cosas que puede establecer en destinos

  • target_link_libraries: Otros destinos; también puede pasar nombres de biblioteca directamente
  • target_include_directories: Include directories
  • target_compile_features: The compiler features you need activated, like cxx_std_11
  • target_compile_definitions: Definitions
  • target_compile_options: More general compile flags
  • target_link_directories: Don’t use, give full paths instead (CMake 3.13+)
  • target_link_options: General link flags (CMake 3.13+)
  • target_sources: Add source files

See more commands here.

Otros tipos de objetivos

Es posible que los objetivos realmente te entusiasmen y ya estés planificando cómo puedes describir tus programas en términos de objetivos. ¡Eso es genial! Sin embargo, se encontrará rápidamente con dos situaciones más en las que el idioma de destino es útil, pero necesita un poco de flexibilidad adicional sobre lo que hemos cubierto.

En primer lugar, es posible que tenga una biblioteca que conceptualmente debería ser un objetivo, pero que en realidad no tiene componentes incorporados, una biblioteca «de solo encabezado». Estas se llaman bibliotecas de interfaz en CMake y escribirías:

add_library(some_header_only_lib INTERFACE)

Aviso de que no es necesario agregar todos los archivos de origen. Ahora puede establecer propiedades INTERFACE solo en esto (ya que no hay ningún componente construido).

La segunda situación es si tiene una biblioteca preconstruida que desea usar. Esto se llama biblioteca animported en CMake, y utiliza la palabra clave IMPORTED. Las bibliotecas importadas también pueden ser bibliotecasINTERFACE, pueden construirse y modificarse utilizando la misma sintaxis que otras bibliotecas(a partir de CMake 3.11), y pueden tener :: en su nombre. (ALIAS las bibliotecas, que simplemente renombra alguna otra biblioteca, también pueden tener ::). La mayoría de las veces, obtendrás bibliotecas importadas de otros lugares, y no estarás haciendo las tuyas propias.

INTERFAZ IMPORTADA

¿Qué pasa con INTERFACE IMPORTED?La diferencia se reduce a dos cosas:

  1. IMPORTED objetivos no son exportables. Si guardas tus objetivos, no puedes guardar los importados, es necesario volver a crearlos (o volver a encontrarlos).
  2. IMPORTED encabezado de incluir directorios siempre será marcado como SYSTEM.

Por lo tanto, un objetivo IMPORTED debería representar algo que no es directamente parte de tu paquete.

leer Más

  • la Base de las Modernas CMake conceptos básicos
  • véase También CMake del docs

Puntos Clave

  • las Bibliotecas y los archivos ejecutables son los objetivos.Los objetivos

  • tienen muchas propiedades útiles.Los objetivos

  • se pueden vincular a otros objetivos.

  • Puede controlar qué partes de un destino se heredan al vincular.

  • Puede crear destinos de INTERFAZ en lugar de crear variables.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.