Compartir a través de


Guía del mantenedor

En este documento se muestra un conjunto de directivas que debe aplicar al agregar o actualizar una receta de puerto. Su intención es servir al papel de Manual de normas de Debian, Guías para el mantenedor de Homebrew y Libro de cocina de fórmulas de Homebrew.

Objetivos generales de diseño del registro

Los puertos de la línea base actual deben instalarse simultáneamente

Queremos poder mostrar a los usuarios de nivel inferior de las bibliotecas en el registro mantenido que la combinación de bibliotecas en cualquier línea base determinada que publicamos se ha probado para trabajar conjuntamente en al menos algunas configuraciones. Permitir que los puertos se excluyan entre sí interrumpen la capacidad de probar estas configuraciones, ya que el número de compilaciones necesarias para estas pruebas crecería como 2^number_of_such_cases. Además, la instalación de dependencias adicionales siempre se considera "segura": no hay forma de que un puerto o un usuario final aserten que una dependencia no está instalada en sus requisitos.

Si desea representar tal situación alternativa para los usuarios, considere describir cómo alguien puede crear un overlay port implementando la forma alternativa con un comentario en portfile.cmake en lugar de intentar añadir puertos adicionales nunca construidos en la integración continua del registro curado. Por ejemplo, consulte glad@0.1.36.

Antes de la introducción de registros, aceptamos varios puertos no probados como alternativas, como boringssl, que podrían facilitar la creación de puertos de superposición. Esto ya no se acepta porque los registros permiten publicar estos puertos no probados sin modificar el registro mantenido.

Uso de minúsculas para cadenas de dígitos hexadecimales

Muchas de las características de vcpkg se basan en la comparación de cadenas de dígitos hexadecimales. Algunos ejemplos incluyen, entre otros, hashes SHA512, identificadores de confirmación de Git y hashes de objetos de árbol.

Internamente, vcpkg utiliza la normalización de minúsculas para las comparaciones de tales valores donde el casing es irrelevante. Sin embargo, las herramientas construidas sobre la infraestructura de vcpkg pueden no tener las mismas consideraciones. Por este motivo, se requieren cadenas hexadecimales

para ser minúsculas para la coherencia en los siguientes escenarios:

  • Parámetro SHA512 en las funciones auxiliares de vcpkg.
  • El parámetro REF en las funciones auxiliares de vcpkg, cuando su valor es una cadena hexadecimal.
  • El objeto git-tree en archivos de base de datos de versiones.
  • Objeto sha512 del scripts/vcpkg-tools.json archivo.
  • Otros lugares donde el uso de mayúsculas/minúsculas en la cadena hexadecimal no es importante.

Estructura de PR

Haga pull requests separadas por puerto

Siempre que sea posible, separe los cambios en varios PR. Esto hace que sean mucho más fáciles de revisar y evita que los problemas con un conjunto de cambios retrasen todos los demás cambios.

Evitar cambios triviales en archivos sin modificar

Por ejemplo, evite cambiar el formato o cambiar el nombre de las variables en los archivos de puerto que, de lo contrario, no tengan ninguna razón para modificarse para el problema en cuestión. Sin embargo, si necesitas modificar el archivo con el principal objetivo de la PR (actualización de la biblioteca), los cambios beneficiosos como corregir erratas obviamente son bienvenidos.

Comprobación de nombres en otros repositorios

Los nombres de puerto deben intentar no ser ambiguos sobre qué paquete instala el puerto. Lo ideal es que la búsqueda del nombre del puerto en un motor de búsqueda le lleve rápidamente al proyecto correspondiente. Un buen servicio para comprobar muchos nombres de paquete en varios repositorios a la vez es Repology.

Los proyectos con nombres cortos o con nombre después de palabras comunes pueden requerir desambiguación, especialmente cuando no hay proyectos con una fuerte asociación con la palabra dada. Por ejemplo, un puerto con el nombre ip no es aceptable, ya que es probable que varios proyectos se denominarían de forma similar.

Algunos ejemplos de buenos desambiguadores son:

  • Nombre de usuario o organización del propietario del repositorio: google-cloud-cpp.
  • El nombre de un conjunto de bibliotecas al que el proyecto pertenece es: boost-dll.

Los prefijos y sufijos comunes usados por C++ y los proyectos de código abierto no son ambigüadores válidos, algunos ejemplos incluyen, entre otros:

  • cpp,
  • free,
  • lib,
  • open,
  • Números

