Как используется CMake? [закрытый]



Как известно, трудно получить какую-либо полезную информацию о CMake в качестве новичка. До сих пор я видел несколько учебников о том, как настроить некоторые очень простой проект или другой. Однако ни один из них не объясняет причины ничего что показано в них, всегда оставляя много отверстий для заполнения.



Что означает вызов CMake на CMakeLists значит? Он должен быть вызван один раз на дерево сборки или что? Как использовать разные настройки для каждой сборки если все они используют одни и те же CMakeLists из одного источника?
Зачем каждому подкаталогу нужны свои собственные CMakeLists? Имеет ли смысл использовать CMake в CMakeLists в корне проекта? Если да, то в каких случаях? В чем разница между указанием того, как построить исполняемый файл или библиотеку из CMakeLists в их собственном подкаталоге, и тем, как это сделать в CMakeLists в корне всего источника?
Могу ли я сделать проект для Eclipse и другой для Visual Studio, просто изменив-G опция при вызове CMake? Это даже то, как он используется?



ни один из учебников, страниц документации или вопросов/ответов, которые я видел до сих пор, не дает никакого полезного представления о том, как использовать CMake. Примеры просто не доскональны. Независимо от того, какие учебники я читаю, я чувствую, что мне не хватает чего-то важного.



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

1296   2  

2 ответов:

что такое CMake для?

согласно Википедии:

CMake is [...] программное обеспечение для управления процессом сборки программного обеспечения использование независимого от компилятора метода. Он предназначен для поддержки иерархии каталогов и приложения, которые зависят от нескольких библиотеки. Он используется в сочетании с собственными средами сборки например, make, Xcode от Apple и Microsoft Visual Studio.

с CMake, вы больше не необходимо поддерживать отдельные настройки, характерные для вашей среды компилятора/сборки. У вас есть один конфигурации, и это работает для много средах.

CMake может создать решение Microsoft Visual Studio, проект Eclipse или лабиринт Makefile из то же самое файлы, ничего не меняя в них.

учитывая кучу каталогов с кодом в них, CMake управляет всеми зависимостями, строит заказы и другие задачи, которые необходимо выполнить перед компиляцией проекта. На самом деле он ничего не компилирует. Чтобы использовать CMake, вы должны сказать это (используя файлы конфигурации, называемые CMakeLists.txt) какие исполняемые файлы вам нужно скомпилировать, на какие библиотеки они ссылаются, какие каталоги есть в вашем проекте и что находится внутри них, а также любые детали, такие как флаги или что-нибудь еще вам нужно (CMake довольно мощный).

если это правильно настроено, вы затем используете CMake для создания всех файлы, которые ваша" родная среда сборки " по выбору должна выполнять свою работу. В Linux, по умолчанию, это означает Makefiles. Поэтому, как только вы запустите CMake, он создаст кучу файлов для собственного использования плюс некоторые Makefiles. все, что вам нужно сделать после этого, это ввести "make" в консоли из корневой папки каждый раз, когда вы закончите редактирование кода, и bam, скомпилированный и связанный исполняемый файл будет сделан.

как работает CMake? Что он делает?

вот пример настройки проекта что я буду использовать во всем:

simple/
  CMakeLists.txt
  src/
    tutorial.cxx
    CMakeLists.txt
  lib/
    TestLib.cxx
    TestLib.h
    CMakeLists.txt
  build/

содержимое каждого файла показано и обсуждается позже.

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

я не знаю, что произойдет, если вы выполните cmake на любой другой, кроме корня CMakeLists.txt.

в этом примере, так как я хочу, чтобы все это размещалось внутри build/ папка, сначала я должен перейти туда, а затем передать CMake каталог, в котором корень CMakeLists.txt проживает.

cd build
cmake ..

по умолчанию, это устанавливает все с помощью Makefiles, как я уже сказал. Вот как теперь должна выглядеть папка сборки:

simple/build/
  CMakeCache.txt
  cmake_install.cmake
  Makefile
  CMakeFiles/
    (...)
  src/
    CMakeFiles/
      (...)
    cmake_install.cmake
    Makefile
  lib/
    CMakeFiles/
      (...)
    cmake_install.cmake
    Makefile

что все эти файлы?единственное, о чем вам нужно беспокоиться, это Makefile и папки проекта.

обратите внимание на src/ и lib/ папки. Они были созданы, потому что simple/CMakeLists.txt указывает на них с помощью команды add_subdirectory(<folder>). Этот команда говорит CMake искать в указанной папке для другого CMakeLists.txt файл и выполните команду это скрипт, поэтому каждый подкаталог добавлен таким образом должны есть внутри. В этом проекте simple/src/CMakeLists.txt описывает, как построить фактический исполняемый файл и simple/lib/CMakeLists.txt описывает, как построить библиотеку. Каждая цель, что a CMakeLists.txt описание будет размещено по умолчанию в его подкаталоге в дереве сборки. Итак, после быстрого

