Ищите команду cmake clean для очистки вывода CMake

419

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

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

Билл Читам
источник

Ответы:

487

Существует нет cmake clean.

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

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

zsxwing
источник
101
Это называется "сборка из исходного кода" и должна быть предпочтительным способом. Это избегает
именных
17
+1 для сборок вне исходного кода. Это становится жизненно важным при построении нескольких архитектур. Например, вы не можете собрать как 64-битные, так и 32-битные двоичные файлы с помощью сборки в исходном коде, поскольку для этого требуются две отдельные иерархии CMake-кэша.
ComicSansMS
9
Вы можете разместить папку в любом месте, но папка сборки в том же каталоге, что и корневой CMakeLists.txt, обычно является хорошим выбором. Для сборки просто укажите в качестве аргумента cmake расположение файла CMakeLists.txt. Например:cd <location-of-cmakelists>/build && cmake ..
ComicSansMS
64
Там действительно должно быть чистым cmake. Каждый, кто когда-либо использовал cmake, даже если он привык делать сборки из исходного кода, случайно запустил cmake в неправильном каталоге, и это огромная боль в том, чтобы убирать вручную.
павон
24
@DevSolar Но обратное неверно; тот факт, что файл не находится под контролем версий, не означает, что он сгенерирован cmake и безопасен для удаления. Выбирать, какие неверсированные файлы находятся в процессе разработки, которые вам нужно сохранить, а какие - cmake cruft, - это боль, особенно когда большинство файлов cmake имеют копии / аналогично названные в ваших файлах.
Павон
84

Официальный FAQ CMake гласит:

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

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

Питер
источник
Первоначально, как было введено и использовано в автоинструментах GNU, цель 'distclean' предназначена для того, чтобы дерево исходного кода было готово к архивированию и созданию дистрибутива tar. Такие tar-файлы пользователи могут загружать и распаковывать, а затем запускать «configure» и «make» без необходимости использования автоинструментов (aclocal, automake, autoconf и т. Д.). Если мы экстраполируем это на cmake, тогда «make distclean» оставит нас с чистой источник, который может быть собран без установки cmake. Однако, это не работает, когда генератор был генератором с одной целью (как цель 'make'), потому что конфигурация с помощью cmake происходит во время
Carlo Wood
... работает cmake. Создание дистрибутива, который не может быть настроен, даже не выполняет тесты платформы и т. Д., Бесполезно. Следовательно, не существует «чистой» цели для cmake. cmake должен существовать на компьютере конечного пользователя.
Карло Вуд
63

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

Жан Дэви
источник
14
Этот -xвариант, хотя. Это отличный трюк в gitторговле. Хотя я бы лично еще сделать всухую первый, git clean -d -f -x -n. Время от времени я держу файл удобства, который я использую для проекта, с gitконтролируемой папкой проекта , но я не хочу делиться этим с другими, поэтому я не делаю git addэтого с проектом. Это уничтожило бы этот файл, если бы я не был осторожен, чтобы добавить -e <pattern>опцию. На этой ноте было бы неплохо, если gitбы был .gitcleanignoreфайл. :)
CivFan
1
@CivFan, который вы можете попробовать использовать chattr +i $filename(нужны права суперпользователя, не позволяет изменять файл после этого). Таким образом, git не сможет удалить этот файл, даже если попытается сделать это так rm -f.
Руслан
3
Это предполагает сборку в исходном коде, чего следует избегать самостоятельно.
Слава
это было простое решение (и я не помню, что означают эти флаги, но это просто машина для разработки)
matanster
1
Хм, а как насчет недавно добавленных файлов, которые пользователь забыл git add?
августа
50

Я гуглил его примерно полчаса, и единственное полезное, что я придумал, это вызов findутилиты:

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

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

:)

