Use bibliotecas habilitadas para CMake em seu projeto CMake (II)


Resumo

Neste protocolo, analiso as desvantagens de usar projetos externos para implementar projetos com várias bibliotecas.

Nota: Existe um artigo anterior (I) e um seguimento a este (III) .


No artigo anterior sobre este assunto, mostrei uma forma de implementar projetos de multi-biblioteca por meio de um ExternalProject_Addregistro de exportação CMake. A solução nos permitiu incluir fontes de biblioteca de terceiros como se estivessem instaladas no sistema (ou seja, com find_package). As soluções não estão isentas de inconvenientes. Depois de usar essa implementação por um tempo, descobri alguns efeitos decepcionantes.

Inconvenientes

As sub-bibliotecas B e C (consulte o artigo anterior ) são construídas como projetos externos. Projetos externos são configurados em tempo de execução. Na verdade, o fluxo de trabalho CMake consiste aproximadamente em 2 etapas: o tempo de configuração e o tempo de execução. O tempo de configuração é quando os cmakeprocessos são nossos CMakeLists.txt. O tempo de execução é o tempo que executamos makeou qualquer ferramenta de compilação que escolhemos. Como resultado disso, o que é explicado no meu artigo anterior não funcionará como esperado:

  • Não é possível fazer referência a destinos nas sub-bibliotecas : isso é algo que já sabíamos e é uma vantagem / desvantagem de usar projetos externos. Somos obrigados a usar arquivos de configuração , o que me leva ao próximo ponto. <br>
  • Os arquivos de configuração ( ) de B e C não são escritos enquanto A está sendo configurado*-config.cmake : de fato, o fato de os projetos externos serem configurados em tempo de execução, faz com que os arquivos de configuração de B e C não sejam escritos no tempo de configuração de A, resultando em e não está funcionando. <br>find_package(A)find_package(B)

Solução

Supondo que o primeiro problema não possa ser resolvido, para resolver o segundo, podemos fazer duas coisas (ambas comentadas neste post ): uma solução é implementar A ainda como outro projeto externo, às vezes referido como a solução “superbuild”, uma vez que nosso top-most não faz nada além de orquestrar vários projetos externos, incluindo nosso projeto A root:CMakeLists.txt

CMakeLists.txt // "superbuild" make list
B
/
CMakeLists.txt
C
/
CMakeLists.txt // depends on B
A
/
CMakeLists.txt // depends on B and C

Precisamos apenas garantir, na raiz , que A seja compilado após C e C, por sua vez, após B:CMakeLists.txt

ExternalProject_Add (  B ... )
ExternalProject_Add ( C ... DEPENDS B )
ExternalProject_Add ( A ... DEPENDS B C )

Outra solução é manter A como projeto raiz e fazer uso de bibliotecas importadas , desde que saibamos onde B e C são criados. ExternalProject_Get_Propertynos dê algumas pistas, mas eventualmente teremos que codificar o caminho para eles. Esta solução também é retratada no post anterior e aqui . Não gosto muito da solução, pois é um pouco hacky , mas devo admitir que é simples.

Sim … um pouco decepcionante. Como você lida com projetos de várias bibliotecas? Deixe-me saber nos comentários! Espero que este protocolo tenha sido útil!