Ищите команду cmake clean для очистки вывода CMake - PullRequest
344 голосов
/ 13 марта 2012

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

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

Ответы [ 19 ]

414 голосов
/ 13 марта 2012

Нет cmake clean.

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

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

73 голосов
/ 16 сентября 2014

Официальный FAQ по CMake утверждает:

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

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

50 голосов
/ 21 августа 2012

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

:)

48 голосов
/ 15 августа 2014

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

31 голосов
/ 05 декабря 2012

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

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 будут удалены до завершения очистки, и 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
)

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

18 голосов
/ 22 июня 2014

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

7 голосов
/ 19 сентября 2012

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

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

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

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

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 

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

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

В заключение, эта оболочка Makefile в сочетании с обязательным out-of-source build Конфигурация 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 ++ .

3 голосов
/ 11 июня 2018

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

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

cmake --build . --target xyz

Вы, конечно, можете запустить

cmake --build . --target clean

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

3 голосов
/ 29 октября 2017

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

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

rm -rf CMakeFiles/
cmake --build .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...