Por ejemplo, al comparar los siguientes nombres de puerto: ip-cpp, libip y ip5 y quitar los desambiguadores no válidos, todos se reducen a la misma raíz (ip) y, por tanto, se considera que tienen el mismo nombre.

Se hace una excepción a esta guía para los nombres que están fuertemente asociados a un solo proyecto. Por ejemplo, libpng, openssl y zlib.

Utilice los borradores de GitHub

Los borradores de PRs de GitHub son una gran manera de obtener retroalimentación de CI o humana sobre el trabajo que aún no está listo para fusionar. La mayoría de los nuevos PR deben ser abiertos como borradores y convertidos en PR normales una vez que el CI pasa.

Para obtener más información acerca de GitHub Draft PRs, consulte Introducción a los borradores de pull requests.

Archivos de puertos

Evitar funciones auxiliares en desuso

En este momento, los siguientes helpers están obsoletos:

Algunas de las funciones ayudantes de sustitución están en "puertos de herramientas" para permitir a los consumidores fijar su comportamiento en versiones específicas, para permitir bloquear el comportamiento de los ayudantes en una versión concreta. Los puertos de herramientas deben agregarse al puerto "dependencies", de la siguiente manera:

{
  "name": "vcpkg-cmake",
  "host": true
},
{
  "name": "vcpkg-cmake-config",
  "host": true
}

Evitar comentarios excesivos en archivos de configuración de puertos

Idealmente, los archivos de puerto deben ser cortos, sencillos y tan declarativos como sea posible. Elimine cualquier comentario introducido por el comando create antes de enviar un PR.

Los puertos no deben ser dependientes de la ruta de acceso

Los puertos no deben cambiar su comportamiento en función de los puertos que ya están instalados en un formulario que cambiaría el contenido que instala ese puerto. Por ejemplo, dado:

> vcpkg install a
> vcpkg install b
> vcpkg remove a

y

> vcpkg install b

los archivos instalados por b deben ser los mismos, independientemente de la influencia de la instalación anterior de a. Esto significa que los puertos no deben intentar detectar si otro puerto proporciona algo en el árbol instalado antes de realizar alguna acción. A continuación se describe una causa específica y común del comportamiento "dependiente de la ruta de acceso" en "Al definir características, controlar explícitamente las dependencias".

Regla de atribución de puerto única

En todo el sistema vcpkg, no se espera que un usuario use dos puertos simultáneamente para proporcionar el mismo archivo. Si un puerto intenta instalar un archivo ya proporcionado por otro archivo, se producirá un error en la instalación. Si un puerto quiere usar un nombre muy común para un encabezado, por ejemplo, debe colocar esos encabezados en un subdirectorio en lugar de en include.

Esta propiedad se comprueba periódicamente mediante ejecuciones de integración continua que intentan instalar todos los puertos del Registro, lo que producirá un error si FILE_CONFLICTS dos puertos proporcionan el mismo archivo.

Añadir exportaciones CMake en un espacio de nombres no oficial.

Un diseño básico ideal de vcpkg es no crear "bloqueo" para los usuarios. En el sistema de construcción, no debe haber ninguna diferencia entre depender de una biblioteca del sistema y depender de una biblioteca de vcpkg. Para ello, evitamos añadir exportaciones CMake u objetivos a las bibliotecas existentes con "el nombre obvio", para permitir que las upstreams añadan sus propias exportaciones CMake oficiales sin entrar en conflicto con vcpkg.

Para ello, las configuraciones de CMake que el puerto exporta, y que no están en la biblioteca original, deben llevar unofficial- como prefijo. Cualquier objetivo adicional debe estar en el espacio de nombres unofficial::<port>::.

Esto significa que el usuario debería ver lo siguiente:

  • find_package(unofficial-<port> CONFIG) como la forma de llegar al paquete exclusivo de vcpkg
  • unofficial::<port>::<target> como un objetivo exportado de ese puerto.

Ejemplos:

  • brotli crea el unofficial-brotli paquete, lo que genera el destino unofficial::brotli::brotli.

Cada puerto tiene que proporcionar un archivo denominado copyright en la carpeta ${CURRENT_PACKAGES_DIR}/share/${PORT}. Si el contenido de licencia de un paquete está disponible en sus archivos de origen, este archivo se debe crear mediante una llamada a vcpkg_install_copyright(). vcpkg_install_copyright también agrupa varios archivos de copyright si es necesario.

vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")

Un método anterior para crear manualmente este archivo es con el comando integrado de file CMake. Esto se desaconseja en favor de vcpkg_install_copyright en los nuevos puertos, pero todavía está permitido.

file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)

