Buscando un comando ‘cmake clean’ para borrar la salida cmake

Así como make clean elimina todos los archivos que ha producido un archivo MAKE, me gustaría hacer lo mismo con CMake. Demasiado a menudo me encuentro pasando manualmente por directorios eliminando archivos como cmake_install.cmake y CMakeCache.txt , y las carpetas CMakeFiles .

¿Existe un comando como cmake clean para eliminar todos estos archivos automáticamente? Idealmente, esto debería seguir la estructura recursiva definida en el archivo CMakeLists.txt del directorio actual.

No hay cmake clean .

Normalmente construyo el proyecto en una sola carpeta como “comstackr”. Entonces, si quiero make clean , puedo simplemente rm -rf build .

La carpeta “comstackr” en el mismo directorio que la raíz “CMakeLists.txt” suele ser una buena opción. Para construir su proyecto, simplemente déle a cmake la ubicación de CMakeLists.txt como argumento. Por ejemplo: cd /build && cmake .. (Desde @ComicSansMS)

Las preguntas frecuentes oficiales de CMake dicen :

Algunos árboles de comstackción creados con autotools GNU tienen un objective “make distclean” que limpia la comstackción y también elimina Makefiles y otras partes del sistema de comstackción generado. CMake no genera un destino “make distclean” porque los archivos CMakeLists.txt pueden ejecutar scripts y comandos arbitrarios; CMake no tiene forma de rastrear exactamente qué archivos se generan como parte de ejecutar CMake. Proporcionar un objective distclean daría a los usuarios la falsa impresión de que funcionaría como se esperaba. (CMake genera un objective “make clean” para eliminar los archivos generados por el comstackdor y el enlazador).

Un objective “make distclean” solo es necesario si el usuario realiza una comstackción en origen. CMake admite comstackciones in-source, pero recomendamos encarecidamente a los usuarios que adopten la noción de una comstackción fuera de la fuente. Usar un árbol de construcción que esté separado del árbol fuente evitará que CMake genere ningún archivo en el árbol fuente. Como CMake no cambia el árbol fuente, no hay necesidad de un destino distclean. Uno puede comenzar una comstackción nueva eliminando el árbol de comstackción o creando un árbol de comstackción por separado.

Lo busqué en Google durante media hora y la única cosa útil que se me ocurrió fue invocar la utilidad de find :

 # Find and then delete all files under current directory (.) that: # 1. contains cmake (case-&insensitive) in it's path (wholename) # 2. name is not CMakeLists.txt find . -iwholename '*cmake*' -not -name CMakeLists.txt -delete 

Además, asegúrese de invocar make clean (o cualquier generador de cmake que esté utilizando) antes de eso.

🙂

En estos días de git en todas partes, puede olvidarse de CMake y usar git clean -d -f -x , que eliminará todos los archivos que no estén bajo el control de código fuente.

Puedes usar algo como:

 add_custom_target(clean-cmake-files COMMAND ${CMAKE_COMMAND} -P clean-all.cmake ) // clean-all.cmake set(cmake_generated ${CMAKE_BINARY_DIR}/CMakeCache.txt ${CMAKE_BINARY_DIR}/cmake_install.cmake ${CMAKE_BINARY_DIR}/Makefile ${CMAKE_BINARY_DIR}/CMakeFiles ) foreach(file ${cmake_generated}) if (EXISTS ${file}) file(REMOVE_RECURSE ${file}) endif() endforeach(file) 

Normalmente creo un comando “make clean-all” que agrega al ejemplo anterior una llamada a “make clean”:

 add_custom_target(clean-all COMMAND ${CMAKE_BUILD_TOOL} clean COMMAND ${CMAKE_COMMAND} -P clean-all.cmake ) 

No intente agregar el objective “limpio” como dependencia:

 add_custom_target(clean-all COMMAND ${CMAKE_COMMAND} -P clean-all.cmake DEPENDS clean ) 

Porque “limpio” no es un objective real en CMake y esto no funciona. Además, no deberías usar este “clean-cmake-files” como dependencia de nada:

 add_custom_target(clean-all COMMAND ${CMAKE_BUILD_TOOL} clean DEPENDS clean-cmake-files ) 

Porque, si haces eso, todos los archivos cmake se borrarán antes de que se complete clean-all, y make te arrojará un error al buscar “CMakeFiles / clean-all.dir / build.make”. En consecuencia, no puede usar el comando clean-all antes de “cualquier cosa” en ningún contexto:

 add_custom_target(clean-all COMMAND ${CMAKE_BUILD_TOOL} clean COMMAND ${CMAKE_COMMAND} -P clean-all.cmake ) 

Esto tampoco funciona.

Simplemente emitir rm CMakeCache.txt funciona para mí.

