Перенаправление временных файлов CMake

CMake, конечно, прекрасен, но мне совершенно не нравится его особенность “гадить” в директорию из которой он был запущен. Какого-либо явного способа сказать CMake – положи все свои промежуточные файлы в директорию XYZ нет, кроме не документированного ключа с кривоватым поведением. В итоге, почти все виденные мной основанные на CMake проекты просто не парятся и мирятся с тем мусором, что образуется у них в корне. Можно, конечно, мириться, но есть и варианты

По большому счету варианта два и оба они не кроссплатформенные: написать скрипты – запускалки (sh и bat) или написать Makefile. Вариант со скриптами на мой взгляд более кривой, так как требует реализации того функционала, который уже предлагается Make. Так что я остановился на 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 ..)

test:
    @  (cd $(BUILD_DIR) > /dev/null && ctest -L unit --verbose)

clean:
    @ $(MAKE) -C $(BUILD_DIR) clean

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

И теперь мне ни мусор не досаждает, ни проблем с вызовом тестов/перегенерацией основного рабочего Makefile нет. Ну и заодно добавил генерацию запускалки в свой gen-cmake.

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

10 Comments Перенаправление временных файлов CMake

    1. Alexander Stavonin

      Ну не знаю. Он, безусловно, кривой… но альтернативы и того хуже. В итоге я склоняюсь к тому, что пусть он лучше живет

      Reply
        1. Alexander Stavonin

          Ну не скажи. Будь оно так, все бы на Коболе писали или еще какой-то архаичности. Да и альтернатив же гора, в теории. На практике C++ проекты слишком сложны и зоопарк технологий их построения нехило так разросся и простые решения не подходят.
          Плюс в CMake очень подкупает именно тот факт, что это генератор сборок, как следствие каждый использует то, что привык.

          Reply
          1. Yauheni Akhotnikau

            Только вот писали этот генератор какие-то инопланетяне. В результате использовать его можно разве что посредством копипасты из чужих проектов. Понять, как же это работает, оказывается весьма не просто.

  1. Alexander Stavonin

    Ну я уже поднаторел на большом проекте, так что вроде более-менее понятно стало. Хотя они навернули слишком уж – это да, не могу не согласиться. Главное вынесенное мной правило – не надо пытаться вставить дополнительную логику в обход CMake (например через sh/bat) дублирующую то, что делает CMake.

    Reply
  2. Pavel Medvedev

    Недокументированный ключ это -B (http://stackoverflow.com/a/20611964/1355844) ? А в чем его кривость заключается?

    Вообще поддержу Евгения, cmake – инопланетная технология по недоразумению ставшая популярной. Вчера потратил весь день чтобы включить в cmake-проект сторонний cmake-проект. Его авторы вообразили себя центром вселенной и использовали CMAKE_SOURCE_DIR в качестве корневого пути чтобы искать свои скрипты конфигурации. Так что просто подключить сторонний проект через add_subdirectory() не удалось, пришлось плясать вокруг ExternalProject_Add()

    Начинать проекты на cmake выходит себе дороже. В итоге все равно приходится обвязывать самописными скриптами. Последние несколько лет я предпочитаю использовать GYP. Это тоже своеобразный инструмент, но в трудных случаях хотя бы можно залезть внутрь исходников и попытаться понять что происходит.

    Reply
    1. Alexander Stavonin

      С -B есть одна очевидная проблема – необходимость в “запускалке” никуда не девается. Кроме того, сейчас уже не вспомню точно что и почему, у нас лезли какие-то магические побочные эффекты с этими ключами. Может просто готовить их не умели.

      Про GYP не слышал никогда, интересно, хотя на первый взгляд (2 минуты поверхностного чтения) функционал очень бедный на фоне CMake. Всё же CMake, это целая подсистема включающая в себя еще и CTest, возможность конфигурировать каким образом обрабатывать файлы после компиляции (актуально для MacOS, т.к. часто нужно править install paths) и многое другое.

      Reply
      1. Pavel Medvedev

        Понятно, спасибо. Да, я тоже получал магические эффекты с cmake которые исчезали после удаления каталога сборки.

        GYP это просто генератор проектов разных форматов, с ним на Windows я получаю проект для Visual Studio, на OSX – проект для Xcode. Так что скрипты для конфигурации, автоматической сборки приходится писать самому. Хотя кое-что можно сделать и средствами GYP action.

        Так что альтернативы cmake есть, как минимум не хуже. Только в этом году я узнал про 2 новых: http://mesonbuild.com и https://build2.org только никак не соберусь попробовать их хотя бы в игрушечных проектах.

        Reply
        1. Yauheni Akhotnikau

          Еще и premake5 на слуху: https://premake.github.io/
          Но мне и своего старого лисапеда на Ruby хватает, особенно после того, как туда добавили простой, но мощный, способ управления зависимостями для C++.

          Reply

Leave a Reply to Pavel Medvedev Cancel reply