2009-03-30 11 views

Respuesta

32

Con CMake 2.8, use el comando file(COPY ...).

Con versiones anteriores de CMake, esta macro copia archivos de un directorio a otro. Si no desea sustituir variables en los archivos copiados, cambie el argumento configure_file @ONLY.

# Copy files from source directory to destination directory, substituting any 
# variables. Create destination directory if it does not exist. 

macro(configure_files srcDir destDir) 
    message(STATUS "Configuring directory ${destDir}") 
    make_directory(${destDir}) 

    file(GLOB templateFiles RELATIVE ${srcDir} ${srcDir}/*) 
    foreach(templateFile ${templateFiles}) 
     set(srcTemplatePath ${srcDir}/${templateFile}) 
     if(NOT IS_DIRECTORY ${srcTemplatePath}) 
      message(STATUS "Configuring file ${templateFile}") 
      configure_file(
        ${srcTemplatePath} 
        ${destDir}/${templateFile} 
        @ONLY) 
     endif(NOT IS_DIRECTORY ${srcTemplatePath}) 
    endforeach(templateFile) 
endmacro(configure_files) 
+0

Es fácil copiar archivos o directorios cuando se usa el modo cmake -E. Muchas gracias –

+0

Editado porque esta es la respuesta aceptada y la otra respuesta con el archivo (el comando COPY es más limpio. –

+3

Sí, pero ¿puede ejecutar el archivo (COPY ...) como un comando personalizado que depende del objetivo? – juzzlin

13

Use execute_process y llame a cmake -E. Si desea una copia profunda, puede usar el comando copy_directory. Aún mejor, podría crear un symlink (si su plataforma lo admite) con el comando create_symlink. Este último se puede lograr de esta manera:

execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/path/to/www 
                  ${CMAKE_BINARY_DIR}/path/to/www) 

Desde: http://www.cmake.org/pipermail/cmake/2009-March/028299.html

+3

El único problema con esto es que rompe el concepto de compilaciones fuera de la fuente si los archivos temporales se producen en el directorio. –

24

El comando configure sólo copiar los archivos cuando se ejecuta cmake. Otra opción es crear un nuevo objetivo y usar la opción custom_command. Aquí hay uno que uso (si lo ejecuta más de una vez, tendrá que modificar la línea add_custom_target para que sea único para cada llamada).

macro(copy_files GLOBPAT DESTINATION) 
    file(GLOB COPY_FILES 
    RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} 
    ${GLOBPAT}) 
    add_custom_target(copy ALL 
    COMMENT "Copying files: ${GLOBPAT}") 

    foreach(FILENAME ${COPY_FILES}) 
    set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}") 
    set(DST "${DESTINATION}/${FILENAME}") 

    add_custom_command(
     TARGET copy 
     COMMAND ${CMAKE_COMMAND} -E copy ${SRC} ${DST} 
    ) 
    endforeach(FILENAME) 
endmacro(copy_files) 
+1

+1 Porque realmente puede usar esto como un POST_BUILD paso – BeRecursive

+0

He adaptado su (sorprendente) respuesta para tener una más script modular. Ver mi respuesta! – Salamandar

101

Desde la versión 2.8, la file command tiene un argumento copia:

file(COPY yourDir DESTINATION yourDestination) 

Tenga en cuenta que:

rutas de entrada

relativos se evaluaron con respecto al directorio actual fuente , y una el destino relativo se evalúa con respecto al directorio de compilación actual

+1

funciona para directorios? – batman

+3

Esto parece prometedor. ¿Puede explicar cómo se activa esto, o se ejecuta cada vez? –

+2

Funciona para directorios. – m01

2

¡Gracias! Ese es un consejo muy útil para usar el grupo de add_custom_target y add_custom_command. Escribí la siguiente función para usar en todas partes en mis proyectos. También especifica la regla de instalación. Lo uso principalmente para exportar archivos de encabezado de interfaz.

# 
# export file: copy it to the build tree on every build invocation and add rule for installation 
# 
function (cm_export_file FILE DEST) 
    if (NOT TARGET export-files) 
    add_custom_target(export-files ALL COMMENT "Exporting files into build tree") 
    endif (NOT TARGET export-files) 
    get_filename_component(FILENAME "${FILE}" NAME) 
    add_custom_command(TARGET export-files COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}" "${CMAKE_CURRENT_BINARY_DIR}/${DEST}/${FILENAME}") 
    install(FILES "${FILE}" DESTINATION "${DEST}") 
endfunction (cm_export_file) 

uso es el siguiente:

cm_export_file("API/someHeader0.hpp" "include/API/") 
cm_export_file("API/someHeader1.hpp" "include/API/") 
+0

Esto parece interesante. Copia directorios enteros? –

11

Como nadie ha mencionado cmake -E copy_directory como un objetivo a medida, esto es lo que he usado:

add_custom_target(copy-runtime-files ALL 
    COMMAND cmake -E copy_directory ${CMAKE_SOURCE_DIR}/runtime-files-dir ${CMAKE_BINARY_DIR}/runtime-files-dir 
    DEPENDS ${MY_TARGET}) 
+0

Corto y fácil, estupendo. Si suelta 'DEPENDS $ {MY_TARGET}', esto puede ejecutarse en paralelo al proceso de compilación. Tenga en cuenta que los archivos se copian cada vez que 'make' se está ejecutando, por lo que puede tener limitaciones con carpetas muy grandes. –

+0

Me sale 'Esperaba un nombre de comando, obtengo un argumento sin cita con el texto"/runtime-files-dir ".' para esto :( – Sorona

1

Sobre la base de la respuesta de Seth Johnson, eso es lo que escribí para mayor comodidad.

# Always define the target 
add_custom_target(copy_resources ALL COMMENT "Copying resources…") 

# Copy single files 
macro(add_files_to_environment files) 
    add_custom_command(TARGET copy_resources POST_BUILD 
     COMMAND ${CMAKE_COMMAND} -E copy ${ARGV} ${CMAKE_CURRENT_BINARY_DIR}) 
endmacro() 

# Copy full directories 
macro(add_directory_to_environment distant local_name) 
    file(GLOB_RECURSE DistantFiles 
     RELATIVE ${distant} 
     ${distant}/*) 
    foreach(Filename ${DistantFiles}) 
     set(SRC "${distant}/${Filename}") 
     set(DST "${CURRENT_BUILD_DIR}/${local_name}/${Filename}") 
     add_custom_command(TARGET copy_resources POST_BUILD 
      COMMAND ${CMAKE_COMMAND} -E copy ${SRC} ${DST}) 

     message(STATUS "file ${Filename}") 
    endforeach(Filename) 
endmacro() 

EDITAR: Eso realmente no funciona como se esperaba. Este funciona a la perfección.

# Copy single files 
macro(resource_files files) 
    foreach(file ${files}) 
     message(STATUS "Copying resource ${file}") 
     file(COPY ${file} DESTINATION ${Work_Directory}) 
    endforeach() 
endmacro() 

# Copy full directories 
macro(resource_dirs dirs) 
    foreach(dir ${dirs}) 
     # Replace/at the end of the path (copy dir content VS copy dir) 
     string(REGEX REPLACE "/+$" "" dirclean "${dir}") 
     message(STATUS "Copying resource ${dirclean}") 
     file(COPY ${dirclean} DESTINATION ${Work_Directory}) 
    endforeach() 
endmacro() 
Cuestiones relacionadas