De alguma forma, estou totalmente confuso com a forma como o CMake funciona. Cada vez que penso que estou chegando mais perto de entender como CMake deve ser escrito, ele desaparece no próximo exemplo que leio. Tudo que eu quero saber é como devo estruturar meu projeto, para que meu CMake exija o mínimo de manutenção no futuro. Por exemplo, não quero atualizar meu CMakeList.txt quando estou adicionando uma nova pasta em minha árvore src, que funciona exatamente como todas as outras pastas src.
É assim que imagino a estrutura do meu projeto, mas, por favor, este é apenas um exemplo. Se a forma recomendada for diferente, diga-me e diga-me como fazê-lo.
myProject
src/
module1/
module1.h
module1.cpp
module2/
[...]
main.cpp
test/
test1.cpp
resources/
file.png
bin
[execute cmake ..]
A propósito, é importante que meu programa saiba onde estão os recursos. Gostaria de saber a forma recomendada de gerenciamento de recursos. Não desejo acessar meus recursos com "../resources/file.png"
fonte
For example I don't want to update my CMakeList.txt when I am adding a new folder in my src tree
você pode dar um exemplo de IDE que coleta fontes automaticamente?Respostas:
depois de alguma pesquisa, agora tenho minha própria versão do exemplo cmake mais simples, mas completo. Aqui está, e ele tenta cobrir a maior parte do básico, incluindo recursos e pacotes.
uma coisa que ele faz fora do padrão é o manuseio de recursos. Por padrão, o cmake deseja colocá-los em / usr / share /, / usr / local / share / e algo equivalente no Windows. Eu queria ter um zip / tar.gz simples que você pudesse extrair de qualquer lugar e executar. Portanto, os recursos são carregados em relação ao executável.
a regra básica para entender os comandos cmake é a seguinte sintaxe:
<function-name>(<arg1> [<arg2> ...])
sem vírgula ou semicolor. Cada argumento é uma string.foobar(3.0)
efoobar("3.0")
é o mesmo. você pode definir listas / variáveis comset(args arg1 arg2)
. Com esta variável definidafoobar(${args})
efoobar(arg1 arg2)
são efetivamente os mesmos. Uma variável inexistente é equivalente a uma lista vazia. Uma lista é internamente apenas uma string com ponto e vírgula para separar os elementos. Portanto, uma lista com apenas um elemento é, por definição, apenas esse elemento, nenhum boxing ocorre. As variáveis são globais. Funções embutidas oferecem alguma forma de argumentos nomeados pelo fato de que eles esperam alguns ids comoPUBLIC
ouDESTINATION
em sua lista de argumentos, para agrupar os argumentos. Mas isso não é um recurso de linguagem, esses ids também são apenas strings e analisados pela implementação da função.você pode clonar tudo do github
fonte
set(sources src/main.cpp)
.CMakeLists.txt
, então um make normal (ou ninja) irá acionar a reinvocação do cmake, então você não pode esquecê-lo. Também é um pouco mais amigável com a equipe, porque assim os membros da equipe também não podem se esquecer de executar o cmake. Mas eu acho que um makefile não precisa ser alterado, só porque alguém adicionou um arquivo. Escreva uma vez e ninguém precisará pensar sobre isso nunca mais.O exemplo mais básico, mas completo, pode ser encontrado no tutorial CMake :
Para o exemplo do seu projeto, você pode ter:
Para sua pergunta adicional, uma maneira de prosseguir é novamente no tutorial: crie um arquivo de cabeçalho configurável que você inclui em seu código. Para isso, faça um arquivo
configuration.h.in
com o seguinte conteúdo:Em seguida, em seu
CMakeLists.txt
add:Finalmente, onde precisar do caminho em seu código, você pode fazer:
fonte
string resourcePath = string(RESOURCE_PATH) + "file.png"
IMHO, é uma má ideia codificar o caminho absoluto para o diretório de origem. E se você precisar instalar seu projeto?Aqui, escrevo um exemplo de arquivos CMakeLists.txt mais simples, mas completo.
Código fonte
Depois disso, ofereci documento para os detalhes.
Se você tiver alguma dúvida, pode entrar em contato comigo e eu gostaria de explicar.
fonte