Si el contenido de la licencia en los archivos de origen ascendentes no está en formato de texto (por ejemplo, un archivo PDF), copyright debe contener una explicación sobre cómo un usuario puede encontrar los requisitos de licencia. Si es posible, también debe incluir un vínculo a los archivos de origen originales que indican esto, por lo que los usuarios pueden comprobar si está actualizado.

file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/copyright" [[As of 2023-07-25, according to
https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Public-Documents/README.md#end-user-license-agreement
this software is bound by the "SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT" PDF located at
https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Public-Documents/ADL%20SDK%20EULA.pdf
]])

Restricciones de versión en puertos

Por lo general, se deben evitar restricciones de versión dentro de los puertos, ya que pueden dificultar la evolución independiente de los proyectos. Agregar estas restricciones solo se permite cuando hay una justificación bien documentada, como la incompatibilidad probada con versiones anteriores específicas. Estas restricciones no deben usarse simplemente para mantener la paridad con proyectos independientes.

Las variables de MAYBE_UNUSED_VARIABLES deben aplicarse a al menos una configuración

Al agregar una nueva variable para MAYBE_UNUSED_VARIABLES silenciar una advertencia durante el paso de configuración de CMake, debe agregar un comentario que explique el caso cuando se aplique la nueva variable. Si una variable no se aplica en ninguna configuración, es muy probable que exista un error subyacente (por ejemplo, un nombre de variable mal escrito) y agregarlo no tenga ningún efecto real en la compilación.

vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
  FEATURES
    windowsfeature WINDOWS_OPTION
)

vcpkg_configure_cmake(
  SOURCE_PATH "${SOURCE_PATH}"
  OPTIONS
    ${FEATURE_OPTIONS}
  MAYBE_UNUSED_VARIABLES
    # Applies only on Windows
    WINDOWS_OPTION
)

Características

No usar características para implementar alternativas

Las características deben tratarse como funcionalidad de adición. Si port[featureA] instala e port[featureB] instala , port[featureA,featureB] debe instalarse. Además, si un segundo puerto depende de [featureA] y un tercer puerto depende de [featureB], la instalación de ambos, el segundo y el tercero, debe tener sus dependencias satisfechas.

Las bibliotecas en esta situación deben elegir una de las opciones disponibles tal como se expresa en vcpkg, y los usuarios que deseen una configuración diferente deben utilizar los puertos superpuestos en este momento.

Los ejemplos existentes que no aceptaríamos hoy conservamos por motivos de compatibilidad con versiones anteriores:

  • libgit2, libzip, open62541 todas tienen características para seleccionar un back-end TLS o criptográfico. curl tiene diferentes opciones de backend de criptografía, pero permite seleccionar entre ellas en tiempo de ejecución, lo que significa que se mantiene el principio anterior.
  • darknet tiene opencv2, opencv3características para controlar qué versión de opencv se va a usar para sus dependencias.

Una característica puede interactuar con la versión preliminar o la funcionalidad beta

A pesar de lo anterior, si hay una rama en versión preliminar o similar en la que la funcionalidad de vista previa tiene una alta probabilidad de no interrumpir la funcionalidad que no es de versión preliminar (por ejemplo, sin eliminaciones de API), una característica es aceptable para modelar esta configuración.

Ejemplos:

  • Los SDK de Azure (con el formato azure-Xxx) tienen una public-preview característica.
  • imgui tiene una característica experimental-docking que activa su rama de acoplamiento de vista previa que utiliza un merge commit adjunto a cada una de sus versiones públicas numeradas.

Las características predeterminadas no deben agregar API

Las características predeterminadas están diseñadas para garantizar que se instale una compilación razonablemente funcional de una biblioteca para los clientes que no saben que lo usan. Si no saben que usan una biblioteca, no pueden saber enumerar las características. Por ejemplo, libarchive expone características que habilitan algoritmos de compresión en una interfaz genérica existente; si se compila sin ninguna de estas características, es posible que la biblioteca no tenga ninguna utilidad.

Uno debe considerar cuidadosamente si una característica debe estar activada de forma predeterminada, ya que deshabilitar las características predeterminadas es compleja.

La deshabilitación de una característica predeterminada como consumidor "transitivo" requiere:

  • Todos los clientes deshabilitan explícitamente las características por defecto a través de "default-features": false o incluyendo [core] en la lista de características en la línea de comandos.
  • Asignar un nombre a la dependencia transitiva en la vcpkg install línea de comandos o como una dependencia directa en el manifiesto de nivel superior

