Шукаєте команду 'cmake clean', щоб очистити вихід CMake


419

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

Чи є така команда, як cmake cleanвидалити всі ці файли автоматично? В ідеалі це має відповідати рекурсивній структурі, визначеній у CMakeLists.txtфайлі поточного каталогу .

Відповіді:


487

Немає cmake clean.

Я зазвичай будую проект в одній папці на зразок "побудувати". Тож якщо я хочу make clean, можу просто rm -rf build.

Папка "build" в тому ж каталозі, що і корінь "CMakeLists.txt", як правило, є хорошим вибором. Щоб побудувати свій проект, ви просто вкажете cmake розташування CMakeLists.txt як аргумент. Наприклад: cd <location-of-cmakelists>/build && cmake ... (Від @ComicSansMS)


101
Це називається "поза вихідної збірки" і має бути кращим способом. Це дозволяє уникнути сутичок з іменами тощо
arne

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 є копіями / аналогічними назвами ваших файлів.
pavon

84

Офіційний FAQ щодо CMake зазначає:

Деякі дерева дерев, створені за допомогою автоінструментів GNU, мають ціль "make distclean", яка очищає збірку, а також видаляє Makefiles та інші частини створеної системи збирання. CMake не генерує ціль "make distclean", оскільки файли CMakeLists.txt можуть запускати сценарії та довільні команди; CMake не може відслідковувати, які саме файли створюються як частина запущеного CMake. Забезпечення неприємних цілей створювало б у користувачів помилкове враження, що воно буде працювати, як очікувалося. (CMake дійсно генерує ціль "очистити", щоб видалити файли, створені компілятором і лінкером.)

Ціль "make distclean" потрібна лише в тому випадку, якщо користувач виконує збірку в джерелі. CMake підтримує вбудовані джерела, але ми наполегливо рекомендуємо користувачам приймати поняття збірки з вихідного коду. Використання дерева збірки, яке є окремим від вихідного дерева, не дозволить CMake генерувати будь-які файли у вихідному дереві. Оскільки CMake не змінює вихідне дерево, немає необхідності в цілеспрямованій цілі. Можна почати свіжу збірку, видаливши дерево збірки або створивши окреме дерево збірки.


Спочатку, як це було запроваджено та використано автоінструментами GNU, мета "distclean" призначена для того, щоб зробити вихідне дерево готовим до відтворення та створення розподілу смоли. Такі користувачі файлу tar можуть завантажувати та знімати untar, а потім запускати "configure" та "make", не потребуючи автоінструментів (aclocal, automake, autoconf тощо). Якщо ми екстраполюємо це для cmake, тоді "make distclean" залишить нас чистим джерело, яке можна побудувати без встановлення cmake. Однак це не спрацьовує, коли генератор був генератором з одноцільовою ціллю (як це зроблено), тому що конфігурація з 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
Це передбачає нарощування джерела, якого слід уникати само собою.
Слава

це було просте рішення (і я не маю пригадування того, що означають ці прапори, але це просто машина розробника lol).
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, він видалив деякі робочі файли репозиторіїв.
бурхливий

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і все ще не робив ...
С.Ф.

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)

Зазвичай я створюю команду "очистити все", додаючи виклик "очистити" до попереднього прикладу:

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 перед "будь-яким" у будь-якому контексті:

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

Це теж не працює.


Чи є спосіб заповнити cmake_generated автоматично? Можливо, поєднуючи це з відповіддю юрі.макаревич? Наразі це не видалить файли у підкаталогах $ {CMAKE_BINARY_DIR}.
foxcub

Не працює для Ninja або Visual studio. Я б не рекомендував такий підхід.
usr1234567

23

Просто видання rm CMakeCache.txtтворів і для мене.


1
Лише видалення пов'язаних змінних у CMakeCache.txt працює і для мене.
Йорквар

Видалення 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ціль у створених файлах збірки.


8

Я погоджуюся, що збірка без джерела - найкраща відповідь. Але для тих часів, коли ви просто повинні робити збірку джерел, я написав доступний тут скрипт Python , який:

  1. Виконує "очистити"
  2. Вилучає конкретні файли, створені CMake, у каталозі верхнього рівня, наприклад CMakeCache.txt
  3. З кожного підкаталогу, що містить каталог CMakeFiles, він видаляє CMakeFiles, Makefile, cmake_install.cmake.
  4. Видаляє всі порожні підкаталоги.

Дякую за це. Я хотів би додати до вашого сценарію рядок, який замовчує, 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)автоматично створюється змінна Makefilemake . 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 ++ Application Project .


4

Звичайно, збірки без джерела - це метод переходу для Unix Makefiles, але якщо ви використовуєте інший генератор, такий як 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 target clean.)


На цьому знімку екрана відображається лише текст . Тим не менш, ти робиш знімок екрана, порушуючи відповідь для всіх, хто приходить сюди, за допомогою екранного читання. Будь ласка, киньте це зображення та зробіть копію / вставлення тексту та витратьте 1 хвилину, щоб правильно форматувати цей ввід.
GhostCat

3

У випадку, коли ви проходите -D параметри в CMake під час генерації файлів збірки та не хочете видаляти всю збірку / каталог:

Просто видаліть каталог CMakeFiles / всередині каталогу збирання.

rm -rf CMakeFiles/
cmake --build .

Це призводить до повторного запуску CMake і відновлення системних файлів. Ваша збірка також почнеться з нуля.


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аргументи, які ви отримаєте зі сценарієм вище.


0

Якщо ти біжиш

cmake .

він відновить файли CMake. Що необхідно, якщо ви додаєте новий файл у папку-джерело, вибрану, наприклад, * .cc.

Хоча це не є "чистим" саме по собі, воно "очищає" файли CMake, регенеруючи кеші.


Це не очищає wrt. стан компіляції: Якщо було складено 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 для цього сценарію.


0

Смішно бачити, що це питання отримує стільки уважних і складних рішень, що справді показує біль не мати чистого методу з cmake.

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

Якщо ви cd .., rm -rf buildа потім mkdir buildі потім cd build, це занадто багато надрукувати.

Тож хорошим рішенням є просто залишатися поза папкою збірки та сказати cmake шлях:
налаштувати: cmake -B build
build: cmake --build build
очистити: rm -rf build
відтворити папку збірки: вам навіть не потрібно mkdir build, просто налаштуйте її за допомогою cmake -B buildcmake створимо її


0

cmakeв основному кухарі Makefile, можна додати rmдо чистого PHONY .

Наприклад,

[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

-1

Я маю це у своєму файлі оболонки rc ( .bashrc, .zshrc):

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

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


-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

-8

Створіть тимчасовий каталог збірки, наприклад, build_cmake . Отже, всі ваші файли збирання знаходяться всередині цієї папки.

Потім в основний файл CMake додайте команду нижче.

add_custom_target(clean-all
    rm -rf *
)

Отже, під час компіляції робити

cmake ..

А чистити робити:

make clean-all

11
хороший спосіб видалити весь ваш проект, якщо хтось випадково створить джерело замість вихідного джерела

3
так. цей метод слід застосовувати лише з "нарощування джерела"
Натеш,

6
Страшна рекомендація. Не повинно існувати як відповідь.
Енн ван Россум

@AnnevanRossum згоден
zevarito
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.