make

в консоли сделано из build/ некоторые файлы добавлены:

simple/build/
  (...)
  lib/
    libTestLib.a
    (...)
  src/
    Tutorial
    (...)

проект построен, и исполняемый файл готов к выполнению. что вы делаете, если хотите, чтобы исполняемые файлы помещались в определенную папку?установите соответствующую переменную CMake или измените свойства конкретной цели. Подробнее о переменных CMake позже.

как мне сказать CMake, как построить мой проект?

вот содержание, объяснил, каждого файла в исходном каталоге:

simple/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6)

project(Tutorial)

# Add all subdirectories in this project
add_subdirectory(lib)
add_subdirectory(src)

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

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

Как упоминалось ранее, add_subdirectory() добавляет папку в проект, что означает, что CMake ожидает, что у него будет CMakeLists.txt в этом, он будет работать, прежде чем продолжить. Кстати, если у вас есть определенная функция CMake, вы можете использовать ее из других CMakeLists.txt в подкаталогах, но вы должны определить до вы используете add_subdirectory() или он не найдет его. CMake это умнее, о библиотеках, хотя, так что это, вероятно, единственный раз, когда вы столкнетесь с этой проблемой.

simple/lib/CMakeLists.txt:

add_library(TestLib TestLib.cxx)

чтобы сделать свой собственный библиотека, вы даете ей имя, а затем перечисляете все файлы, из которых она построена. Простой. Если ему нужен другой файл,foo.cxx, чтобы быть скомпилированным, вы бы вместо этого написали add_library(TestLib TestLib.cxx foo.cxx). Это также работает для файлов в других каталогах, например add_library(TestLib TestLib.cxx ${CMAKE_SOURCE_DIR}/foo.cxx). Подробнее о переменной CMAKE_SOURCE_DIR позже.

еще одна вещь, которую вы можете сделать с этим, это указать, что вы хотите общую библиотеку. Пример: add_library(TestLib SHARED TestLib.cxx). Не бойтесь, это то, где CMake начинает делать вашу жизнь проще. Так ли это общий или нет, теперь все, что вам нужно обработать, чтобы использовать библиотеку, созданную таким образом, - это имя, которое вы дали ей здесь. Имя этой библиотеки теперь TestLib, и вы можете ссылаться на него из в любом месте в проект. CMake найдет его.

есть ли лучший способ перечислить зависимости?определенно да. Проверьте ниже для получения дополнительной информации этот.

simple/lib/TestLib.cxx:

#include <stdio.h>

void test() {
  printf("testing...\n");
}

simple/lib/TestLib.h:

#ifndef TestLib
#define TestLib

void test();

#endif

simple/src/CMakeLists.txt:

# Name the executable and all resources it depends on directly
add_executable(Tutorial tutorial.cxx)

# Link to needed libraries
target_link_libraries(Tutorial TestLib)

# Tell CMake where to look for the .h files
target_include_directories(Tutorial PUBLIC ${CMAKE_SOURCE_DIR}/lib)

команда add_executable() работает точно так же, как add_library(), за исключением, конечно, будет генерировать исполняемый файл. Этот исполняемый файл теперь можно ссылаться в качестве цели для таких вещей, как target_link_libraries(). Начиная с учебника.cxx использует код, найденный в библиотеке TestLib, вы указываете на это CMake, как показано на рисунке.

аналогично .H-файлы #включено любыми источниками в add_executable() что это не в том же каталоге, что и источник, нужно как-то добавить. Если бы не , lib/TestLib.h не будет найден при компиляции учебника, так что весь lib/ папка добавляется в каталоги include для поиска #includes. Вы также можете увидеть команду include_directories() который действует аналогичным образом, за исключением того, что вам не нужно указывать цель, поскольку он прямо устанавливает ее глобально для всех выполнимые программы. Еще раз, я объясню CMAKE_SOURCE_DIR позже.

simple/src/tutorial.cxx:

#include <stdio.h>
#include "TestLib.h"
int main (int argc, char *argv[])
{
  test();
  fprintf(stdout, "Main\n");
  return 0;
}

обратите внимание, как "TestLib.файл H", включен. Нет необходимости включать полный путь; CMake заботится обо всем, что за кулисами благодаря target_include_directories().

Технически говоря, в простом исходном дереве, как это можно обойтись без CMakeLists.txt s под lib/ и src/ и просто добавляя что-то вроде add_executable(Tutorial src/tutorial.cxx) до simple/CMakeLists.txt. Это зависит от вас и вашего потребности проекта.

что еще я должен знать, чтобы правильно использовать CMake?

(АКА темы, относящиеся к вашему пониманию)