En el registro mantenido de vcpkg, si la característica agrega API adicionales, ejecutables u otros archivos binarios, debe estar desactivada de forma predeterminada. En caso de duda, no marque una característica como predeterminada.

No usar características para controlar alternativas en interfaces publicadas

Si un consumidor de un puerto depende solo de la funcionalidad central de ese puerto, con alta probabilidad no deben ser rotos por la activación de la característica. Esto es aún más importante cuando el consumidor no controla directamente la alternativa, sino mediante la configuración del compilador como /std:c++17 / -std=c++17.

Los ejemplos existentes que no aceptaríamos hoy conservamos por motivos de compatibilidad con versiones anteriores:

  • redis-plus-plus[cxx17] controla un polyfill pero no incorpora la configuración en el árbol instalado.
  • ace[wchar] cambia todas las API para aceptar const wchar_t* en lugar de const char*.

Una característica puede reemplazar polyfills con alias siempre que el reemplazo se incorpore al árbol instalado.

No obstante lo anterior, los puertos pueden eliminar los polyfills con una feature, siempre y cuando:

  1. La activación de la función cambie los polyfills por alias de la entidad polyfilled
  2. El estado del polyfill está integrado en las cabeceras instaladas, de tal forma que los errores de tiempo de ejecución "imposibles" de desajuste ABI son improbables
  3. Es posible que un consumidor del puerto escriba código que funcione en ambos modos, por ejemplo mediante una definición de tipo que sea polirrellenada o no.

Ejemplo:

  • abseil[cxx17] cambia absl::string_view a un reemplazo o std::string_view; el parche implementa el requisito de baking.

Si es fundamental exponer las alternativas subyacentes, se recomienda proporcionar mensajes en tiempo de compilación para indicar al usuario cómo copiar el puerto en una superposición privada:

set(USING_DOG 0)
message(STATUS "This version of LibContoso uses the Kittens backend. To use the Dog backend instead, create an overlay port of this with USING_DOG set to 1 and the `kittens` dependency replaced with `dog`.")
message(STATUS "This recipe is at ${CMAKE_CURRENT_LIST_DIR}")
message(STATUS "See the overlay ports documentation at https://github.com/microsoft/vcpkg/blob/master/docs/specifications/ports-overlay.md")

Técnicas de construcción

No usar dependencias proporcionadas

No use copias embebidas de bibliotecas. Todas las dependencias deben dividirse y empaquetarse por separado para que se puedan actualizar y mantener.

Las dependencias proporcionadas por el proveedor presentan varios desafíos que entran en conflicto con los objetivos de vcpkg de proporcionar un sistema de administración de paquetes confiable, coherente y fácil de mantener:

Dificultad en las actualizaciones: las copias insertadas de bibliotecas dificultan el seguimiento y la aplicación de actualizaciones, incluidas las revisiones de seguridad, de los proyectos ascendentes. Esto conduce a posibles riesgos de seguridad y dependencias obsoletas en el ecosistema.

Conflictos de símbolos: las dependencias de proveedor pueden provocar conflictos de símbolos cuando varios paquetes incluyen versiones diferentes de la misma biblioteca.

Por ejemplo: Si package A vendors Library X (versión 1) y Package B vendors Library X (versión 2), una aplicación que vincula ambos paquetes puede experimentar errores en tiempo de ejecución o un comportamiento indefinido debido a símbolos conflictivos.

Al empaquetar las dependencias por separado, vcpkg garantiza que se use una sola versión de una biblioteca en todos los paquetes, lo que elimina dichos conflictos.

Cumplimiento de licencias: las dependencias incorporadas pueden ocultar las licencias de las bibliotecas insertadas, lo que podría violar sus términos o crear incompatibilidades.

Mayor carga de mantenimiento: mantener las dependencias proporcionadas sincronizadas con sus versiones ascendentes requiere un esfuerzo manual significativo y, a menudo, conduce a un trabajo duplicado entre paquetes.

Preferir el uso de CMake

Cuando haya varios sistemas de compilación disponibles, prefiera usar CMake. Además, cuando sea correspondiente, puede ser más fácil y más manejable reescribir sistemas de compilación alternativos en CMake mediante directivas file(GLOB).

Ejemplos: abseil

Elegir archivos binarios estáticos o compartidos

Al compilar bibliotecas de CMake, vcpkg_cmake_configure() pasará el valor correcto para BUILD_SHARED_LIBS en función de la variante solicitada por el usuario.

Puede calcular parámetros de configuración alternativos mediante string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" ...).

# portfile.cmake

string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "static" KEYSTONE_BUILD_STATIC)
string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" KEYSTONE_BUILD_SHARED)

