Ищет команду «cmake clean», чтобы очистить выходной сигнал CMake

Точно так же, как make clean удаляет все файлы, которые создавал make-файл, я хотел бы сделать то же самое с CMake. Слишком часто я обнаруживаю, что вручную просматриваю каталоги, удаляя файлы, такие как cmake_install.cmake и CMakeCache.txt , и папки CMakeFiles .

Есть ли команда, подобная cmake clean чтобы удалить все эти файлы автоматически? В идеале это должно соответствовать рекурсивной структуре, определенной в файле CMakeLists.txt текущего каталога.

Нет никакого cmake clean .

Обычно я создаю проект в одной папке, например «build». Поэтому, если я хочу make clean , я могу просто rm -rf build .

Папка «build» в том же каталоге, что и «CMakeLists.txt», обычно является хорошим выбором. Чтобы создать свой проект, вы просто даете cmake расположение CMakeLists.txt в качестве аргумента. Например: cd /build && cmake .. (Из @ComicSansMS)

Официальное FAQ в CMake :

Некоторые деревья сборки, созданные с помощью GNU autotools, имеют цель «make distclean», которая очищает сборку, а также удаляет Makefile и другие части сгенерированной системы сборки. CMake не создает цель «make distclean», потому что файлы CMakeLists.txt могут запускать скрипты и произвольные команды; У CMake нет способа точно отслеживать, какие файлы генерируются как часть запуска CMake. Предоставление distclean target даст пользователям ложное впечатление, что он будет работать, как ожидалось. (CMake генерирует цель «make clean» для удаления файлов, сгенерированных компилятором и компоновщиком).

objective «сделать distclean» необходима только в том случае, если пользователь выполняет сборку в источнике. CMake поддерживает встроенные сборки, но мы настоятельно рекомендуем пользователям принять понятие сборки вне источника. Использование дерева сборки, которое отделено от исходного дерева, не позволит CMake генерировать любые файлы в исходном дереве. Поскольку CMake не изменяет исходное дерево, нет необходимости в distclean target. Можно начать новую сборку, удалив дерево сборки или создав отдельное дерево сборки.

Я отправил его в Google за полчаса, и единственная полезная вещь, которую я придумал, заключалась в использовании утилиты 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 

Кроме того, перед этим обязательно используйте make clean (или какой-либо генератор cmake, который вы используете).

🙂

В эти дни git везде, вы можете забыть CMake и использовать git clean -d -f -x , который удалит все файлы, не находящиеся под контролем источника.

Вы можете использовать что-то вроде:

 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) 

Обычно я создаю команду «make clean-all», добавляя в предыдущий пример вызов «make clean»:

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

Не пытайтесь добавить «чистую» цель в зависимость:

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

Потому что «чистый» не является реальной целью в CMake, и это не работает. Кроме того, вы не должны использовать эти «чистые файлы cmake» в качестве зависимости от всего:

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

Потому что, если вы это сделаете, все файлы cmake будут стираться до очистки – все будет завершено, и make сделает запрос об ошибке «CMakeFiles / clean-all.dir / build.make». В результате вы не можете использовать команду clean-all перед «anything» в любом контексте:

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

Это тоже не работает.

Простое выпуск rm CMakeCache.txt работает и для меня.

Я согласен с тем, что assembly вне источника – лучший ответ. Но в то время, когда вы просто должны делать сборку in-source, я написал здесь скрипт Python, который:

  1. Запускает “make clean”
  2. Удаляет файлы, созданные с помощью cmake, в каталоге верхнего уровня, таком как CMakeCache.txt
  3. Для каждого подкаталога, содержащего каталог CMakeFiles, он удаляет CMakeFiles, Makefile, cmake_install.cmake.
  4. Удаляет все пустые подкаталоги.

Решение, которое я нашел недавно, состоит в том, чтобы объединить концепцию сборки вне источника с оболочкой Makefile.

В моем файле CMakeLists.txt верхнего уровня я включаю следующее, чтобы предотвратить встроенные сборки:

 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() 

Затем я создаю Makefile верхнего уровня и включаю следующее:

 # ----------------------------------------------------------------------------- # 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 

objective цели по умолчанию вызывается путем ввода make и вызывает целевой ./build/Makefile .

Первым делом target ./build/Makefile является создание каталога build с помощью $(MKDIR) , который является переменной для mkdir -p . Конструкция каталогов – это то, где мы будем выполнять нашу сборку вне источника. Мы предоставляем аргумент -p для обеспечения того, чтобы mkdir не кричал на нас, пытаясь создать каталог, который может уже существовать.

Во-вторых, целевой ./build/Makefile – это изменение каталогов в каталоге build и вызов cmake .

Вернемся ко all цели, мы вызываем $(MAKE) -C build , где $(MAKE) – это переменная Makefile, автоматически создаваемая для make . make -C изменяет каталог перед тем, как что-либо сделать. Поэтому использование $(MAKE) -C build эквивалентно выполнению cd build; make cd build; make .

Подводя итог, вызов этой оболочки Makefile с make all или make эквивалентен выполнению:

 mkdir build cd build cmake .. make 

Целевой distclean вызывает cmake .. , затем make -C build clean и, наконец, удаляет все содержимое из каталога build . Я считаю, что это именно то, что вы просили в своем вопросе.