Estoy de acuerdo en que la construcción fuera de la fuente es la mejor respuesta. Pero para los tiempos en que solo debes hacer una comstackción en fuente, he escrito un script de Python disponible aquí , que:

  1. Corre “hacer limpio”
  2. Elimina archivos específicos generados por cmake en el directorio de nivel superior como CMakeCache.txt
  3. Para cada subdirectorio que contiene un directorio CMakeFiles, elimina CMakeFiles, Makefile, cmake_install.cmake.
  4. Elimina todos los subdirectorios vacíos.

Una solución que encontré recientemente es combinar el concepto de comstackción fuera de la fuente con un contenedor Makefile.

En mi archivo CMakeLists.txt de nivel superior, incluyo lo siguiente para evitar comstackciones in-source:

 if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} ) message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." ) endif() 

Luego, creo un Makefile de nivel superior e incluyo lo siguiente:

 # ----------------------------------------------------------------------------- # CMake project wrapper Makefile ---------------------------------------------- # ----------------------------------------------------------------------------- SHELL := /bin/bash RM := rm -rf MKDIR := mkdir -p all: ./build/Makefile @ $(MAKE) -C build ./build/Makefile: @ ($(MKDIR) build > /dev/null) @ (cd build > /dev/null 2>&1 && cmake ..) distclean: @ ($(MKDIR) build > /dev/null) @ (cd build > /dev/null 2>&1 && cmake .. > /dev/null 2>&1) @- $(MAKE) --silent -C build clean || true @- $(RM) ./build/Makefile @- $(RM) ./build/src @- $(RM) ./build/test @- $(RM) ./build/CMake* @- $(RM) ./build/cmake.* @- $(RM) ./build/*.cmake @- $(RM) ./build/*.txt ifeq ($(findstring distclean,$(MAKECMDGOALS)),) $(MAKECMDGOALS): ./build/Makefile @ $(MAKE) -C build $(MAKECMDGOALS) endif 

El objective predeterminado es invocar make e invocar el destino ./build/Makefile .

Lo primero que hace el objective ./build/Makefile es crear el directorio de build usando $(MKDIR) , que es una variable para mkdir -p . La build directorio es donde realizaremos nuestra comstackción fuera de la fuente. Proporcionamos el argumento -p para garantizar que mkdir no nos grite por intentar crear un directorio que ya exista.

Lo segundo que hace el objective ./build/Makefile es cambiar directorios al directorio de build e invocar cmake .

Volviendo al objective all , invocamos $(MAKE) -C build , donde $(MAKE) es una variable Makefile generada automáticamente para make . make -C cambia el directorio antes de hacer cualquier cosa. Por lo tanto, usar $(MAKE) -C build es equivalente a hacer cd build; make cd build; make .

Para resumir, llamar a este contenedor de Makefile con make all o make es equivalente a hacerlo:

 mkdir build cd build cmake .. make 

El destino distclean invoca cmake .. , luego make -C build clean , y finalmente, elimina todo el contenido del directorio de build . Creo que esto es exactamente lo que solicitó en su pregunta.

La última parte del Makefile evalúa si el objective proporcionado por el usuario es distclean o no. De lo contrario, cambiará directorios para build antes de invocarlo. Esto es muy poderoso porque el usuario puede escribir, por ejemplo, make clean , y el Makefile lo transformará en un equivalente de cd build; make clean de cd build; make clean cd build; make clean

En conclusión, esta envoltura de Makefile, en combinación con una configuración CMake de comstackción obligatoria fuera de la fuente, lo hace para que el usuario nunca tenga que interactuar con el comando cmake . Esta solución también proporciona un método elegante para eliminar todos los archivos de salida de CMake del directorio de build .

PS En el Makefile, usamos el prefijo @ para suprimir la salida de un comando de shell, y el prefijo @- para ignorar los errores de un comando de shell. Al usar rm como parte del destino distclean , el comando devolverá un error si los archivos no existen (pueden haberse eliminado ya usando la línea de comando con rm -rf build , o nunca se generaron en primer lugar). Este error de retorno forzará a nuestro Makefile a salir. Usamos el prefijo @- para evitar eso. Es aceptable si ya se eliminó un archivo; queremos que nuestro Makefile continúe y elimine el rest.

Otra cosa a tener en cuenta: este Makefile puede no funcionar si utiliza un número variable de variables de CMake para construir su proyecto, por ejemplo, cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar" . Este Makefile asume que invocas CMake de forma consistente, ya sea escribiendo cmake .. o proporcionando cmake una cantidad consistente de argumentos (que puedes incluir en tu Makefile).

Finalmente, crédito donde se debe crédito. Este contenedor Makefile se adaptó del Makefile proporcionado por la Plantilla de proyecto de aplicación C ++ .

Si ejecuta esto:

 cmake . 

Regenerará los archivos cmake. Lo cual es necesario si agrega un nuevo archivo a la carpeta de origen que es seleccionado por * .cc, por ejemplo.

