Может кто-нибудь объяснить мне этот скрипт cmake? - PullRequest
8 голосов
/ 30 мая 2011

Я чувствую, что все сообщество cmake троллит меня. Ни один из "учебников" или ресурсов не имеет никакого смысла для меня. Как будто я что-то упустил. Я думаю, что больше всего меня смущает язык, и ни один из увиденных мною уроков не приблизился даже к тому, чтобы быть приличным в объяснении cmake кому-то, у кого мало юниксов и опыта.

В любом случае, я работаю с FireBreath, и он широко использует cmake, думаю, пришло время выяснить, как его использовать, а не менять файлы проекта напрямую.

Корневой файл CMakeLists.txt содержит следующее:

cmake_minimum_required (VERSION 2.6)
set (CMAKE_BACKWARDS_COMPATIBILITY 2.6)

Project(${PLUGIN_NAME})

file (GLOB GENERAL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
    [^.]*.cpp
    [^.]*.h
    [^.]*.cmake
    )

include_directories(${PLUGIN_INCLUDE_DIRS})

# Generated files are stored in ${GENERATED} by the project configuration
SET_SOURCE_FILES_PROPERTIES(
    ${GENERATED}
    PROPERTIES
        GENERATED 1
    )

SOURCE_GROUP(Generated FILES
    ${GENERATED}
    )

SET( SOURCES
    ${GENERAL}
    ${GENERATED}
    )

Я бы действительно был бы признателен, если бы кто-нибудь объяснил мне каждую строку. Особенно то, что ${GENERAL} и ${GENERATED}.

Ответы [ 2 ]

19 голосов
/ 30 мая 2011

Прежде всего, синтаксис cmake действительно прост. Он состоит из «команд» и «аргументов». Это так просто, что требуется некоторое время, чтобы это впиталось. Все есть «команда (аргументы)». Кроме того, имена команд не чувствительны к регистру. Раньше они должны были быть ВСЕМИ КОПИЯМИ, но начиная с версии 2.6 (я думаю) это не имеет значения. Аргументы, однако, чувствительны к регистру.

cmake_minimum_required (VERSION 2.6)

Эта команда устанавливает минимальную требуемую версию cmake для проекта. Если текущая версия cmake ниже 2.6, она прекратит обработку и сообщит об ошибке. Это предотвращает необходимость поддерживать древние версии инструмента.

set (CMAKE_BACKWARDS_COMPATIBILITY 2.6)

Установите для переменной CMAKE_BACKWARDS_COMPATIBILITY значение 2.6. На самом деле это небольшая ошибка в представленном вами файле CMakeLists.txt, так как CMAKE_BACKWARDS_COMPATIBILITY не следует использовать для версии 2.6 и выше. Сценарий, вероятно, должен использовать cmake_policy. Это указывает на то, как должны вести себя новые версии cmake, когда сталкиваются с несоответствиями в предыдущих версиях cmake. Любые сценарии, которые вы пишете с нуля сегодня, не должны беспокоиться об этом.

Project(${PLUGIN_NAME})

Устанавливает имя проекта равным значению того, что находится в переменной PLUGIN_NAME. Это значение отображается как имя проекта в некоторых IDE. Чтобы записать значение в переменную, вы можете использовать set(PLUGIN_NAME myName), а для чтения значения вы используете синтаксис ${}: "${PLUGIN_NAME}". Некоторые команды также записывают переменные, но вы используете их так же, как в команде set.

file (GLOB GENERAL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
     [^.]*.cpp
     [^.]*.h
     [^.]*.cmake
     )

file - это команда. Его первый аргумент GLOB означает «вернуть файлы на диск, имена которых соответствуют шаблонам, которые я приведу в качестве аргументов». Следующий аргумент GENERAL - это переменная, в которой хранится результат, подобно set, он записывает результат в переменную, и вы можете позже прочитать его с помощью ${GENERAL}. RELATIVE и путь означает возврат имени файла относительно этого пути, а не полного пути. Поэтому вместо «C: \ some \ long \ path \ src \ foo.cpp» или «/home/me/some/path/src/foo.cpp» вы получите «src \ foo.cpp» или «src / foo.cpp». Переменная CMAKE_CURRENT_SOURCE_DIR - это «волшебная переменная», которую CMake заполняет для вас, и она ссылается на путь к исходному каталогу, обрабатываемому в данный момент, где находится этот файл CMakeLists.txt. Последний список аргументов - это шаблоны файлов, которые будут сопоставлены. По сути, все, что имеет расширение файла cpp, h или cmake.

include_directories(${PLUGIN_INCLUDE_DIRS})

