Cmake с нуля для нескольких каталогов проекта - PullRequest
0 голосов
/ 01 февраля 2019

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

Точка 1 - Нужно ли создавать отдельный файл CMakeLists.txt для каждой папки (да, для простоты давайте назовем это папкой)?

Точка 2 - Очевидно Ответ на Точку 1 равен НЕТ .Я нашел эти команды для автоматизации поиска *.cpp файлов

# get all *.cpp files recursively
file(GLOB_RECURSE SRC_LIST *.c* *.h*)

Точка 3 - Кажется, нет необходимости упоминать файл *.hpp.(Это неопределенно балл)

Я попытался скомпилировать ПРОСТОЙ Hello World! program

CMakeLists.txt
src
| - main.cpp (here I included #include "XYZ/abc.hpp")
| - XYZ
    | - abc.cpp (included #include "XYZ/abc.hpp")
    | - abc.hpp

ИCMake для этого был

cmake_minimum_required(VERSION 3.10)
project(CMAkeSample)
add_executable(hello src/main.cpp src/XYZ/abc.cpp)

Это говорит о том, что добавьте все файлы .cpp вместе с путем в add_executable, и все готово.Это правда?

Точка 4 - Теперь у меня есть сравнительно большой проект (разработанный в Eclipse для по любой причине ).Но мне нужно создать для него файл cmake и, следовательно, не использовать eclipse для сборки.

ниже - файловая система, и я хочу сделать CMakeLists.txt только один раз (если это возможно)

CMakeLists.txt
src
| - main.cpp (here I included #include "File0.hpp" and #include "Folder1/File1.hpp")
| - File0.cpp (here I included #include "File0.hpp")
| - File0.hpp (here I included #include "Folder1/File1.hpp" and #include "Folder2/File2.hpp")
| - Folder1
    | - File1.cpp (included #include "File1.hpp")
    | - File1.hpp
| - Folder2
    | - File2.cpp (included #include "File2.hpp")
    | - File2.hpp

Итак, теперь Как получить все .cpp файлы, не записывая вручную cmake в каждую папку.Любые предложения?

ОБНОВЛЕНИЕ 1: Я добавил CMakeLists.txt, как показано

ProjectFolder
    CMakeLists.txt
    src
    | - CMakeLists.txt
    | - main.cpp (here I included #include "File0.hpp" and #include "Folder1/File1.hpp")
    | - File0.cpp (here I included #include "File0.hpp")
    | - File0.hpp (here I included #include "Folder1/File1.hpp" and #include "Folder2/File2.hpp")
    | - Folder1
        | - CMakeLists.txt
        | - File1.cpp (included #include "File1.hpp")
        | - File1.hpp
    | - Folder2
        | - CMakeLists.txt
        | - File2.cpp (included #include "File2.hpp")
        | - File2.hpp

В ProjectFolder> src> CMakeLists.txt

add_library(main main.cpp File0.cpp File0.hpp)
target_link_libraries(main File1)

In ProjectFolder> src> File1> CMakeLists.txt

add_library(File1 File1.cpp File1.hpp)
target_link_libraries(File1 File2)

In ProjectFolder> src> Файл> CMakeLists.txt

add_library(File2 File2.cpp File2.hpp)

После всего этого я получаю сообщение об ошибке:

-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/ProjectFolder
[ 33%] Built target main
[ 44%] Building CXX object CMakeFiles/ProjectFolder.dir/src/main.cpp.o
[ 55%] Linking CXX executable ProjectFolder
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: cannot find -lFile1

ОБНОВЛЕНИЕ 2:

Идем дальше, чтобы сделать эторабота, Несколько изменений здесь и там были сделаны (как указано в ОБНОВЛЕНИЕ 1 и добавлены ссылки вручную в CMakeLists.txt папки проекта как

set(GCC_LINK_FLAGS "-lpthread -lcurl -lgobject-2.0 -lgstreamer-1.0 -lglib-2.0 -lssl -lcrypto -lboost_thread -lboost_system")
add_subdirectory(src)
add_subdirectory(src/Folder1)
add_subdirectory(src/Folder2)

add_executable(ProjectFolder src/main.cpp)
target_link_libraries(ProjectFolder main ${GCC_LINK_FLAGS})

Программа выполняется отлично. Ноочевидно, это очень грубый способ написания ссылок. Поиск решения для Point2 .

1 Ответ

0 голосов
/ 01 февраля 2019

Пункт 1 - Нужно ли создавать отдельный файл CMakeLists.txt для каждой папки (да, для простоты будем называть это папкой)?

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

Для папок с подпапками вам может понадобиться CMakeLists.txtкоторый содержит только add_subdirectory() команд.(См. Пример ниже.)

Можно даже создать CMakeLists.txt, который рассматривает источники из нескольких подпапок.Я однажды написал ответ по этому поводу.( ТАК: достаточно одного CMakeLists.txt для моего проекта? ) Хотя, посмотрите на голоса - не так много людей, которые считают это хорошей идеей.; -)

Пункт 2 - Очевидно, ответом на пункт 1 является НЕТ.Я нашел эти команды для автоматизации поиска * .cpp файлов

Мы широко используем его, но есть и рекомендации не делать этого.

Недостатком является то, что ваша цепочка сборкине распознает автоматически при добавлении новых источников.Если вы явно дадите имена всем источникам в CMakeLists.txt, это может быть предоставлено.

С CMake doc. :

Примечание : Мы не рекомендуем использовать GLOB для сбора списка исходных файлов из дерева исходных текстов.Если файл CMakeLists.txt не изменяется при добавлении или удалении источника, сгенерированная система сборки не может знать, когда попросить CMake сгенерировать заново.Флаг CONFIGURE_DEPENDS может работать не надежно на всех генераторах, или если в будущем будет добавлен новый генератор, который не сможет его поддерживать, проекты, использующие его, будут заблокированы.Даже если CONFIGURE_DEPENDS работает надежно, проверка каждой перестройки все еще требует затрат.

Поэтому, используя file(GLOB, вы никогда не должны забывать перезапускать CMake явно один раз.файлы были добавлены, перемещены или удалены.

Пункт 3 - Кажется, нет необходимости упоминать файл * .hpp.(Это смутное замечание)

Да, это не обязательно, поскольку включаемые файлы упоминаются в файлах cpp.С другой стороны, мы используем CMake с VS2013.Хорошо, если вы найдете все заголовки в соотв.Папка проекта VS.Итак, я бы рекомендовал упомянуть и о включении.(Похоже, что CMake достаточно умен, чтобы отделить их от источников. Поэтому он не будет создавать команды сборки для заголовочных файлов.)

Пункт 4 - Теперь у меня есть сравнительно большой проект (разработанный в Eclipse).для любой причины).Но мне нужно создать для него файл cmake и, следовательно, не использовать eclipse для сборки.

CMake - сборщик скриптов сборки.Мы используем его для создания решений и проектов VS.Я уверен, что он также может создавать Makefiles для Linux.К сожалению, у меня нет практического опыта по этому поводу.(На самом деле, именно по этой причине мы перешли на CMake - чтобы можно было переносить сборку нашего портативного письменного исходного кода.


Кстати. Есть введение в cmake.org:

CMake Tutorial


Пример:

Представьте себе следующее дерево каталогов для приложения myApp:

└─ MyApp/
  ├─ main/
  │ ├─ CMakeLists.txt
  │ └─ myApp.cc
  ├─ gui/
  │ ├─ CMakeLists.txt
  │ ├─ guiMainWindow.cc
  │ └─ guiMainWindow.h
  ├─ model/
  │ ├─ CMakeLists.txt
  │ ├─ model.cc
  │ └─ model.h
  └─ CMakeLists.txt 

* * MyApp/CMakeLists.txt не отвечает за исходный код, но собирает сценарии сборки подпапок. Это может выглядеть так:

# MyApp/CMakeLists.txt

# make a project
project(MyApp)
# This will generate a MyApp solution for VisualStudio
# containing all involved projects.

# add sub-folders which have to be considered
add_subdirectory(main)
add_subdirectory(gui)
add_subdirectory(model)

* MyApp/model может содержать библиотекудля базовой модели данных MyApp без дополнительных зависимостей. Таким образом, MyApp/model/CMakeLists.txt может выглядеть следующим образом:

# MyApp/model/CMakeLists.txt

# build rule for library libmodel
add_libary(model
  model.cc model.h)

MyApp/gui может предоставить другую библиотеку для графического интерфейса MyApp с зависимостями дляlibmodel. MyApp/gui/CMakeLists.txt может выглядеть так:

# MyApp/gui/CMakeLists.txt

# build rule for library libgui
add_libary(gui
  guiMainWindow.cc guiMainWindow.h)

# dependencies
target_link_libraries(gui
  model)

Наконец, MyApp/main предоставляет исходный код для функции main() MyApp и создает исполняемый файл. MyApp/main/CMakeLists.txt может выглядетькак это:

# MyApp/main/CMakeLists.txt

# build rule for executable myApp
add_executable(myApp
  myApp.cc)

# dependencies
target_link_libraries(myApp
  gui model)
...