Затруднительное положение - PullRequest
2 голосов
/ 29 апреля 2020

Я работаю над проектом C ++. Пока это не так сложно, но зависит от нескольких «популярных» библиотек (nlohmann / json, ToruNiina / toml11 и другие). У всех них есть CMakeLists.txt, и, с моей неопытной точки зрения, я считаю их хорошо структурированными.

Теперь, конечно, я могу скомпилировать библиотеки одну за другой или включить «копию» в мой проект репо, но я хочу быть лучше, чем это. Изучив доступные инструменты сборки, я решил использовать cmake для сборки и управления проектом C ++. Обещанием было получить стабильный, широко поддерживаемый инструмент, который поможет упростить и унифицировать процесс сборки. Более того, из-за характера проекта у меня нет привилегий навязывать какие-либо требования целевой машине; Мне нужно собрать все для развертывания.

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

Я прочитал статей о том, почему бы не объединить зависимости, а за ними следуют методы для этого . Я нашел рекомендацию использовать один путь A над B, C над B и позже A над C. Мне потребовалось некоторое время, чтобы выяснить разницу между 2.8 и 3.0, obscurity из target_link_libraries, установкой флагов cxx версии и / или предупреждений компилятора и так далее.

Я хочу сказать, что даже после изнурительной экспедиции в моря cmake я все еще не уверен в некоторых элементарных вопросах:

Как использовать cmake?

Что такое стандарт, что такое вежливость, а что нет?

Как я могу сказать, что что-то является функцией, обратной совместимостью archai c или и тем, и другим?

Теперь я проиллюстрирую это на своем проекте. Мне нужно только что-то вроде этого

cmake_minimum_required(VERSION 3.14)
project(CaseCore CXX)

add_executable(myBinary list/of/cpp/sources.cpp)
target_link_libraries(myBinary PUBLIC someExternalLibs likeForExample nlohmann_json::nlohmann_json oqs)

Единственная проблема - с библиотеками (в любом случае нет места для других проблем). Я хочу построить их с проектом и не хочу делать локальную копию (не тащить кучу несвязанных файлов все время). Во-первых, я создал вилки для библиотечных репозиториев, чтобы иметь надежный источник и иметь возможность объединять более новые версии в мой форк.

Теперь было решено, использовать ли git submodule или какую-то другую схему. Подмодуль read не очень хорошо работает, а также предпочитает, чтобы все это управлялось одним cmake. Я начал с ExternalProject_Add, но позже обнаружил около FetchContent, который помог мне легко добавить внешние зависимости в мой список cmake

FetchContent_Declare(nlohmann
    GIT_REPOSITORY https://github.com/my-reliable-fork-of/json
    GIT_TAG v3.7.3
)
message(STATUS  "Fetching Json...this may take a while")
FetchContent_MakeAvailable(nlohmann)

Кажется, работает хорошо и минимально. Однако мне всегда приходится искать в самой библиотеке, чтобы найти / угадать , какие цели связаны с моей исполняемой целью ? Кажется, что соглашение близко к нулю, и если соответствующий CMakeLists.txt не достаточно прост для его чтения, я склонен угадывать имена целей, пока не найду его.

Недавно я хотел связать liboqs с здесь и вышеупомянутый сценарий не очень помог; по какой-то причине я могу связать oqs, #include "oqs/oqs.h", но библиотека Dynami c не создается и выполнение прекращается. Я почти уверен, что смогу решить проблему после еще одного периода времени, проведенного в поиске и поиске различных переменных cmake Однако я не ожидал, что cmake поможет мне управлять моим проектом; на самом деле все как раз наоборот.

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

add_subdirectory from local repo copy (git submodule)
ExternalProject_Add from local repo copy (git submodule)
ExternalProject_Add from online repo
find_package

, так как они казались гораздо более неясными / по старому стилю et c ( несмотря на то, что, несмотря на часы исследований, все они кажутся такими же, как и многие другие способы сделать то же самое для меня)

Теперь, когда у меня есть

Я что-то не так делаю, или действительно, как должна выглядеть работа с cmake?

Действительно ли мне нужно "перепроектировать" чужие списки CMakeLists, чтобы использовать библиотеку?

В таких условиях, как я могу убедить своих коллег использовать аналогичный рабочий процесс?

и, наконец,

Как мне настроить свою работу, чтобы облегчить эти трудности для других?

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

1 Ответ

1 голос
/ 29 апреля 2020

Как предполагается использовать cmake?

Типичное использование cmake соответствует старому использованию автоинструментов:

$ cmake /path/to/src #replaces /path/to/src/configure
$ make
$ make install

Некоторые цели изменены (например, make check vs make test), и cmake не предоставляет все те же стандартные цели (например, make distclean), но использование, которое я использовал выше, - то, что будет делать большинство разработчиков (и поскольку cmake перезапускается сам, это действительно просто второй шаг большую часть времени).

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

Что такое стандарт, что такое вежливость, а что нет?

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

Хорошо ведущий себя проект cmake должен экспортировать свои цели (множество вопросов и ответов об этом в Stack Overflow) и распространять флаги и зависимостей. Это значительно облегчает зависимым проектам использование экспортированных целей, и, к счастью, это легко сделать.

Как я могу сказать, что что-то является функцией, обратной совместимостью archai c или и тем, и другим?

Я ничего не знаю о том, что делает эти различия. В целом, новые методы используют функции target_* вместо глобальных (например, target_include_directories против include_directories). Функции target_* также используются для распространения флагов, включают в себя каталоги, функции компилятора и зависимые библиотеки, как я упоминал выше.

Я делаю что-то не так, или это действительно то, что работа с cmake должна Похоже?

Вы говорите об управлении внешними зависимостями, и я собираюсь пропустить это, чтобы не получать мнения. Короткая версия заключается в том, что зависимости C и C ++ являются сложными, и существует множество конкурирующих способов управления ими в проекте. У каждого из них есть свои плюсы и минусы, но большинство из них по-прежнему предназначены для сценариев использования авторов. Вам нужно будет выяснить, какие варианты использования вам нужны, и выбрать инструменты и рабочие процессы на их основе.

Нужно ли мне "перепроектировать" чужие списки CMakeLists, чтобы использовать библиотеку ?

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

В таких условиях, как я могу убедить своих коллег использовать подобный рабочий процесс?

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

...