vcpkg_cmake_configure(
    SOURCE_PATH ${SOURCE_PATH}
    OPTIONS
        -DKEYSTONE_BUILD_STATIC=${KEYSTONE_BUILD_STATIC}
        -DKEYSTONE_BUILD_SHARED=${KEYSTONE_BUILD_SHARED}
)

Si una biblioteca no ofrece opciones de configuración para seleccionar la variante de compilación, la compilación debe ser modificada. Cuando se parchea una compilación, siempre se debe intentar maximizar la mantenibilidad futura del puerto. Típicamente esto significa minimizar el número de líneas que necesitan ser tocadas para arreglar el problema en cuestión.

Ejemplo: Aplicación de revisiones a una biblioteca de CMake para evitar la creación de variantes no deseadas

Por ejemplo, al aplicar revisiones a una biblioteca basada en CMake, puede ser suficiente agregar EXCLUDE_FROM_ALL a destinos no deseados y encapsular la install(TARGETS ...) llamada en un if(BUILD_SHARED_LIBS). Esto será más corto que envolver o borrar cada línea que menciona la variante no deseada.

Para un proyecto CMakeLists.txt con el siguiente contenido:

add_library(contoso SHARED contoso.c)
add_library(contoso_static STATIC contoso.c)

install(TARGETS contoso contoso_static EXPORT ContosoTargets)

install(EXPORT ContosoTargets
  FILE ContosoTargets
  NAMESPACE contoso::
  DESTINATION share/contoso)

Solo es necesario aplicar revisiones a la install(TARGETS) línea.

add_library(contoso SHARED contoso.c)
add_library(contoso_static STATIC contoso.c)

if(BUILD_SHARED_LIBS)
  set_target_properties(contoso_static PROPERTIES EXCLUDE_FROM_ALL 1)
  install(TARGETS contoso EXPORT ContosoTargets)
else()
  set_target_properties(contoso PROPERTIES EXCLUDE_FROM_ALL 1)
  install(TARGETS contoso_static EXPORT ContosoTargets)
endif()

install(EXPORT ContosoTargets
  FILE ContosoTargets
  NAMESPACE contoso::
  DESTINATION share/contoso)

Al definir características, controle explícitamente las dependencias.

Al definir una característica que captura una dependencia opcional, asegúrese de que la dependencia no se usará accidentalmente cuando la característica no esté habilitada explícitamente.

set(CMAKE_DISABLE_FIND_PACKAGE_ZLIB ON)
set(CMAKE_REQUIRE_FIND_PACKAGE_ZLIB OFF)
if ("zlib" IN_LIST FEATURES)
  set(CMAKE_DISABLE_FIND_PACKAGE_ZLIB OFF)
  set(CMAKE_REQUIRE_FIND_PACKAGE_ZLIB ON)
endif()

vcpkg_cmake_configure(
  SOURCE_PATH ${SOURCE_PATH}
  OPTIONS
    -DCMAKE_DISABLE_FIND_PACKAGE_ZLIB=${CMAKE_DISABLE_FIND_PACKAGE_ZLIB}
    -DCMAKE_REQUIRE_FIND_PACKAGE_ZLIB=${CMAKE_REQUIRE_FIND_PACKAGE_ZLIB}
)

El fragmento de código siguiente que usa vcpkg_check_features() es equivalente.

vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS
  FEATURES
    "zlib"    CMAKE_REQUIRE_FIND_PACKAGE_ZLIB
  INVERTED_FEATURES
    "zlib"    CMAKE_DISABLE_FIND_PACKAGE_ZLIB
)

vcpkg_cmake_configure(
    SOURCE_PATH ${SOURCE_PATH}
    OPTIONS
      ${FEATURE_OPTIONS}
)

ZLIB en el fragmento distingue entre mayúsculas y minúsculas. Para obtener más información, consulte la documentación CMAKE_DISABLE_FIND_PACKAGE_<PackageName> y CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>.

Una lib se considera en conflicto si realiza alguna de las acciones siguientes:

  • Definir main
  • Definir malloc
  • Definir símbolos que también se declaran en otras bibliotecas

Las librerías conflictivas son típicamente por diseño y no se consideran un defecto. Dado que algunos sistemas de compilación se vinculan con todo en el directorio lib, estos deben moverse a un subdirectorio denominado manual-link.

Control de versiones

Siga las convenciones comunes para el "version" campo.

