Visión general
Enseñanza: 10 min
Ejercicios: 15 minPreguntas
¿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
STATIC
SHARED
, oMODULE
si sabe qué tipo de biblioteca desea crear; el valor predeterminado es una biblioteca «automática» que puede seleccionarse por el usuario conBUILD_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 etiqueta
target_link_libraries
y una palabra clave; uno dePUBLIC
PRIVATE
yINTERFACE
. ¡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 demy_lib.hpp
ymy_lib.cpp
. Se requiere al menos C++14 para compilar. Si luego agregamy_exe
, y necesitamy_lib
, ¿debería forzar amy_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 unPRIVATE
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
.![]()
la Figura 1: Ejemplo de PÚBLICO, PRIVADO e INTERFAZ.
myprogram
construirá las tres bibliotecas a través demylibrary
; 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
deTargetA
tienemydir
anexada. Si utiliza la palabra claveINTERFACE
en su lugar, entoncesINTERFACE_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 variableCMAKE_CXX_STANDARD
si está establecida,pero no hay una versión de INTERFAZ; no puede forzar una variableCXX_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 queCXX_STANDARD
esté establecido (y eso es un error agradable y claro si estableceCXX_STANDARD
demasiado bajo).target_compile_features
puede rellenarCOMPILE_FEATURES
yINTERFACE_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
yMYLIB_PUBLIC
definidos.- simple_example.cpp: Debe compilarse con
MYLIB_PUBLIC
definido, pero noMYLIB_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 directamentetarget_include_directories
: Include directoriestarget_compile_features
: The compiler features you need activated, likecxx_std_11
target_compile_definitions
: Definitionstarget_compile_options
: More general compile flagstarget_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 filesSee 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:
IMPORTED
objetivos no son exportables. Si guardas tus objetivos, no puedes guardar los importados, es necesario volver a crearlos (o volver a encontrarlos).IMPORTED
encabezado de incluir directorios siempre será marcado comoSYSTEM
.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.