поиск и использование пакетов:ответ на этот вопрос это объясняет лучше, чем я когда-либо мог.

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

CMake переменные: есть много, так что ниже приведен ускоренный курс, чтобы вы на правильном пути. CMake wiki-это хорошее место, чтобы получить более подробную информацию о переменных и якобы другие вещи, а также.

вы можете редактировать некоторые переменные, не перестраивая дерево сборки. Используйте ccmake для этого (он редактирует CMakeCache.txt file). Не забывай configure, когда сделано с изменениями, а затем generate makefiles с обновленной конфигурацией.

читать ранее упомянутом учебнике сведения об использовании переменных, но короче: set(<variable name> value) для изменения или создания переменной. ${<variable name>} использовать его.

  • CMAKE_SOURCE_DIR: корневой каталог источник. В предыдущем примере, это всегда равен /simple
  • CMAKE_BINARY_DIR: корневой каталог построение. В предыдущем примере это равно simple/build/, но если вы запускали cmake simple/ из такой папки, как foo/bar/etc/, тогда все ссылки на CMAKE_BINARY_DIR в этом дереве сборки станет /foo/bar/etc.
  • CMAKE_CURRENT_SOURCE_DIR - каталог, в котором ток CMakeLists.txt в. Это означает, что он изменяется во всем: печать этого из simple/CMakeLists.txt доходность /simple, и печать его из simple/src/CMakeLists.txt доходность /simple/src.
  • CMAKE_CURRENT_BINARY_DIR: вы поняли идею. Этот путь будет зависеть не только от папка, в которой находится сборка, но также и на текущем скрипта.

почему это важно? Исходные файлы, очевидно, не будет в дереве сборки. Если вы попробуете что-то вроде target_include_directories(Tutorial PUBLIC ../lib) в предыдущем примере этот путь будет относительно дерева сборки, то есть это будет похоже на запись ${CMAKE_BINARY_DIR}/lib, который будет смотреть внутрь simple/build/lib/. Нет .H файлы там; в лучшем случае вы найдете libTestLib.a. Ты хочешь ${CMAKE_SOURCE_DIR}/lib вместо.

  • CMAKE_CXX_FLAGS: флаги для передачи компилятору, в данном случае компилятору C++. Также стоит отметить CMAKE_CXX_FLAGS_DEBUG, который будет использоваться, если CMAKE_BUILD_TYPE установлен для отладки. Есть еще такие; проверьте Вики CMake.
  • CMAKE_RUNTIME_OUTPUT_DIRECTORY: скажите CMake, где разместить все исполняемые файлы при сборке. Это глобальная настройка. Вы можете, например, установить его в bin/ и там все аккуратно разложено. EXECUTABLE_OUTPUT_PATH похож, но устарел, если вы наткнетесь на него.
  • CMAKE_LIBRARY_OUTPUT_DIRECTORY: аналогично, глобальная настройка, чтобы сказать CMake, куда поместить все файлы библиотеки.

целевые свойства: вы можете установить свойства, которые влияют только на одну цель, будь то исполняемый файл или библиотека (или архив... вы поняли идею). вот хороший пример о том, как его использовать (с set_target_properties().

есть ли простой способ добавить источники к цели автоматически? использовать GLOB чтобы перечислить все в данном каталоге под той же переменной. Пример синтаксиса -FILE(GLOB <variable name> <directory>/*.cxx).

вы можете указать различные типы сборки? да, хотя я не уверен, как это работает или ограничивает. Вероятно, это требует некоторого if / then'Ning, но CMake предлагает некоторую базовую поддержку без настройки чего-либо, например, по умолчанию для CMAKE_CXX_FLAGS_DEBUG, например. Вы можете либо установить свой тип сборки от внутри через set(CMAKE_BUILD_TYPE <type>) или вызывая CMake из консоли с соответствующими флагами, например cmake -DCMAKE_BUILD_TYPE=Debug.

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

использование переменных из CMake в вашем коде: вот быстрый и грязный пример (взято из какой-то другой учебник):

simple/CMakeLists.txt:

project (Tutorial)

# Setting variables
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 1)

# Configure_file(<input> <output>)
# Copies a file <input> to file <output> and substitutes variable values referenced in the file content.
# So you can pass some CMake variables to the source code (in this case version numbers)
configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_SOURCE_DIR}/src/TutorialConfig.h"
)

simple/TutorialConfig.h.in:

// Configured options and settings
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

полученный файл, созданный с помощью CMake, например, simple/src/TutorialConfig.h:

// Configured options and settings
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 1

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

для всего остального переполнение стека переполнено конкретными вопросами и краткими ответами, что отлично подходит для всех, кроме непосвященных.

вот некоторые (трудно найти, как и все о CMake) видео:

надеюсь, это поможет (и позор CMake и его плохая документация,#^&! ):)

Comments

    Ничего не найдено.