Al crear un puerto, siga la convención de control de versiones que usa el autor del paquete. Al actualizar el puerto, siga usando la misma convención a menos que la cadena ascendente indique lo contrario. Para obtener una explicación completa de nuestras convenciones, consulte nuestra documentación de control de versiones.

Si la cadena ascendente no ha publicado una versión en un tiempo, no cambie el esquema de control de versiones del puerto a version-date para obtener los cambios más recientes. Estas confirmaciones pueden incluir cambios que no están listos para producción. En su lugar, pida al repositorio ascendente que publique una nueva versión.

Actualice el campo "port-version" en el fichero de manifiesto de cualquier puerto modificado.

vcpkg usa este campo para determinar si un puerto determinado está obsoleto y se debe cambiar cada vez que cambia el comportamiento del puerto.

Nuestra convención es usar el campo "port-version" para cambios en el puerto que no cambien la versión upstream, y poner el "port-version" a cero cuando se haga una actualización de la versión upstream.

Por ejemplo:

  • La versión del paquete de Zlib es actualmente 1.2.1, sin "port-version" explícito (equivalente a un "port-version" de 0).
  • Ha descubierto que se ha implementado el archivo de copyright incorrecto y lo ha corregido en el archivo portfile.
  • Debe actualizar el "port-version" campo del archivo de manifiesto a 1.

Consulte la documentación de control de versiones para obtener más información.

Actualice los ficheros de versión en versions/ de cualquier puerto modificado

vcpkg usa un conjunto de archivos de metadatos para alimentar su característica de control de versiones. Estos archivos se encuentran en las siguientes ubicaciones:

  • ${VCPKG_ROOT}/versions/baseline.json, (este archivo es común a todos los puertos) y
  • ${VCPKG_ROOT}/versions/${first-letter-of-portname}-/${portname}.json (uno por puerto).

Por ejemplo, para zlib los archivos pertinentes son:

  • ${VCPKG_ROOT}/versions/baseline.json
  • ${VCPKG_ROOT}/versions/z-/zlib.json

Esperamos que cada vez que actualice un puerto, también actualice sus archivos de versión.

El método recomendado para actualizar estos archivos es ejecutar el x-add-version comando, por ejemplo:

vcpkg x-add-version zlib

Si está actualizando varios puertos al mismo tiempo, en su lugar puede ejecutar:

vcpkg x-add-version --all

para actualizar los archivos de todos los puertos modificados a la vez.

Nota:

Estos comandos requieren que haya confirmado los cambios en los puertos antes de ejecutarlos. La razón es que el Git SHA del directorio del puerto es requerido en estos ficheros de versión. Pero no se preocupe, el x-add-version comando le avisará si tiene cambios locales que no se han confirmado.

Para obtener más información, consulte los artículos Referencia de control de versiones y Registros.

Aplicación de revisión

vcpkg es una solución de empaquetado, no los propietarios finales de los componentes que implementamos. En algunos casos, es necesario aplicar revisiones para mejorar la compatibilidad de los componentes con plataformas o la compatibilidad de los componentes entre sí.

  • Queremos evitar parches que:
    • no estén de acuerdo con el upstream
    • causen vulnerabilidades o fallos
    • seamos incapaces de mantener a través de las actualizaciones de la versión upstream
    • son lo suficientemente grandes como para provocar el entrelazamiento de licencias con el propio repositorio vcpkg.

Notificar a los propietarios de upstream los parches relevantes para upstream

Si un parche puede ser útil para el desarrollador, este debe ser notificado de su contenido. (Los parches que aplican un comportamiento específico de vcpkg no relacionado con upstream, como la devolución de una dependencia, no requieren notificación).

Para evitar situaciones en las que upstream no esté de acuerdo con el parche, esperaremos al menos 30 días para aplicar dichos parches.

Omitiremos este período de espera si tenemos alta confianza de que el cambio es correcto. Ejemplos de parches de alta confianza incluyen, pero no se limitan a:

  • La aceptación de aguas arriba como un parche (por ejemplo, backporting un cambio específico de un pull request aguas arriba ha fusionado).
  • Añadir #include que faltan.
  • Correcciones de código de producto pequeñas y obvias (por ejemplo, inicializando una variable sin inicializar).
  • Deshabilitación de componentes irrelevantes en vcpkg de la compilación, como pruebas o ejemplos.

Preferir alternativas antes que aplicar parches

Es preferible establecer opciones en una llamada a vcpkg_configure_xyz() en lugar de aplicar revisiones directamente a la configuración.

