¿Agregar automáticamente todos los archivos en una carpeta a un destino usando CMake?

163

Estoy considerando cambiar un proyecto multiplataforma de sistemas de administración de compilación separados en Visual C ++, XCode y makefiles a CMake.

Una característica esencial que necesito es agregar automáticamente todos los archivos en un directorio a un destino. Si bien esto es fácil de hacer con make, no es fácil de hacer con Visual C ++ y XCode (corrígeme si estoy equivocado). ¿Es posible hacerlo directamente en CMake? ¿Cómo?

martjno
fuente
Por cierto. En Visual Studio, al menos en proyectos de C #, hay un botón de barra de herramientas en el explorador de proyectos, llamado mostrar todos los archivos. Hace todos los subdirectorios de un proyecto visibles, atenuados si no contienen ningún archivo incluido lógicamente en el proyecto. Puede incluir estos directorios a través del menú contextual, que incluye todos los archivos fuente dentro de ellos, de forma recursiva :)
yeoman

Respuestas:

228

Es posible. Por ejemplo con file(GLOB:

cmake_minimum_required(VERSION 2.8)

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

add_executable(helloworld ${helloworld_SRC})

Tenga en cuenta que esto requiere una ejecución manualcmake si se agrega o elimina un archivo fuente, ya que el sistema de compilación generado no sabe cuándo pedirle a CMake que se regenere, y hacerlo en cada compilación aumentaría el tiempo de compilación.

Kleist
fuente
11
Una alternativa para volver a ejecutar manualmente cmake es tocar el archivo CMakeLists.txt antes de ejecutar make.
Seamus Connor
8
> "No recomendamos utilizar GLOB para recopilar una lista de archivos fuente de su árbol fuente. Si no cambia el archivo CMakeLists.txt cuando se agrega o elimina una fuente, el sistema de compilación generado no puede saber cuándo pedirle a CMake que se regenere". Esto ya no se recomienda en los documentos CMAKE3.7 vinculados por Hand1Cloud
triple
44
¿Cuál es la alternativa a GLOB entonces?
Shayne
13
Aquí se sugiere una mejor manera desde v3.1: target_sources () crascit.com/2016/01/31/…
Sheen
34

La respuesta de Kleist ciertamente funciona, pero hay una advertencia importante:

Cuando escribe un Makefilemanual, puede generar una SRCSvariable usando una función para seleccionar todos .cppy .harchivos. Si luego se agrega un archivo de origen, volver a ejecutarlo makelo incluirá.

Sin embargo, CMake (con un comando como file(GLOB ...)) generará explícitamente una lista de archivos y la colocará en el autogenerado Makefile. Si tiene un nuevo archivo fuente, deberá volver a generarlo Makefilevolviendo a ejecutarlo cmake.

editar: no es necesario eliminar el Makefile.

kara deniz
fuente
44
¿No se puede volver a ejecutar cmake, lo que debería eliminar / modificar el Makefile desactualizado?
Ethan
25
Esta no es una respuesta, es un comentario sobre la respuesta de @ Kleist.
Neowizard
3
@Neowizard no está en la terminología de Stackoverflow.
kara deniz
1
Este comentario es bueno, pero es "estándar", ¿verdad? El autor de la pregunta ya está utilizando cmake, por lo que sugerir que make pueda ser "más inteligente" no es tan útil.
frankliuao
Entonces, ¿hay alguna manera de agregar nuevos archivos fuente y luego construir sin volver a ejecutar cmake?
artin
6

Extensión para la respuesta @Kleist :

Desde CMake 3.12, la opción adicional CONFIGURE_DEPENDS es compatible con comandos file(GLOB)yfile(GLOB_RECURSE) . Con esta opción hay ninguna necesidad a manualmente volver a ejecutar CMake después de la adición / eliminación de un archivo de origen en el directorio - CMake se volverá a funcionar automáticamente en la próxima construcción del proyecto.

Sin embargo, la opción CONFIGURE_DEPENDS implica que el directorio correspondiente se volverá a verificar cada vez que se solicite la construcción, por lo que el proceso de construcción consumiría más tiempo que sin CONFIGURE_DEPENDS .

Incluso con la opción CONFIGURE_DEPENDS disponible, la documentación de CMake todavía no recomienda usar file(GLOB)o file(GLOB_RECURSE)recopilar las fuentes.

Tsyvarev
fuente
"La documentación de CMake todavía no recomienda usar file(GLOB)o file(GLOB_RECURSE)para recopilar las fuentes" ¿Qué recomiendan entonces? ¿Usa algo más para recopilar las fuentes o para enumerar manualmente cada archivo fuente?
Thomas hace
1
@Thomas: recomiendan enumerar manualmente cada archivo fuente. Esa respuesta da una gran explicación de la recomendación.
Tsyvarev
-2

Entonces, ¿por qué no usar powershell para crear la lista de archivos fuente para usted? Echa un vistazo a este 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;

Supongamos que tiene una carpeta con esta estructura

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

Ahora guarde este archivo como "generateSourceList.ps1", por ejemplo, y ejecute el script como

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

El archivo out.txt contendrá

set(SOURCE "A/a.cpp" "B/b.cpp")
alcoforado
fuente
La pregunta está etiquetada multiplataforma: PowerShell no es multiplataforma.
Reichhart
@reichhart powershell también funciona en Linux y Mac
nadie el
Lo sé. Pero no hay una etiqueta para powershell y "CMake" ya es una plataforma cruzada. "Powershell" sería una dependencia adicional y rara vez se usa en otro sistema operativo que no sea Windows. Es posible que encuentre aún más desarrolladores de C # en Linux que personas con powershell. Y el hecho más importante es la pregunta: "¿Es posible hacerlo directamente en CMake? ¿Cómo?"
Reichhart