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_Add
registro 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 cmake
processos são nossos CMakeLists.txt
. O tempo de execução é o tempo que executamos make
ou 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_Property
nos 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!