Opciones comunes que permiten evitar la aplicación de revisiones:

  • [MSBUILD] <PropertyGroup> ajustes dentro del archivo de proyecto puede ser anulado a través de parámetros /p:.
  • [CMAKE] Las llamadas a find_package(XYz) en scripts de CMake se pueden deshabilitar a través de -DCMAKE_DISABLE_FIND_PACKAGE_XYz=ON
  • [CMAKE] Las variables de caché (declaradas como set(VAR "value" CACHE STRING "Documentation") o option(VAR "Documentation" "Default Value")) se pueden invalidar simplemente pasandolas en la línea de comandos como -DVAR:STRING=Foo. Una excepción notable es si el FORCE parámetro se pasa a set(). Para obtener más información, consulte la documentación de CMake set .

Preferir la descarga de parches aprobados sobre la comprobación de ellos en el puerto

Si se puede obtener un fichero de parche aprobado o fusionado de aguas arriba, los puertos deberían intentar descargarlos y aplicarlos en lugar de tenerlos como parte de los ficheros del puerto. Este proceso se prefiere porque:

  • Confirma que upstream ha aceptado los cambios del parche
  • Simplifica el proceso de revisión cambiando las responsabilidades ascendentes
  • Reduce el tamaño del repositorio de vcpkg para los usuarios que no usan el parche.
  • Evita conflictos de licencias con el repositorio vcpkg.

Las revisiones deben descargarse desde un punto de conexión estable para evitar conflictos de SHA. Al descargar archivos de revisión desde una solicitud de incorporación de cambios o un commit desde GitHub y GitLab, el parámetro ?full_index=1 debe anexarse a la dirección URL de descarga.

Ejemplos:

  • https://github.com/google/farmhash/pull/40.diff?full_index=1
  • https://github.com/linux-audit/audit-userspace/commit/f8e9bc5914d715cdacb2edc938ab339d5094d017.patch?full_index=1
  • https://gitlab.kitware.com/paraview/paraview/-/merge_requests/6375.diff?full_index=1

Prefiere parchear antes que anular valores VCPKG_<VARIABLE>

Algunas variables con VCPKG_<VARIABLE> prefijo tienen un equivalente CMAKE_<VARIABLE>. Sin embargo, no todos ellos se pasan a la construcción interna del paquete (ver implementación: Windows toolchain).

Considere el ejemplo siguiente:

set(VCPKG_C_FLAGS "-O2 ${VCPKG_C_FLAGS}")
set(VCPKG_CXX_FLAGS "-O2 ${VCPKG_CXX_FLAGS}")

Usando las cadenas de herramientas integradas de vcpkg esto funciona, porque el valor de VCPKG_<LANG>_FLAGS se reenvía a la variable CMAKE_LANG_FLAGS apropiada. Sin embargo, una cadena de herramientas personalizada que no conoce las vcpkgvariables no las reenvía.

Por este motivo, es preferible aplicar revisiones al sistema de compilación directamente al establecer CMAKE_<LANG>_FLAGS.

Minimizar parches

Al realizar cambios en una biblioteca, intente minimizar la diferencia final. Esto significa que no debe volver a formatear el código fuente ascendente al realizar cambios que afecten a una región. Al deshabilitar un condicional, es mejor agregar un AND FALSE o un && 0 a la condición que eliminar cada línea del condicional. Si una región grande necesita ser desactivada, es más corto añadir un if(0) o #if 0 alrededor de la región en lugar de borrar cada línea del parche.

No agregue revisiones si el puerto está obsoleto y la actualización del puerto a una versión más reciente publicada solucionaría el mismo problema. vcpkg prefiere actualizar puertos a parchear versiones obsoletas.

Esto ayuda a reducir el tamaño del repositorio vcpkg, así como a mejorar la probabilidad de que el parche se aplique a futuras versiones de código.

No implementar características en parches

El propósito de aplicar revisiones en vcpkg es habilitar la compatibilidad con compiladores, bibliotecas y plataformas. No se trata de implementar nuevas características sin seguir el procedimiento adecuado de Open Source (presentar un Issue/PR/etc.).

No compile pruebas, documentos o ejemplos de forma predeterminada

Al enviar un puerto nuevo, compruebe si hay opciones como BUILD_TESTS o WITH_TESTS y POCO_ENABLE_SAMPLES asegúrese de que los archivos binarios adicionales están deshabilitados. Esto minimiza los tiempos de compilación y las dependencias del usuario medio.

Opcionalmente, puede agregar una test característica que permita compilar las pruebas, pero esto no debe estar en la Default-Features lista.

Permitir que los usuarios existentes de la biblioteca cambien a vcpkg

No añada CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS

