Qual é a diferença entre include_directories e target_include_directories no CMake?

134

Eu tenho uma estrutura de diretório para o meu código C ++ que é assim:

|
|->include
|->src

Estou escrevendo um arquivo CMakeLists.txt para o meu código. Eu quero entender a diferença entre include_directoriese target_include_directoriesem CMake.

Qual é a diferença entre o uso e para adicionar o caminho do arquivo de inclusão que devo usar?

Ujjwal Aryan
fonte
4
Você leu a documentação para include_directoriese target_include_directories? O que você não entende sobre a diferença entre eles?
Algum cara programador
74
Não há clareza na documentação. Eu li e supus o que Angew escreveu em sua resposta, mas não há descrições, nem exemplos; para um sistema destinado à criação de projetos, não há exemplos baseados em projetos na documentação do CMake. Se houvesse uma documentação boa e exaustiva do CMake, eu não estaria sobrecarregando a comunidade com essas perguntas.
Ujjwal Aryan
Os conceitos de cmake estão mal documentados. Particularmente alvo e "não segmentado".
John Greene

Respostas:

148

include_directories(x/y)afeta o escopo do diretório. Todos os destinos neste CMakeList, bem como aqueles em todos os subdiretórios adicionados após o ponto de sua chamada, terão o caminho x/yadicionado ao seu caminho de inclusão.

target_include_directories(t x/y)tem escopo de destino - ele adiciona x/yao caminho de inclusão do destino t.

Você deseja o primeiro se todos os seus destinos usarem os diretórios de inclusão em questão. Você deseja o último se o caminho for específico para um destino ou se desejar um controle mais preciso da visibilidade do caminho. Este último vem do fato de que target_include_directories()suporta os PRIVATE, PUBLICe INTERFACEqualificadores.

Angew não se orgulha mais de SO
fonte
35
Eu acho que o último geralmente deve ser preferido (desde que você esteja usando o cmake 3). Ele tem o benefício adicional de x/yincluir o caminho de inclusão de qualquer destino dependente que use tem seus target_link_librariescomandos. É claro que há um lugar para o primeiro, mas acredito que o último seja geralmente melhor.
Phil
2
A resposta original afirmou que apenas os alvos e subdiretórios adicionados após include_directoriesserão afetados. Estou editando a resposta: a documentação afirma claramente que todos os alvos nas CMakeLists atuais são afetados. A documentação não menciona, mas apenas subdirs depois da chamada são afetados (como foi correctamente indicado na resposta original)
tamas.kenez
@Phil, target_include_directoriesfoi introduzido no CMake 2.8.11 (maio de 2013)
tamas.kenez
@ tamas.kenez Obrigado por trazer isso à minha atenção, corrigido. Eu estava bastante convencido de que era uma coisa "de agora em diante".
Angew não está mais orgulhoso de SO
40

Ao lado do que a resposta de Angew diz corretamente, outra diferença muito importante entre include_directoriese target_include_directoriesé que, quando usado com PUBLICou INTERFACE, o último preenche a INTERFACE_INCLUDE_DIRECTORIESpropriedade do alvo. Essa propriedade é útil quando outro destino usa target_link_librariespara vincular ao destino original, pois o destino de vinculação terá automaticamente os diretórios incluídos. Veja exemplo .

Esse recurso importante está muito bem oculto na documentação: target_include_directories menciona preenchimento INTERFACE_INCLUDE_DIRECTORIES, cuja documentação diz:

Quando as dependências de destino são especificadas usando target_link_libraries () , o CMake lê essa propriedade de todas as dependências de destino para determinar as propriedades de construção do consumidor.

Antonio
fonte
Esta é a primeira vez que li uma explicação compreensível das PUBLICpropriedades etc.! Obrigado: D
RL-S
2

Como o @Angew disse, a grande diferença é:

1, include_directories () é acessível para todos os arquivos na árvore de origem 2, target_include_directories () é acessível apenas para um destino específico durante a compilação.

Nick.Rhan
fonte