Последняя часть Makefile оценивает, является ли distclean пользователем цель или не является distclean . Если нет, это приведет к изменению каталогов для build перед его вызовом. Это очень мощно, потому что пользователь может напечатать, например, make clean , а Makefile превратит это в эквивалент cd build; make clean cd build; make clean .

В заключение, эта shell Makefile в сочетании с обязательной конфигурацией CMake для сборки вне исходного кода делает так, чтобы пользователь никогда не должен взаимодействовать с командой cmake . Это решение также предоставляет элегантный метод для удаления всех выходных файлов CMake из каталога build .

PS В Makefile мы используем префикс @ для подавления вывода из команды оболочки, а префикс @- для игнорирования ошибок из команды оболочки. При использовании rm качестве части distclean target команда возвращает ошибку, если файлы не существуют (они, возможно, уже были удалены с использованием командной строки с помощью rm -rf build , или они никогда не генерировались в первую очередь). Эта обратная ошибка заставит наш Makefile выйти. Мы используем префикс @- для предотвращения этого. Это приемлемо, если файл уже был удален; мы хотим, чтобы наш Makefile продолжал идти и удалял остальные.

Еще одно замечание: этот Makefile может не работать, если вы используете переменное число переменных CMake для создания вашего проекта, например cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar" . Этот Makefile предполагает, что вы последовательно ссылаетесь на CMake, набрав cmake .. или предоставив cmake последовательное количество аргументов (которые вы можете включить в свой Makefile).

Наконец, кредит, в котором должен быть кредит. Эта shell Makefile была адаптирована из Makefile, предоставленной шаблоном Project Application C ++ .

Если вы запустите это:

 cmake . 

Он будет регенерировать файлы cmake. Это необходимо, если вы добавляете новый файл в исходную папку, выбранную * .cc, например.

Хотя это не «чистый» как таковой, он «очищает» файлы cmake, регенерируя кеши.

Надеюсь, это поможет.

В случае, когда вы передаете параметры -D в cmake при создании файлов сборки и не хотите удалять всю сборку / каталог. Просто удалите каталог CMakeFiles / внутри каталога сборки.

rm -rf CMakeFiles/

cmake --build .

Это приводит к повторному запуску cmake и регенерации системных файлов. Ваша assembly также начнется с нуля.

Может быть, это немного устарело, но так как это первый хит, когда вы google cmake clean , я добавлю следующее:

Поскольку вы можете начать сборку в каталоге build с указанной целью с помощью

cmake --build . --target xyz

вы можете, конечно, бежать

cmake --build . --target clean

для запуска clean цели в сгенерированных файлах сборки.

Добавляя это как ответ из-за популярного спроса:

Разумеется, assembly вне исходного кода – это метод go-to для Unix Make-файлов, но если вы используете другой генератор, такой как Eclipse CDT, он предпочитает создавать встроенный источник. В этом случае вам нужно будет очистить файлы CMake вручную. Попробуй это:

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

Или если вы включили globstar с shopt -s globstar , попробуйте этот менее отвратительный подход:

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

Я использую этот сценарий оболочки для этой цели:

 #!/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 

Если вы используете Windows, используйте Cygwin для этого скрипта.

Чтобы упростить очистку при использовании сборки «из источника» (т.е. вы строите в каталоге build ), я использую следующий скрипт

 $ 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 

Каждый раз, когда вам нужно очищать, вы должны указать этот скрипт из каталога build :

 . cmake-clean-build 

Если у вас есть пользовательские настройки и вы хотите сохранить их перед очисткой, запустите в каталоге сборки следующее:

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

Затем создайте новый каталог сборки (или удалите старый каталог сборки и заново создайте его) и, наконец, запустите cmake с аргументами, которые вы получите со сценарием выше.

У меня это в моем файле оболочки rc ( .bashrc , .zshrc ):

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

Вы должны использовать его только для сборки вне источника. Допустим, у вас есть каталог с именем build/ для этой цели. Тогда вам просто нужно запустить t-cmake-clean изнутри.

Я успешно использовал ответ от zsxwing, чтобы решить следующую проблему:

У меня есть источник, который я построил на нескольких хостах (на плате Raspberry PI Linux, на виртуальной машине VMware Linux и т. Д.).

У меня есть сценарий bash, который создает каталоги tmp на основе имени хоста машины следующим образом:

 # 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 

Надеюсь, это поможет кому-то …

Создайте временную директорию сборки. например build_cmake. поэтому все, что вы создаете, будет находиться внутри этой папки.

затем в вашем основном файле cmake добавьте команду ниже.

 add_custom_target(clean-all rm -rf * ) 

поэтому при компиляции do

 cmake .. 

и чистить

 make clean-all 
  • Подсказка Найти .cmake Файлы с пользовательским каталогом
  • Кросс-компиляция CMake: флаги C из файла toolchain игнорируются
  • Библиотека разделов CMake с несколькими исполняемыми файлами
  • CMake не находит компилятор Visual C ++
  • Каков правильный способ использования `pkg-config` из` cmake`?
  • Список include_directories в CMake
  • CMake: как создавать внешние проекты и включать их цели
  • cmake add_custom_command
  • Как поддерживать оба vcxproj в cmake в проекте?
  • Немедленно создайте инструмент, чтобы его можно было использовать позже в том же запуске CMake
  • Как связать программу на C ++ с помощью Boost с помощью CMake
  • Interesting Posts
    Давайте будем гением компьютера.