Добавить каталоги в ${PLUGIN_INCLUDE_DIRS} в каталоги, которые ищет компилятор для поиска включаемых файлов. Это приведет к дополнительным аргументам "-I", если вы скомпилируете, например, с gcc.

# Generated files are stored in ${GENERATED} by the project configuration

Строки, начинающиеся с #, являются комментариями.

SET_SOURCE_FILES_PROPERTIES(
       ${GENERATED}
       PROPERTIES
           GENERATED 1
       )

С файлами могут быть связаны пары ключ / значение, и это влияет на их построение. Здесь для файлов, перечисленных в переменной ${GENERATED}, свойству «GENERATED» присвоено значение 1. Что это значит? Что ж, теперь CMake знает, что не нужно искать файлы «$ {GENERATED}» на диске, так как они будут созданы на следующем этапе сборки. В размещенном фрагменте никто не устанавливает переменную ${GENERATED}. Я предполагаю, что это установлено в другом месте в файлах проекта. Не путайте переменную ${GENERATED} со свойством GENERATED! Это тонкий момент, и, возможно, переменная должна была быть GENERATED_FILES, чтобы избежать путаницы, т.е. SET_SOURCE_FILES_PROPERTIES(${GENERATED_FILES} PROPERTIES GENERATED 1).

 SOURCE_GROUP(Generated FILES ${GENERATED})

Это создает группу, которая в Visual Studio преобразуется во вкладку файла, которая называется «Сгенерировано» и содержит файлы в переменной ${GENERATED}.

 SET(SOURCES ${GENERAL} ${GENERATED})

Эта строка устанавливает переменную SOURCES для того, что находится в переменных ${GENERAL} и ${GENERATED}. Ранее мы установили ${GENERAL}, чтобы быть списком файлов cpp, h и cmake, которые были в текущем исходном каталоге. В C-подобном псевдокоде это похоже на «SOURCES = GENERAL + GENERATED». В качестве детали реализации, значение SOURCES на самом деле является списком, а его содержимое разделено знаком ";" персонажи. Обычно это делается для того, чтобы позже вы могли создать библиотеку или исполняемый файл, просто используя переменную ${SOURCES}, а не повторяя две другие переменные везде.

6 голосов
/ 30 мая 2011

Иногда я могу понять ваши чувства по поводу учебников по cmake. Я рекомендую просмотреть онлайн-документы и некоторые cmake-проекты: например, Огре, Втк, Кде.

Из вашего просмотра CMakeLists.txt видно, что этот должен вызываться внешним CMake-проектом (с add_subdirectory), поскольку он ссылается на переменные PLUGIN_NAME, PLUGIN_INCLUDE_DIRS и GENERATED.

Чтобы ответить на ваши вопросы:

cmake_minimum_required (VERSION 2.6)
set (CMAKE_BACKWARDS_COMPATIBILITY 2.6)
Project(${PLUGIN_NAME})

Это подготовит ваш cmakefile, сообщит cmake, что он должен быть версии 2.6 или выше и что вы запускаете проект с именем, указанным в переменной PLUGIN_NAME.

file (GLOB GENERAL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
    [^.]*.cpp
    [^.]*.h
    [^.]*.cmake
    )

Эта часть пролистывает текущий каталог с исходным кодом (тот, где находится ваш файл cmakelists.txt) и собирает ВСЕ файлы * .cpp, * .h и * .cmake. Результатом является набор / список путей к файлам, относительный с пересчетом к текущему исходному каталогу и сохраненный в переменной GENERAL.

# Generated files are stored in ${GENERATED} by the project configuration
SET_SOURCE_FILES_PROPERTIES(
    ${GENERATED}
    PROPERTIES
        GENERATED 1
    )

SOURCE_GROUP(Generated FILES
    ${GENERATED}
    )

Очевидно, будет набор исходных файлов, хранящихся в переменной GENERATED (следовательно, не GENERAL). В случае сгенерированных при сборке исходных файлов эти файлы не обязательно присутствуют при первой сборке CMake, и CMake должен знать, что они созданы. С помощью команды set_source_files_properties они получают «сгенерированное» свойство, которое необходимо для CMake, чтобы выполнить корректную проверку зависимостей.

SET( SOURCES
    ${GENERAL}
    ${GENERATED}
    )

Итак, теперь у нас есть набор исходных файлов из вызова файла (GLOB ...), хранящихся в переменной GENERAL. И у нас есть набор файлов, хранящихся в переменной GENERATED, которая создается где-то еще. Эти два набора объединяются в единый список исходных файлов и хранятся в переменной SOURCES.

В обычных условиях я бы ожидал вызова add_library: add_library ($ {PLUGIN_NAME} {SOURCES})

Это указывает Cmake, что новая библиотека должна создаваться и создаваться из исходных файлов в SOURCES.

...