Adicionar automaticamente todos os arquivos em uma pasta a um destino usando o CMake?

163

Estou pensando em mudar um projeto de plataforma cruzada de sistemas separados de gerenciamento de compilação no Visual C ++, XCode e makefiles para o CMake.

Um recurso essencial que preciso é adicionar automaticamente todos os arquivos em um diretório a um destino. Embora isso seja fácil de fazer com make, não é possível com o Visual C ++ e o XCode (corrija-me se estiver errado). É possível fazer isso diretamente no CMake? Quão?

martjno
fonte
Btw. No Visual Studio, pelo menos nos projetos C #, há um botão da barra de ferramentas no explorador de projetos, chamado show all files. Torna todos os subdiretórios de um projeto visíveis, acinzentados se não contiverem nenhum arquivo incluído logicamente no projeto. Você pode incluir esses diretórios através do menu de contexto, que inclui todos os arquivos fonte dentro deles, de forma recursiva :)
yeoman

Respostas:

228

É possível. Por exemplo, com file(GLOB:

cmake_minimum_required(VERSION 2.8)

file(GLOB helloworld_SRC
    "*.h"
    "*.cpp"
)

add_executable(helloworld ${helloworld_SRC})

Observe que isso requer nova execução manual de cmakese um arquivo de origem for adicionado ou removido, pois o sistema de compilação gerado não sabe quando pedir ao CMake para se regenerar, e fazê-lo a cada compilação aumentaria o tempo de compilação.

Kleist
fonte
11
Uma alternativa para executar novamente o cmake manualmente é tocar no arquivo CMakeLists.txt antes de executar o make.
Seamus Connor
8
> "Não recomendamos o uso do GLOB para coletar uma lista de arquivos de origem da sua árvore de origem. Se nenhum arquivo CMakeLists.txt for alterado quando uma fonte for adicionada ou removida, o sistema de criação gerado não poderá saber quando pedir ao CMake para se regenerar." Isso não é mais recomendado nos documentos do CMAKE3.7 vinculados por Hand1Cloud
triple
4
qual é a alternativa ao GLOB então?
quer
13
Uma maneira melhor desde a v3.1 é sugerida aqui: target_sources () crascit.com/2016/01/31/…
Sheen
34

A resposta de Kleist certamente funciona, mas há uma ressalva importante:

Quando você escreve um Makefilemanualmente, você pode gerar uma SRCSvariável usando uma função para selecionar todos .cppe .harquivos. Se um arquivo de origem for adicionado posteriormente, a reexecução makeo incluirá.

No entanto, o CMake (com um comando como file(GLOB ...)) irá gerar explicitamente uma lista de arquivos e colocá-la na geração automática Makefile. Se você tiver um novo arquivo de origem, precisará gerar Makefilenovamente, reexecutando cmake.

editar: Não há necessidade de remover o Makefile.

kara deniz
fonte
4
O cmake não pode simplesmente ser executado novamente, o que deve remover / modificar o Makefile desatualizado?
Ethan
25
Esta não é uma resposta, é um comentário sobre a resposta de @ Kleist.
Neowizard 30/07/16
3
@ Neowizard não está na terminologia Stackoverflow.
Kara deniz
1
Esse comentário é legal, mas é "padrão", certo? O solicitante já está usando o cmake, então sugerir make pode ser "mais inteligente" não é tão útil.
frankliuao
Então, existe uma maneira de adicionar novos arquivos de origem e depois compilar sem executar o cmake?
Artin 29/04/19
6

Extensão para a resposta @Kleist :

Desde o CMake 3.12, a opção adicional CONFIGURE_DEPENDS é suportada pelos comandos file(GLOB)e file(GLOB_RECURSE). Com esta opção não existe nenhuma necessidade para manualmente CMake re-executar após a adição / exclusão de um arquivo de origem no diretório - CMake serão automaticamente na próxima construção do projeto re-run.

No entanto, a opção CONFIGURE_DEPENDS implica que o diretório correspondente seja verificado novamente toda vez que a construção for solicitada, portanto, o processo de construção consumiria mais tempo do que sem CONFIGURE_DEPENDS .

Mesmo com a opção CONFIGURE_DEPENDS disponível, a documentação do CMake ainda não recomenda o uso file(GLOB)ou file(GLOB_RECURSE)a coleta de fontes.

Tsyvarev
fonte
"A documentação do CMake ainda não recomenda o uso file(GLOB)ou file(GLOB_RECURSE)a coleta de fontes" O que eles recomendam então? Usando outra coisa para coletar as fontes ou listar manualmente todos os arquivos de origem?
Thomas
1
@ Thomas: Eles recomendam listar manualmente todos os arquivos de origem. Essa resposta fornece uma ótima explicação para a recomendação.
Tsyvarev
-2

Então, por que não usar o powershell para criar a lista de arquivos de origem para você. Dê uma olhada neste script

param (
    [Parameter(Mandatory=$True)]
    [string]$root 
)

if (-not (Test-Path  -Path $root)) {    
throw "Error directory does not exist"
}

#get the full path of the root
$rootDir = get-item -Path $root
$fp=$rootDir.FullName;


$files = Get-ChildItem -Path $root -Recurse -File | 
         Where-Object { ".cpp",".cxx",".cc",".h" -contains $_.Extension} | 
         Foreach {$_.FullName.replace("${fp}\","").replace("\","/")}

$CMakeExpr = "set(SOURCES "

foreach($file in $files){

    $CMakeExpr+= """$file"" " ;
}
$CMakeExpr+=")"
return $CMakeExpr;

Suponha que você tenha uma pasta com essa estrutura

C:\Workspace\A
--a.cpp
C:\Workspace\B 
--b.cpp

Agora salve este arquivo como "generateSourceList.ps1", por exemplo, e execute o script como

~>./generateSourceList.ps1 -root "C:\Workspace" > out.txt

O arquivo out.txt conterá

set(SOURCE "A/a.cpp" "B/b.cpp")
alcoforado
fonte
A pergunta está marcada com várias plataformas - o powershell não é multiplataforma.
reichhart 07/04
@reichhart powershell também funciona em linux e mac
noone
Eu sei. Mas não há tag para o PowerShell e o "CMake" já é uma plataforma cruzada. O "PowerShell" seria uma dependência adicional e é muito raramente usado em outro sistema operacional que não o Windows. Você pode encontrar ainda mais desenvolvedores de C # no Linux do que pessoas com PowerShell. E o fato mais importante é a pergunta: "É possível fazer isso diretamente no CMake? Como?"
reichhart