A menos que el autor de la biblioteca ya lo use, no deberíamos usar esta funcionalidad de CMake porque interactúa mal con las plantillas de C++ y interrumpe determinadas características del compilador. Las bibliotecas que no proporcionan un archivo .def y no usan declaraciones __declspec() simplemente no admiten compilaciones compartidas para Windows y deben marcarse como tales:

if(VCPKG_TARGET_IS_WINDOWS)
    vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
endif()

No cambie el nombre de los archivos binarios fuera de los nombres proporcionados por la cadena ascendente.

Esto significa que si la biblioteca ascendente tiene nombres diferentes en la versión y depuración (libx frente a libxd), la biblioteca de depuración no debe cambiarse a libx. Viceversa, si la biblioteca upstream tiene el mismo nombre en release y debug, no debemos introducir un nuevo nombre.

Advertencia importante:

  • Las variantes estáticas y compartidas a menudo deben cambiarse a un esquema común. Esto permite a los consumidores usar un nombre común e ignorar las conexiones posteriores. Esto es seguro porque solo hacemos que uno a la vez esté disponible.

Si una biblioteca genera archivos de integración de CMake (foo-config.cmake), el cambio de nombre debe realizarse mediante la aplicación de revisiones a la compilación de CMake en lugar de simplemente llamar a file(RENAME) en los archivos o LIB de salida.

Por último, los archivos DLL en Windows nunca se deben cambiar de nombre después de la compilación porque interrumpe los LIB generados.

Manifiestos

Es necesario dar formato al archivo de manifiesto. Use el siguiente comando para dar formato a todos los archivos de manifiesto:

> vcpkg format-manifest --all

Trillizos

No aceptamos solicitudes para agregar tripletas no comunitarias en este momento. La promoción del estado de comunidad a triplete completo se basa principalmente en el presupuesto para disponer de hardware que permita probar estos tripletes. Además, estará orientada por las métricas proporcionadas por vcpkg para maximizar la probabilidad de que lo que la gente realmente utiliza sea completamente probado.

Añadiremos tripletes comunitarios si:

  • está demostrado que la gente utilizará realmente ese triplete comunitario; y,
  • no sabemos si dicha tripleta está rota.

Por ejemplo, no agregamos un triplete en https://github.com/microsoft/vcpkg/pull/29034 porque el autor estaba intentando "completar el conjunto" en lugar de indicar que realmente usarían esa cosa, y no agregamos linux-dynamic hasta que se creó la solución patchelf para hacer que los resultados sean reubicables.

Notas útiles de implementación

Los archivos de puerto se ejecutan en modo de script

Aunque portfile.cmake y CMakeLists.txt comparten una sintaxis común y construcciones principales del lenguaje CMake (también conocido como "Comandos de scripting"), los portfiles se ejecutan en "Modo de script", mientras que los archivos CMakeLists.txt se ejecutan en "Modo de proyecto". La diferencia más importante entre estos dos modos es que "Modo de script" no tiene los conceptos de "Cadena de herramientas", "Language" y "Target". Los comportamientos, incluidos los comandos de scripting, que dependen de estas construcciones (por ejemplo CMAKE_CXX_COMPILER, , CMAKE_EXECUTABLE_SUFFIX, CMAKE_SYSTEM_NAME) no serán correctos.

Los portfiles tienen acceso directo a las variables establecidas en el archivo de tripletas, pero los CMakeLists.txt no (aunque a menudo se produce una traducción: VCPKG_LIBRARY_LINKAGE frente a BUILD_SHARED_LIBS).

Los archivos de puerto y las compilaciones de Project invocadas por los archivos port se ejecutan en distintos procesos. Conceptualmente:

+----------------------------+       +------------------------------------+
| CMake.exe                  |       | CMake.exe                          |
+----------------------------+       +------------------------------------+
| Triplet file               | ====> | Toolchain file                     |
| (x64-windows.cmake)        |       | (scripts/buildsystems/vcpkg.cmake) |
+----------------------------+       +------------------------------------+
| Portfile                   | ====> | CMakeLists.txt                     |
| (ports/foo/portfile.cmake) |       | (buildtrees/../CMakeLists.txt)     |
+----------------------------+       +------------------------------------+

Para determinar el host en un archivo de puerto, las variables estándar de CMake están bien (CMAKE_HOST_WIN32).

Para determinar el destino en un archivo de puerto, se deben usar las variables de triplete de vcpkg (VCPKG_CMAKE_SYSTEM_NAME).

Consulte también nuestra triplet documentation para obtener una enumeración completa de las posibles opciones de configuración.