Питер Мортенсен
источник
36
Я бы не рекомендовал использовать этот подход, если каталог, в котором вы работаете, находится под контролем версий: когда я пробовал этот подход с svn, он удалил некоторые из рабочих файлов репозиториев.
13
8
Там могут быть другие файлы, соответствующие cmake, так что это действительно не универсальный подход. Это должно сделать: rm -rf CMakeFiles; rm -rf CMakeCache.txt; rm -rf cmake_install.cmake;
honza_p
1
Я бы удалил -exec rm -rf {} \ + и просто использовал -delete.
Эдгар Арутюнян
3
Понижено, поскольку эта команда потенциально может удалить некоторые пользовательские файлы. Я предпочитаю команду honza_p, не очень длинную, более простую и менее рискованную.
Эдриан Декамп
1
@AdrienDescamps: за исключением того, что он все еще оставляет связанный с cmake мусор в подкаталогах. Я делал rm -rf CMakeFiles ; rm -rf */CMakeFiles ; rm -rf */*/CMakeFiles ; rm -rf */*/*/CMakeFilesи все еще не сделал ...
SF.
35

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

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, и это не работает.

Более того, вы не должны использовать этот «clean-cmake-files» как зависимость от чего-либо:

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

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

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

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

Peregring-лк
источник
Есть ли способ заполнить cmake_generated автоматически? Возможно, совмещая это с ответом юрия.макаревича? В настоящее время это не приведет к удалению файлов в подкаталогах $ {CMAKE_BINARY_DIR}.
foxcub
Не работает для студии Ninja или Visual. Я бы не рекомендовал такой подход.
usr1234567
23

Просто выдача rm CMakeCache.txtработает для меня тоже.

user1480788
источник
1
Только удаление связанных переменных в CMakeCache.txt тоже работает для меня.
Yorkwar
Удаление CMakeCache.txt и последующее выполнение «cmake --build / build-path» вызывает «Ошибка: не удалось загрузить кэш».
Ненчев
1
@nenchev тебе нужно cmake /build-pathснова бежать .
Самаурса
@Samaursa cmake - сборка перезапускает cmake при необходимости, этот метод ломает каталог сборки и cmake жалуется. В моем ответе ниже говорится, что вы должны удалить каталог CMakeFiles /, что приведет к автоматическому перезапуску и перезапуску cmake.
Ненчев
2
@nenchev Я понимаю, что ты имеешь в виду, и я согласен.
Самаурса
9

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

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

cmake --build . --target xyz

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

cmake --build . --target clean

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

redleg
источник
8

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

  1. Бежит "почисти"
  2. Удаляет определенные сгенерированные CMake файлы в каталоге верхнего уровня, таком как CMakeCache.txt
  3. Для каждого подкаталога, содержащего каталог CMakeFiles, он удаляет CMakeFiles, Makefile, cmake_install.cmake.
  4. Удаляет все пустые подкаталоги.
tschutter
источник
Спасибо за это. Я хотел бы добавить строку в ваш скрипт, которая заставляет замолчать, makeкогда нет Makefileприсутствия из-за предварительной очистки (то есть делает этот скрипт идемпотентным). Просто добавьте строку (правильно расположенную): if os.path.isfile(os.path.join(directory,'Makefile')):прямо перед строкой 24: args = [и, конечно, сделайте отступ для остальной части тела функции после только что добавленной строки. Это будет выполнено, только make ... cleanесли a Makefileприсутствует в текущем очищаемом каталоге. В остальном сценарий идеален!
Михаил Гольдштейн
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

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

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

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

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

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

mkdir build
cd build
cmake ..
make 

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

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

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

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

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

Наконец, кредит, где кредит должен. Эта оболочка Makefile была адаптирована из Makefile, предоставленного шаблоном проекта приложения C ++ .

Эрнан Виллануева
источник
4

Конечно, сборки из исходного кода - это метод перехода для сборочных файлов Unix, но если вы используете другой генератор, такой как 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
Крис Уоттс
источник
Вчера я выбрал клонирование репо в новую папку, обновление CMakeLists.txt для сборки из подпапки build. Это заняло немного больше времени, чем эти команды, но я должен был сделать это только один раз :)
Tien Do
4

попробуйте использовать: cmake --clean-first path-of-CMakeLists.txt-file -B output-dir

--clean-first: сначала создать мишень, а затем построить.
(Только для очистки используйте --target clean.)

赏心悦目
источник
Этот снимок экрана показывает только текст . Тем не менее, вы делаете снимок экрана, ломая ответ для любого, кто приходит сюда со скринридером. Пожалуйста, отбросьте это изображение, сделайте копию / вставку текста и потратьте 1 минуту, чтобы правильно отформатировать этот ввод.
GhostCat
3

В случае, когда вы передаете -Dпараметры в CMake при генерации файлов сборки и не хотите удалять весь каталог build /:

Просто удалите каталог CMakeFiles / внутри вашего каталога сборки.

rm -rf CMakeFiles/
cmake --build .

Это приводит к повторному запуску CMake, и системные файлы сборки восстанавливаются. Ваша сборка также начнется с нуля.

nenchev
источник
1

Чтобы упростить очистку при использовании сборки «вне источника» (т. Е. При сборке в 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
Александр Лобов
источник
Красиво и безопасно. Поскольку вы можете открыть каталог сборки в файловом менеджере, я предлагаю заменить cd .. ; rm ; mkdir ; cdпоследовательность на cd .. ; rm -rf build/*.
Мостафа Фарзан
0

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

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

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

Zouppen
источник
0

Если вы бежите

cmake .

это восстановит файлы CMake. Что необходимо, если вы добавляете новый файл в исходную папку, выбранную, например, * .cc.

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

Homer6
источник
Это не чистит по отношению к. состояние компиляции: если 500 из 1200 файлов были скомпилированы, после «cmake». он просто продолжит работу с последними 700 файлами.
Питер Мортенсен
0

Я использую следующий скрипт для таких целей:

#!/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 для этого скрипта.

yanpas
источник
0

Забавно видеть, что этот вопрос получает так много внимания и сложных решений, что действительно показывает боль, когда у меня нет чистого метода cmake.

Ну, вы можете определенно cd buildделать свою работу, а затем делать, rm -rf *когда вам нужно убрать. Однако rm -rf *это опасная команда, учитывая, что многие люди часто не знают, в каком каталоге они находятся.

Если вы cd .., rm -rf buildа затем mkdir buildи тогдаcd build , это просто слишком много печатать.

Поэтому хорошим решением будет просто остаться вне папки сборки и указать cmake путь:
настроить: cmake -B build
построить: cmake --build build
очистить: rm -rf build
воссоздать папку сборки: вам даже не нужно mkdir build, просто настройте ее, cmake -B buildи cmake создаст ее

откровенный
источник
0

cmakeВ основном готовит Makefile, можно добавить rmв чистую ФОНИ .

Например,

[root@localhost hello]# ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  CMakeLists.txt  hello  Makefile  test
[root@localhost hello]# vi Makefile
clean:
        $(MAKE) -f CMakeFiles/Makefile2 clean
        rm   -rf   *.o   *~   .depend   .*.cmd   *.mod    *.ko   *.mod.c   .tmp_versions *.symvers *.d *.markers *.order   CMakeFiles  cmake_install.cmake  CMakeCache.txt  Makefile
LinconFive
источник
-1

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

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

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

thiagowfx
источник
-3

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

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

У меня есть сценарий Bash, который создает временные каталоги на основе имени хоста компьютера, например:

# 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 the temporary dir and build parent 
#       which is a way of making cmake tmp files stay
#       out of the way.
#
# Note 2: to clean up cmake files, it is OK to
#        "rm -rf" the temporary directories

echo
echo Creating Makefiles with cmake ...

cd $TMP_DIR

cmake ..

# Run makefile (in temporary directory)

echo
echo Starting build ...

make
asantanna
источник
-8

Создайте временный каталог сборки, например build_cmake,. Следовательно, все ваши файлы сборки будут в этой папке.

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

add_custom_target(clean-all
    rm -rf *
)

Следовательно, при компиляции

cmake ..

И для очистки сделать:

make clean-all
Natesh
источник
11
хороший способ удалить весь ваш проект, если кто-то случайно соберет исходный код вместо
3
да. этот метод должен использоваться только с "сборкой вне исходного кода"
Natesh
6
Страшная рекомендация. Не должно существовать в качестве ответа.
Энн ван Россум
@AnnevanRossum согласен
zevarito