Si bien esto no es un “limpio” per se, sí “limpia” los archivos cmake al regenerar los cachés.

Espero que ayude.

En el caso en que pase parámetros -D en cmake al generar los archivos de comstackción, y no quiera eliminar toda la comstackción / directorio. Simplemente elimine el directorio CMakeFiles / dentro de su directorio de comstackción.

rm -rf CMakeFiles/

cmake --build .

Esto hace que cmake vuelva a ejecutar y los archivos del sistema de comstackción se regeneran. Tu construcción también comenzará desde cero.

Tal vez esté un poco desactualizado, pero como este es el primer golpe cuando cmake clean , cmake clean esto:

Ya que puedes comenzar una construcción en el directorio de comstackción con un objective específico con

cmake --build . --target xyz

por supuesto puedes correr

cmake --build . --target clean

ejecutar el objective clean en los archivos de comstackción generados.

Agregando esto como una respuesta debido a la demanda popular:

Por supuesto, las comstackciones fuera de la fuente son el método de acceso para los Makefiles de Unix, pero si está usando otro generador como Eclipse CDT, prefiere que construya en fuente. En ese caso, deberá purgar los archivos CMake manualmente. Prueba esto:

 find . -name 'CMakeCache.txt' -o -name '*.cmake' -o -name 'Makefile' -o -name 'CMakeFiles' -exec rm -rf {} + 

O si ha habilitado globstar con shopt -s globstar , intente con este enfoque menos desagradable en su lugar:

 rm -rf **/CMakeCache.txt **/*.cmake **/Makefile **/CMakeFiles 

Uso este script de shell para tal fin:

 #!/bin/bash for fld in $(find -name "CMakeLists.txt" -printf '%h ') do for cmakefile in CMakeCache.txt cmake_install.cmake CTestTestfile.cmake CMakeFiles Makefile do rm -rfv $fld/$cmakefile done done 

Si usa Windows, use Cygwin para este script.

Para simplificar la limpieza cuando utilizo la comstackción “fuera de fuente” (es decir, comstack en el directorio de build ), utilizo la siguiente secuencia de comandos

 $ cat ~/bin/cmake-clean-build #!/bin/bash if [ -d ../build ]; then cd .. rm -rf build mkdir build cd build else echo "build directory DOES NOT exist" fi 

Cada vez que necesite limpiar, debe obtener este script del directorio de build :

 . cmake-clean-build 

Si tiene definiciones personalizadas y desea guardarlas antes de limpiarlas, ejecute lo siguiente en su directorio de comstackción:

 sed -ne '/variable specified on the command line/{n;s/.*/-D \0 \\/;p}' CMakeCache.txt 

Luego, cree un nuevo directorio de comstackción (o elimine el antiguo directorio de comstackción y cmake a cmake ) y finalmente ejecute cmake con los argumentos que obtendrá con el guión anterior.

Tengo esto en mi archivo shell rc ( .bashrc , .zshrc ):

 t-cmake-clean() { local BUILD=$(basename $(pwd)) cd .. rm -rf $BUILD mkdir $BUILD && cd $BUILD } 

Se supone que debes usarlo solo para comstackciones fuera de la fuente. Digamos que tienes un directorio llamado build/ para este propósito. Entonces solo tienes que ejecutar t-cmake-clean desde dentro.

Utilicé la respuesta de zsxwing más arriba con éxito para resolver el siguiente problema:

Tengo una fuente que creo en varios hosts (en una placa Raspberry PI Linux, en una máquina virtual VMware Linux, etc.)

Tengo un script bash que crea directorios tmp basados ​​en el nombre de host de la máquina así:

 # get hostname to use as part of directory names HOST_NAME=`uname -n` # create a temporary directory for cmake files so they don't # end up all mixed up with the source. TMP_DIR="cmake.tmp.$HOSTNAME" if [ ! -e $TMP_DIR ] ; then echo "Creating directory for cmake tmp files : $TMP_DIR" mkdir $TMP_DIR else echo "Reusing cmake tmp dir : $TMP_DIR" fi # create makefiles with CMake # # Note: switch to tmp dir and build parent which # is a way of making cmake tmp files stay # out of the way. # # Note2: to clean up cmake files, it is OK to # "rm -rf" the tmp dirs echo echo Creating Makefiles with cmake ... cd $TMP_DIR cmake .. # run makefile (in tmp dir) echo echo Starting build ... make 

Espero que esto ayude a alguien …

Crea un directorio de comstackción temporal. por ejemplo, build_cmake. por lo tanto, todos los archivos comstackdos estarán dentro de esta carpeta.

luego, en su archivo principal de cmake, agregue el siguiente comando.

 add_custom_target(clean-all rm -rf * ) 

por lo tanto, mientras se comstack

 cmake .. 

y para limpiar hacer

 make clean-all