Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este documento lista um conjunto de políticas que você deve aplicar ao adicionar ou atualizar uma receita de porta. Destina-se a servir o papel do Manual de Políticas do Debian, das Diretrizes do Mantenedor do Homebrewe do Livro de Receitas de Fórmulas do Homebrew.
Objetivos gerais de conceção do registo
As portas na linha de base atual devem ser instaláveis simultaneamente
Desejamos poder mostrar aos utilizadores finais das bibliotecas no registo curado que a combinação de bibliotecas em qualquer versão base que publicamos foi testada para funcionar em conjunto em pelo menos algumas configurações. Permitir que as portas se excluam umas às outras compromete a capacidade de testar tais configurações, pois o número de builds necessários para estes testes aumentaria significativamente conforme 2^number_of_such_cases. Além disso, a instalação de dependências adicionais é sempre considerada "segura": não há como uma porta ou usuário final afirmar que uma dependência não está instalada em seus requisitos.
Se pretender representar tal situação alternativa para os utilizadores, considere descrever como alguém pode criar uma porta de sobreposição para, implementando o formulário alternativo com um comentário em portfile.cmake, em vez de tentar adicionar portas adicionais nunca construídas na integração contínua do registo curado. Por exemplo, ver glad@0.1.36.
Antes da introdução de registros, aceitamos várias portas não testadas como alternativas, como boringssl, que poderiam facilitar a criação de portas de sobreposição. Isso não é mais aceito porque os registros permitem a publicação dessas portas não testadas sem modificar o registro selecionado.
Use minúsculas para sequências de dígitos hexadecimais
Muitos dos recursos do vcpkg dependem da comparação de cadeias de caracteres de dígitos hexadecimais. Alguns exemplos incluem, mas não estão limitados a, hashes SHA512, IDs de confirmação do Git e hashes de objeto de árvore.
Internamente, vcpkg usa normalização minúscula para comparações de tais valores onde o invólucro é irrelevante. No entanto, as ferramentas construídas sobre a infraestrutura do vcpkg podem não ter as mesmas considerações. Por esta razão, necessitamos de cadeias hexadecimais
a ser rebaixado para consistência nos seguintes cenários:
- O parâmetro
SHA512nas funções utilitárias do vcpkg. - O
REFparâmetro nas funções auxiliares vcpkg, quando o valor é uma cadeia hexadecimal. - O
git-treeobjeto em ficheiros de base de dados de versão. - O
sha512objeto noscripts/vcpkg-tools.jsonarquivo. - Outros locais onde o invólucro da cadeia hexadecimal não é importante.
Estrutura de Relações Públicas
Faça solicitações pull separadas por porta
Sempre que possível, separe as alterações em várias PRs. Isso facilita significativamente a revisão e evita que problemas com um conjunto de alterações atrasem todas as outras.
Evite alterações triviais em arquivos intocados
Por exemplo, evite reformatar ou renomear variáveis em portfiles que, de outra forma, não têm motivo para serem modificados para o problema em questão. No entanto, se você precisar modificar o arquivo para o objetivo principal do PR (atualizar a biblioteca), então, obviamente, mudanças benéficas, como a correção de erros de digitação, são apreciadas!
Verificar nomes em relação a outros repositórios
Os nomes das portas devem tentar ser inequívocos sobre qual pacote a porta instala. Idealmente, pesquisar o nome do porto em um mecanismo de busca deve levá-lo rapidamente ao projeto correspondente. Um bom serviço para verificar muitos nomes de pacotes em vários repositórios ao mesmo tempo é Repology.
Projetos com nomes curtos ou com nomes de palavras comuns podem exigir desambiguação, especialmente quando não há projetos com uma forte associação à palavra dada. Por exemplo, uma porta com o nome ip não é aceitável, pois é provável que vários projetos sejam nomeados de forma semelhante.
Exemplos de bons desambiguadores são:
- Nome de usuário ou organização do proprietário do repositório:
google-cloud-cpp. - O nome de um conjunto de bibliotecas do qual o projeto faz parte:
boost-dll.
Prefixos e sufixos comuns usados por C++ e projetos de código aberto não são desambiguadores válidos, alguns exemplos incluem, mas não estão limitados a:
-
cpp, -
free, -
lib, -
open, - Números
Por exemplo, ao comparar os seguintes nomes de porta: ip-cpp, libip e ip5 e remover os desambiguadores inválidos, todos eles são reduzidos à mesma haste (ip) e, portanto, são considerados como tendo o mesmo nome.
Uma exceção a esta diretriz é feita para nomes que estão fortemente associados a um único projeto. Por exemplo: libpng, openssl e zlib.
Para evitar confusão para os utilizadores, podemos limitar a frequência com que uma porta pode ser renomeada depois de ser adicionada ao registo público. A nossa política atual é não permitir mais do que uma mudança de nome por ano.
Usar RPs de rascunho do GitHub
Os Rascunhos de PR do GitHub são uma ótima maneira de obter feedback humano ou de CI sobre o trabalho que ainda não está pronto para ser integrado. A maioria das novas RP deve ser aberta como rascunho e convertida em RP normal assim que a IC for aprovada.
Para obter mais informações sobre PRs de rascunho do GitHub, consulte Introducing draft pull requests.
A equipa do vcpkg pode converter o seu PR em rascunho durante o processo de revisão. Normalmente, com uma solicitação para fazer alterações no seu código ou comentários indicando quando marcar o PR como Pronto para revisão.
Fechar RPs inativos
Para evitar acumular PRs obsoletas, a equipa do vcpkg pode fechar PRs que aguardam ação do colaborador há mais de 60 dias. Esta contagem regressiva começa a partir da última vez que um mantenedor vcpkg faz uma solicitação de alterações ou feedback, se nenhuma atividade for observada dentro de 60 dias, o PR é considerado obsoleto e pode ser fechado a critério da equipe do vcpkg.
Portfiles
Evite funções auxiliares preteridas
Neste momento, os seguintes auxiliares são preteridos:
-
vcpkg_extract_source_archive_ex()deve ser substituído pela sobrecarga suportada devcpkg_extract_source_archive()(comARCHIVE) - A sobrecarga obsoleta de
vcpkg_extract_source_archive()semARCHIVEdeve ser substituída pela sobrecarga suportada comARCHIVE. -
vcpkg_apply_patches()deve ser substituído pelos argumentosPATCHESpara as funções auxiliares de "extrair" (por exemplo,vcpkg_from_github()) -
vcpkg_build_msbuild()deve ser substituído porvcpkg_install_msbuild() -
vcpkg_copy_tool_dependencies()deve ser substituído porvcpkg_copy_tools() -
vcpkg_configure_cmakedeve ser substituído porvcpkg_cmake_configure()após a remoçãoPREFER_NINJA -
vcpkg_build_cmakedeve ser substituído porvcpkg_cmake_build() -
vcpkg_install_cmakedeve ser substituído porvcpkg_cmake_install() -
vcpkg_fixup_cmake_targetsdeve ser substituído porvcpkg_cmake_config_fixup
Algumas das funções auxiliares de substituição estão em "portas de ferramentas" para permitir que os consumidores fixem seu comportamento em versões específicas, para permitir bloquear o comportamento dos auxiliares em uma versão específica. As portas de ferramentas precisam ser adicionadas ao "dependencies"da sua porta, da seguinte forma:
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
Evite comentários excessivos em portfiles
Idealmente, os portfiles devem ser curtos, simples e o mais declarativos possível.
Remova todos os comentários padrão introduzidos pelo comando create antes de enviar um PR.
As portas não devem depender do caminho
As portas não devem alterar seu comportamento com base em quais portas já estão instaladas em um formato que alteraria o conteúdo que a porta instala. Por exemplo, dado:
> vcpkg install a
> vcpkg install b
> vcpkg remove a
e ainda
> vcpkg install b
Os arquivos instalados por b devem ser os mesmos, independentemente da influência da instalação anterior do a. Isso significa que as portas não devem tentar detetar se algo é fornecido na árvore instalada por outra porta antes de tomar qualquer ação. Uma causa específica e comum desse comportamento "dependente de caminho" é descrita abaixo em "Ao definir recursos, controle explicitamente as dependências".
Regra de atribuição de porta exclusiva
Em todo o sistema vcpkg, duas portas que um utilizador possa querer usar ao mesmo tempo não devem fornecer o mesmo ficheiro. Se uma porta tentar instalar um arquivo já fornecido por outro arquivo, a instalação falhará. Se uma porta quiser usar um nome extremamente comum para um cabeçalho, por exemplo, ela deve colocar esses cabeçalhos em um subdiretório em vez de em include.
Esta propriedade é verificada regularmente por execuções de integração contínua que tentam instalar todas as portas no registro, que falhará com FILE_CONFLICTS se duas portas fornecerem o mesmo arquivo.
Adicionar exportações CMake em um namespace não oficial
Um ideal de design central do vcpkg é não criar "lock-in" para os usuários. No sistema de compilação, não deve haver diferença entre depender de uma biblioteca do sistema e depender de uma biblioteca do vcpkg. Para esse fim, evitamos adicionar exportações ou alvos do CMake às bibliotecas existentes com "o nome óbvio", para permitir que projetos upstream adicionem suas próprias exportações oficiais do CMake sem entrar em conflito com o vcpkg.
Para esse fim, todas as configurações do CMake que a porta exporta, que não estão na biblioteca de origem, devem ter unofficial- como um prefixo. Quaisquer destinos adicionais devem estar no espaço de nomes unofficial::<port>::.
Isso significa que o usuário deve ver:
-
find_package(unofficial-<port> CONFIG)é o método para obter o pacote exclusivo do vcpkg -
unofficial::<port>::<target>como destino exportado a partir dessa porta.
Exemplos:
-
brotlicria o pacoteunofficial-brotli, produzindo o destinounofficial::brotli::brotli.
Instalar arquivo de direitos autorais
Cada porta tem que fornecer um arquivo chamado copyright na pasta ${CURRENT_PACKAGES_DIR}/share/${PORT}. Se o conteúdo da licença de um pacote estiver disponível em seus arquivos de origem, esse arquivo deverá ser criado por uma chamada para vcpkg_install_copyright().
vcpkg_install_copyright também agrupa vários arquivos de direitos autorais, se necessário.
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
Um método mais antigo para criar manualmente esse arquivo é com o comando file interno do CMake. Isso é desencorajado em favor de vcpkg_install_copyright em novos portos, mas ainda é permitido.
file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)
Se o conteúdo da licença nos arquivos de origem upstream não estiver em forma de texto (por exemplo, um arquivo PDF), copyright deve conter uma explicação sobre como um usuário pode encontrar os requisitos de licença. Se possível, ele também deve incluir um link para os arquivos de origem originais indicando isso, para que os usuários possam verificar se ele está atualizado.
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
]])
Restrições de versão em portas
As restrições de versão dentro dos portos devem geralmente ser evitadas, pois podem dificultar a evolução independente dos projetos. A adição de tais restrições só é permitida quando existe uma justificação bem documentada, como a incompatibilidade comprovada com versões anteriores específicas. Estas restrições não devem ser utilizadas apenas para manter a paridade com projetos independentes.
As variáveis em MAYBE_UNUSED_VARIABLES devem ser aplicadas a pelo menos uma configuração
Ao adicionar uma nova variável para MAYBE_UNUSED_VARIABLES silenciar um aviso durante a etapa de configuração do CMake, você deve adicionar um comentário explicando o caso quando a nova variável se aplica. Se uma variável não se aplicar em nenhuma configuração, é muito provável que exista um bug subjacente (por exemplo, um nome de variável perdido) e adicioná-la não terá efeito real na compilação.
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
)
Caraterísticas
Não use recursos para implementar alternativas
Os recursos devem ser tratados como funcionalidade aditiva. Se port[featureA] instala e port[featureB] instala, então port[featureA,featureB] deve instalar. Além disso, se uma segunda porta depende de [featureA] e uma terceira porta depende de [featureB], a instalação tanto da segunda quanto da terceira porta deve ter suas dependências satisfeitas.
As bibliotecas nessa situação devem escolher uma das opções disponíveis, conforme expresso em vcpkg, e os usuários que desejam uma configuração diferente devem usar portas de sobreposição neste momento.
Exemplos existentes que não aceitaríamos hoje serão mantidos para compatibilidade retroativa.
-
libgit2,libzip,open62541todos têm recursos para selecionar um back-end TLS ou cripto.curltem diferentes opções de back-end de criptografia, mas permite selecionar entre elas em tempo de execução, o que significa que o princípio acima é mantido. -
darknettemopencv2,opencv3, recursos para controlar qual versão do OpenCV usar para suas dependências.
Um recurso pode ativar a funcionalidade de visualização ou beta
Não obstante o acima, se houver uma ramificação de visualização ou similar em que a funcionalidade de visualização tenha uma alta probabilidade de não interromper a funcionalidade de não visualização (por exemplo, sem remoções de API), um recurso é aceitável para modelar essa configuração.
Exemplos:
- Os SDKs do Azure (do formato
azure-Xxx) têm um recursopublic-preview. -
imguitem uma funcionalidade deexperimental-dockingque envolve a sua ramificação de pré-visualização, a qual utiliza um commit de mesclagem associado a cada uma das suas versões públicas numeradas.
Os recursos padrão não devem adicionar APIs
Observação
Uma funcionalidade que está ativada por padrão pelo sistema de build a montante não implica que a funcionalidade deva ser adicionada às entradas default-features. Como o objetivo pretendido de default-features não é modelar as decisões tomadas pelo upstream, mas sim proporcionar conveniência para os utilizadores do modo clássico.
Os recursos padrão destinam-se a garantir que uma compilação razoavelmente funcional de uma biblioteca seja instalada para clientes que não sabem que estão usando-a. Se eles não sabem que estão usando uma biblioteca, eles não podem saber listar recursos. Por exemplo, libarchive expõe recursos que permitem algoritmos de compactação a uma interface genérica existente; Se construído sem qualquer um desses recursos, a biblioteca pode não ter utilidade.
Deve-se considerar cuidadosamente se um recurso deve estar ativado por padrão, porque desabilitar recursos padrão é complexo.
A desativação de um recurso padrão como consumidor "transitivo" exige:
- Todos os clientes que desativam explicitamente os recursos padrão via
"default-features": falseou incluem[core]na lista de recursos através da linha de comando. - Nomeando a dependência transitiva na linha de comando
vcpkg installou como uma dependência direta no manifesto de nível superior
No registro curado do vcpkg, se o recurso adicionar APIs, executáveis ou outros binários adicionais, ele deverá estar desativado por padrão. Em caso de dúvida, não marque um recurso como padrão.
Não use recursos para controlar alternativas em interfaces publicadas
Se um consumidor de uma porta depende apenas da funcionalidade principal dessa porta, há uma alta probabilidade de que eles não serão afetados ao ativar a funcionalidade. Isso é ainda mais importante quando a alternativa não é controlada diretamente pelo consumidor, mas por configurações de compilador como /std:c++17 / -std=c++17.
Exemplos existentes que não aceitaríamos hoje serão mantidos para compatibilidade retroativa.
-
redis-plus-plus[cxx17]controla um polyfill, mas não incorpora a configuração na árvore instalada. -
ace[wchar]altera todas as APIs para aceitarconst wchar_t*em vez deconst char*.
Um recurso pode substituir "polyfills" por "aliases", desde que a substituição esteja incorporada na árvore instalada.
Tendo em conta o exposto acima, as portas podem remover polyfills com uma característica, desde que:
- Ativar a funcionalidade transforma os polyfills em alias da entidade coberta por polyfill.
- O estado do polyfill é incorporado nos cabeçalhos instalados, de modo que se tornem improváveis os erros "impossíveis" de incompatibilidade ABI em tempo de execução.
- É possível para um utilizador da porta escrever código que funcione em ambos os modos, por exemplo, utilizando um typedef que seja polyfill ou não.
Exemplo:
-
abseil[cxx17]alteraabsl::string_viewa uma substituição oustd::string_view; o patch implementa o requisito de cozedura.
Soluções recomendadas
Se for crítico expor as alternativas subjacentes, recomendamos fornecer mensagens no momento da compilação para instruir o usuário sobre como copiar a porta em uma sobreposição 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 construção
Não use dependências de fornecedores
Não utilize cópias incorporadas de bibliotecas. Todas as dependências devem ser divididas e empacotadas separadamente para que possam ser atualizadas e mantidas.
As dependências de fornecedores apresentam vários desafios que entram em conflito com os objetivos do vcpkg de fornecer um sistema de gerenciamento de pacotes confiável, consistente e sustentável:
Dificuldade em atualizações: cópias incorporadas de bibliotecas dificultam o rastreamento e a aplicação de atualizações, incluindo patches de segurança, dos projetos upstream. Esta situação conduz a potenciais riscos de segurança e a dependências desatualizadas no ecossistema.
Conflitos de símbolos: dependências externas podem causar conflitos de símbolos quando vários pacotes incluem versões diferentes da mesma biblioteca.
Por exemplo: Se o Pacote A incorpora a Biblioteca X (versão 1) e o Pacote B incorpora a Biblioteca X (versão 2), um aplicativo que vincula ambos os pacotes pode enfrentar erros de tempo de execução ou comportamento indefinido devido a símbolos em conflito.
Ao empacotar dependências separadamente, o vcpkg garante que uma única versão de uma biblioteca seja usada em todos os pacotes, eliminando esses conflitos.
Conformidade de licenciamento: dependências de fornecedores podem obscurecer o licenciamento das bibliotecas incorporadas, potencialmente violando seus termos ou criando problemas de compatibilidade.
Maior carga de manutenção: Manter as dependências do fornecedor sincronizadas com suas versões upstream requer um esforço manual significativo e muitas vezes leva a trabalho duplicado entre pacotes.
Prefira usar o CMake
Quando vários sistemas de compilação estiverem disponíveis, prefira usar o CMake.
Além disso, quando apropriado, pode ser mais simples e mais fácil de manter reescrever os sistemas de compilação alternativos em CMake usando diretivas file(GLOB).
Exemplos: abseil
Escolha binários estáticos ou compartilhados
Ao criar bibliotecas CMake, vcpkg_cmake_configure() passará o valor correto para BUILD_SHARED_LIBS com base na variante solicitada pelo usuário.
Você pode calcular parâmetros de configuração alternativos usando 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}
)
Se uma biblioteca não oferecer opções de configuração para selecionar a variante de compilação, a compilação deverá ser corrigida. Ao aplicar patches em uma compilação, você deve sempre tentar maximizar a capacidade de manutenção futura da porta. Normalmente, isso significa minimizar o número de linhas que precisam ser alteradas para corrigir o problema em questão.
Exemplo: Aplicar patches em uma biblioteca CMake para evitar a criação de variantes indesejadas
Por exemplo, ao aplicar patches numa biblioteca com base em CMake, pode ser o suficiente adicionar EXCLUDE_FROM_ALL a destinos indesejados e envolver a chamada install(TARGETS ...) num if(BUILD_SHARED_LIBS). Isso será mais curto do que quebrar ou excluir todas as linhas que mencionam a variante indesejada.
Para um projeto CMakeLists.txt com o seguinte conteúdo:
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)
Apenas a linha install(TARGETS) precisa ser corrigida.
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)
Ao definir recursos, controle explicitamente as dependências
Ao definir um recurso que captura uma dependência opcional, certifique-se de que a dependência não será usada acidentalmente quando o recurso não estiver explicitamente habilitado.
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}
)
O trecho abaixo usando vcpkg_check_features() é 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 no trecho diferencia maiúsculas de minúsculas. Para obter mais informações, consulte a documentação CMAKE_DISABLE_FIND_PACKAGE_<PackageName> e CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>.
Colocar libs conflitantes em um diretório manual-link
Uma lib é considerada conflitante se fizer qualquer um dos seguintes:
- Definir
main - Definição de malloc
- Definir símbolos que também são declarados em outras bibliotecas
Libs conflitantes são tipicamente por design e não são considerados um defeito. Como alguns sistemas de compilação se conectam a tudo no diretório lib, eles devem ser movidos para um subdiretório chamado manual-link.
Instalando binários pré-construídos
As portas que instalam artefatos pré-construídos (somente binários) são permitidas, mas fortemente desencorajadas, desde que não bloqueiem efetivamente a alteração das versões de outras portas. A construção a partir do código-fonte é preferida porque respeita todas as configurações do vcpkg que alteram o compilador ou os sinalizadores.
Rejeitaremos portos que cumpram todas as seguintes condições:
- Instale binários pré-construídos em vez de criar a partir do código-fonte, e
- Esses binários têm (ou exigem em tempo de execução) dependências que são fornecidas por outras portas no registro curado, e
- Os artefatos instalados entram no domínio de link publicado do vcpkg – ou seja, instalam bibliotecas/cabeçalhos/CMake ou metadados pkg-config que se espera que portas downstream ou projetos de usuário vinculem.
Fundamentação: Esta combinação bloqueia efetivamente o ABI do gráfico de dependência para as versões usadas quando o upstream pré-construído foi produzido. vcpkg não pode atualizar com segurança (por exemplo) zlib, openssl ou dependências semelhantes, sem arriscar uma quebra sutil de ODR / ABI para os consumidores ao ligarem a biblioteca pré-compilada, e assim os usuários podem perder patches de segurança críticos.
"Entrar no domínio do link publicado" geralmente significa qualquer uma das seguintes opções:
- Instalar
.lib,.a,.so,.dylib, ou importar bibliotecas destinadas a serem utilizadas por consumidores para ligação. - Envio de cabeçalhos que fazem referência (diretamente ou através de código embutido/modelo) a símbolos, tipos ou macros de outras portas vcpkg.
- Instalação de arquivos CMake config / pkg-config que invocam
find_dependency()/Requires:em outras portas vcpkg.
Cenários permitidos (mas ainda desencorajados):
- Ferramentas auxiliares exclusivas do host (executáveis) utilizadas no tempo de construção cujas saídas são consumidas, mas que não são vinculadas diretamente por portas dependentes, desde que agrupem dependências privadamente ou dependam apenas de bibliotecas de tempo de execução do sistema ubíquas.
- Bibliotecas pré-construídas totalmente independentes que vinculam estaticamente todas as dependências do OSS E não expõem seus símbolos ou tipos por meio de cabeçalhos instalados ou interfaces exportadas (os consumidores não podem observar ou depender da ABI transitiva).
- Somente dados, firmware ou pacotes de recursos não vinculados ao código do usuário.
Exemplos proibidos:
- Um
libfoopré-construído que instalalib/libfoo.libjuntamente com cabeçalhos, incluindo<zlib.h>, e foi compilado contra uma versão específica dezlib; os consumidores depois fazem a ligação alibfoo, esperando compatibilidade. - Um SDK pré-compilado que instala um ficheiro de pacote do CMake chamando
find_dependency(OpenSSL)enquanto o binário foi compilado com base numa versão mais antiga do OpenSSL.
Mitigações / alternativas:
- Forneça uma compilação a partir do código-fonte utilizando scripts upstream ou adicione um wrapper fino de CMake.
- Peça à equipa responsável pelo código-fonte para publicar uma versão baseada no código-fonte ou instruções de compilação reproduzíveis; inclua o problema ou PR na origem num comentário em
portfile.cmakeouvcpkg.json. - Use uma porta de sobreposição ou um registo privado para pré-compilados específicos da organização que não podem satisfazer essas regras.
Versionamento
Siga as convenções comuns para o campo "version"
Ao criar uma nova porta, siga a convenção de controle de versão usada pelo autor do pacote. Ao atualizar a porta, continue a usar a mesma convenção, a menos que o upstream diga o contrário. Para obter uma explicação completa de nossas convenções, consulte nossa documentação de controle de versão .
Se o upstream não publicar uma versão há algum tempo, não altere o esquema de versionamento da porta para version-date para obter as alterações mais recentes. Esses compromissos podem incluir alterações que não estão prontas para produção. Em vez disso, solicite ao repositório de origem que publique uma nova versão.
Atualize o campo "port-version" no arquivo de manifesto de todas as portas modificadas
O VCPKG usa esse campo para determinar se uma determinada porta está desatualizada e deve ser alterada sempre que o comportamento da porta mudar.
Nossa convenção é usar o campo "port-version" para alterações na porta que não alterem a versão upstream e redefinir o "port-version" de volta a zero quando uma atualização para a versão upstream for feita.
Por exemplo:
- A versão do pacote Zlib está atualmente
1.2.1, sem"port-version"explícito (equivalente a um"port-version"de0). - Você descobriu que o arquivo de direitos autorais errado foi implantado e corrigiu isso no portfile.
- Você deve atualizar o campo
"port-version"no arquivo de manifesto para1.
Consulte a documentação de controlo de versão para obter mais informações.
Atualize os arquivos de versão em versions/ de quaisquer portas modificadas
O VCPKG usa um conjunto de arquivos de metadados para potencializar seu recurso de controle de versão. Esses arquivos estão localizados nos seguintes locais:
-
${VCPKG_ROOT}/versions/baseline.json, (este ficheiro é comum a todas as portas) e -
${VCPKG_ROOT}/versions/${first-letter-of-portname}-/${portname}.json(uma por porta).
Por exemplo, para zlib os ficheiros relevantes são:
${VCPKG_ROOT}/versions/baseline.json${VCPKG_ROOT}/versions/z-/zlib.json
Esperamos que cada vez que você atualiza uma porta, você também atualiza seus arquivos de versão.
O método recomendado para atualizar esses arquivos é executar o comando x-add-version, por exemplo:
vcpkg x-add-version zlib
Se você estiver atualizando várias portas ao mesmo tempo, em vez disso, poderá executar:
vcpkg x-add-version --all
para atualizar os arquivos de todas as portas modificadas de uma só vez.
Para obter mais informações, consulte o de referência de controle de versão e artigos Registros.
Aplicação de patches
VCPKG é uma solução de embalagem, não os proprietários finais dos componentes que implantamos. Precisamos aplicar patches em alguns casos para melhorar a compatibilidade de componentes com plataformas, ou compatibilidade de componentes entre si.
- Queremos evitar patches que:
- a entidade superior discordaria
- causar vulnerabilidades ou falhas
- somos incapazes de manter atualizações de versão upstream
- são grandes o suficiente para causar complicações de licença com o repositório vcpkg em si próprio
Notificar os responsáveis upstream para patches upstream relevantes
Se um patch puder ser útil a montante, o upstream deve ser notificado do conteúdo do patch. (Patches que implementam comportamento específico do vcpkg independente do upstream, como remover uma dependência interna, não exigem notificação.)
Para evitar situações em que o upstream discorde do patch, vamos esperar no mínimo 30 dias para aplicar tais patches.
Ignoraremos este período de espera se tivermos grande confiança de que a mudança está correta. Exemplos de patches de alta confiança incluem, mas não estão limitados a:
- Aceitação do upstream como um patch (por exemplo, retroportação de uma alteração específica de uma solicitação de pull que foi mesclada upstream).
- A adicionar
#includes ausentes. - Correções de código de produto pequenas e óbvias (por exemplo, inicializando uma variável não inicializada).
- Desativando componentes da compilação irrelevantes no vcpkg, como testes ou exemplos.
Prefira opções em vez de aplicar correções
É preferível definir opções em uma chamada para vcpkg_configure_xyz() em vez de corrigir as configurações diretamente.
Opções comuns que permitem evitar a aplicação de patches:
- [MSBUILD]
<PropertyGroup>configurações dentro do arquivo de projeto podem ser substituídas através de parâmetros/p: - [CMAKE] As chamadas para
find_package(XYz)nos scripts do CMake podem ser desativadas via-DCMAKE_DISABLE_FIND_PACKAGE_XYz=ON - [CMAKE] As variáveis de cache (declaradas como
set(VAR "value" CACHE STRING "Documentation")ouoption(VAR "Documentation" "Default Value")) podem ser substituídas apenas passando-as na linha de comando como-DVAR:STRING=Foo. Uma exceção notável é se o parâmetroFORCEfor passado paraset(). Para obter mais informações, consulte a documentação do CMakeset
Prefira baixar patches aprovados em vez de verificá-los na porta
Se um arquivo de patch aprovado ou mesclado puder ser obtido do upstream, as portas devem tentar baixá-los e aplicá-los em vez de tê-los como parte dos arquivos de porta. Este processo é preferido porque:
- Confirma que upstream aceitou as alterações no patch
- Simplifica o processo de revisão, transferindo o ónus para a etapa anterior
- Reduz o tamanho do repositório vcpkg para usuários que não estão usando o patch
- Evita conflitos de licença com o repositório vcpkg
Os patches devem ser baixados de um ponto final estável para evitar conflitos de SHA.
Ao baixar arquivos de patch de uma solicitação pull ou commit do GitHub e do GitLab, o parâmetro ?full_index=1 deve ser anexado ao URL de download.
Exemplos:
https://github.com/google/farmhash/pull/40.diff?full_index=1https://github.com/linux-audit/audit-userspace/commit/f8e9bc5914d715cdacb2edc938ab339d5094d017.patch?full_index=1https://gitlab.kitware.com/paraview/paraview/-/merge_requests/6375.diff?full_index=1
Prefira a aplicação de patches em vez da substituição de valores de VCPKG_<VARIABLE>
Algumas variáveis prefixadas com VCPKG_<VARIABLE> têm um CMAKE_<VARIABLE>equivalente.
No entanto, nem todos eles são passados para a compilação do pacote interno (veja a implementação: ferramenta do Windows).
Considere o seguinte exemplo:
set(VCPKG_C_FLAGS "-O2 ${VCPKG_C_FLAGS}")
set(VCPKG_CXX_FLAGS "-O2 ${VCPKG_CXX_FLAGS}")
Usando as cadeias de ferramentas internas do vcpkg, isto funciona, porque o valor de VCPKG_<LANG>_FLAGS é encaminhado para a variável CMAKE_LANG_FLAGS correspondente. Mas, uma cadeia de ferramentas personalizada que não reconhece as variáveis do vcpkgnão as encaminhará.
Por causa disso, é preferível corrigir o buildsystem diretamente ao definir CMAKE_<LANG>_FLAGS.
Minimizar correções
Ao fazer alterações numa biblioteca, procure minimizar a diferença final. Isso significa que você não deve reformatar o código-fonte upstream ao fazer alterações que afetem uma região. Ao desativar um condicional, é melhor adicionar um AND FALSE ou && 0 à condição do que excluir todas as linhas do condicional. Se uma região grande precisar ser desativada, é mais simples adicionar if(0) ou #if 0 ao redor da região em vez de excluir todas as linhas do patch.
Não adicione patches se a porta estiver desatualizada e atualizar a porta para uma versão mais recente resolveria o mesmo problema. vcpkg prefere atualizar portas em vez de corrigir versões desatualizadas.
Isso ajuda a manter o tamanho do repositório vcpkg baixo, bem como melhora a probabilidade de que o patch se aplique a versões futuras do código.
Não implementar recursos em patches
O objetivo do patching no vcpkg é permitir a compatibilidade com compiladores, bibliotecas e plataformas. Não se deve implementar novas funcionalidades em detrimento de seguir corretamente o processo de Código Aberto, como submeter um problema ou Pull Request (PR), entre outros.
Não crie testes/docs/exemplos por padrão
Ao enviar uma nova porta, verifique se há opções como BUILD_TESTS ou WITH_TESTS ou POCO_ENABLE_SAMPLES e verifique se os binários adicionais estão desativados. Isso minimiza os tempos de compilação e as dependências para o usuário médio.
Opcionalmente, você pode adicionar um recurso de test que permite a criação dos testes, no entanto, isso não deve estar na lista de Default-Features.
Permitir que os usuários existentes da biblioteca alternem para vcpkg
Não adicionar CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
A menos que o autor da biblioteca já esteja usando, não devemos usar essa funcionalidade CMake porque ela interage mal com modelos C++ e quebra certos recursos do compilador. As bibliotecas que não fornecem um arquivo .def e não usam declarações __declspec() simplesmente não oferecem suporte a compilações compartilhadas para Windows e devem ser marcadas como tal:
if(VCPKG_TARGET_IS_WINDOWS)
vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
endif()
Não renomeie binários fora dos nomes fornecidos pelo upstream
Isso significa que, se a biblioteca upstream tiver nomes diferentes em release e debug (libx versus libxd), a biblioteca de depuração não deverá ser renomeada para libx. Vice-versa, se a biblioteca upstream tiver o mesmo nome em release e debug, não devemos introduzir um novo nome.
Ressalva importante:
- Variantes estáticas e compartilhadas muitas vezes devem ser renomeadas para um esquema comum. Isto permite que os consumidores utilizem um nome comum e ignorem a ligação a jusante. Isto é seguro porque só disponibilizamos um de cada vez.
Se uma biblioteca gera ficheiros de integração do CMake (foo-config.cmake), a renomeação deve ser feita através da modificação direta da compilação do CMake em vez de simplesmente executar file(RENAME) sobre os ficheiros de saída/LIBs.
Finalmente, os arquivos DLL no Windows nunca devem ser renomeados pós-compilação porque quebra as LIBs geradas.
Manifestos
Exigimos que o arquivo de manifesto seja formatado. Use o seguinte comando para formatar todos os arquivos de manifesto:
> vcpkg format-manifest --all
Trigêmeos
Não estamos aceitando pedidos para adicionar trigêmeos não comunitários no momento. A promoção da comunidade para o status de triplete completo baseia-se principalmente no orçamento para o hardware necessário para testar esses tripletes e será impulsionada por métricas enviadas pelo vcpkg para maximizar a probabilidade de que o que as pessoas realmente usam seja totalmente testado.
Adicionaremos trigêmeos comunitários se:
- Está demonstrado que as pessoas vão realmente usar esse trio comunitário; e,
- não sabemos que tal trio está quebrado.
Por exemplo, não adicionamos um trio em https://github.com/microsoft/vcpkg/pull/29034 porque o autor estava apenas tentando "completar o conjunto" em vez de indicar que eles realmente usariam tal coisa, e não adicionamos linux-dynamic até que a solução patchelf para tornar os resultados relocáveis fosse criada.
Notas de implementação úteis
Portfiles são executados no modo de script
Enquanto portfile.cmakee CMakeLists.txtcompartilham uma sintaxe comum e construções principais da linguagem CMake (também conhecidas como "Comandos de Script"), os portfiles são executados em "Modo de Script", enquanto os arquivos CMakeLists.txt são executados em "Modo de Projeto". A diferença mais importante entre estes dois modos é que o "Modo Script" não tem os conceitos de "Toolchain", "Language" e "Target". Quaisquer comportamentos, incluindo comandos de script, que dependem dessas construções (por exemplo, CMAKE_CXX_COMPILER, CMAKE_EXECUTABLE_SUFFIX, CMAKE_SYSTEM_NAME) não estarão corretos.
Portfiles têm acesso direto às variáveis definidas no arquivo tríptico, mas CMakeLists.txtnão têm (embora frequentemente ocorra uma tradução -- VCPKG_LIBRARY_LINKAGE versus BUILD_SHARED_LIBS).
Portfiles e compilações de projeto invocadas por portfiles são executadas em processos diferentes. 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 o host em um portfile, as variáveis CMake padrão são boas (CMAKE_HOST_WIN32).
Para determinar o destino em um portfile, as variáveis triplete vcpkg devem ser usadas (VCPKG_CMAKE_SYSTEM_NAME).
Consulte a nossa documentação do triplet ,, para uma enumeração completa das configurações possíveis.