Как правильно настроить CMake для установки пакетов?

Я почти не знаком с C++, но в вузе мне задали практическую задачу, которую я хотел бы выполнить с использованием сторонних библиотек, пакетного менеджера и кросс-платформенного подхода. Я могу указать в README на необходимость установки всех зависимостей, но это выглядит не совсем профессионально. Мне хотелось бы, чтобы CMake автоматически справлялся с установкой недостающих зависимостей, возможно, даже используя пакетный менеджер. <br/> <br/> Какой пакетный менеджер будет наилучшим выбором в этом случае? Как правильно подключить его к CMake? Можно ли автоматизировать установку пакетного менеджера через CMake, или лучше упомянуть об этом в README? Вопрос в том, подходит ли использование пакетного менеджера для "взрослых" решений в C++?
  • 28 октября 2024 г. 14:42
Ответы на вопрос 2
Настройка CMake для установки пакетов и использование пакетного менеджера — это действительно хороший подход для управления зависимостями в C++ проектах. Вот несколько рекомендаций, которые помогут вам правильно организовать этот процесс.

### Выбор пакетного менеджера

1. **Conan**: Один из самых популярных пакетных менеджеров для C++. Он хорошо интегрируется с CMake и имеет широкую базу с готовыми пакетами. А также поддерживает Windows, Linux и macOS.
   
2. **vcpkg**: Еще один мощный пакетный менеджер, который также поддерживает кросс-платформенность. Он предлагает простой интерфейс и хорошо справляется с установкой и управлением зависимостями.

3. **Hunter**: Это система управления зависимостями, которая интегрируется с CMake. Она управляет зависимостями, загружая их из своих репозиториев при сборке проекта.

### Настройка CMake с пакетом

Рассмотрим, как можно использовать **Conan** и **CMake**:

1. **Установка Conan**: Убедитесь, что у вас установлен Conan. Вы можете установить его через `pip`:

    ```bash
    pip install conan
    ```

2. **Создание конфигурации Conan**: Создайте файл `conanfile.txt` в корне вашего проекта для указания необходимых зависимостей. Пример:

    ```
    [requires]
    fmt/8.0.0  # Пример зависимости

    [generators]
    cmake
    ```

3. **Использование Conan в CMake**: В ваш `CMakeLists.txt` добавьте несколько строк для интеграции Conan:

    ```cmake
    cmake_minimum_required(VERSION 3.15)
    project(MyProject)

    include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
    conan_basic_setup()

    add_executable(MyExecutable main.cpp)
    target_link_libraries(MyExecutable ${CONAN_LIBS})
    ```

4. **Сборка с Conan**: Перед сборкой вы можете создать скрипт, который будет автоматически запускать Conan для установки зависимостей:

    ```bash
    mkdir build
    cd build
    conan install .. --build=missing
    cmake ..
    make
    ```

### Автоматизация установки пакетного менеджера

Автоматизировать установку самого пакетного менеджера (например, Conan) через CMake не очень распространенная практика, так как не все пользователи могут быть согласны устанавливать что-то на своем компьютере без их ведома. Поэтому лучше всего упомянуть об этом в вашем `README`, чтобы пользователи заранее знали о необходимых шагах:

```markdown
## Установка зависимостей

Перед сборкой проекта убедитесь, что установлен **Conan**. Вы можете установить его с помощью:

```bash
pip install conan
```

После этого выполните:

```bash
mkdir build
cd build
conan install .. --build=missing
cmake ..
make
```
```

### Заключение

Использование пакетного менеджера в C++ — это профессиональный подход, который упрощает управление зависимостями и ускоряет процесс сборки. **Conan** и **vcpkg** идеально подходят для этой задачи. Их интеграция с CMake довольно проста, и вы сможете эффективно управлять проектами с сторонними библиотеками и зависимостями. Не забывайте информировать пользователей о необходимых шагах для настройки окружения в вашем `README`.
Самому заниматься установкой зависимостей есть смысл только для статически линкуемых библиотек. В этом случае самый простой вариант такие библиотеки оформить например как субмодуль git. Тогда при клонировании вашего репозитория скачаются исходники библиотеки. В cmake просто собираете ее как отдельный таргет и используете по назначению. Хорошо если библиотека уже поддерживает сборку через cmake - будет меньше возни. Если нет, то придется написать самому для нее CMakeLists.txt. 

Для динамических библиотек стоит оставить удовлетворение зависимостей пользователю, потому что вариантов пакетных менеджеров много (вы хотите их все поддерживать?). В вашем CMakeLists.txt нужно только сделать тем или иным способом поиск установленного пакета и если его нет - выдачу ошибки и завершение сборки. Такие механизмы в cmake есть. Можно использовать выше приведенный find_package или например pkg_check_modules (который в свою очередь использует утилиту pkg-config).
Почти все более-менее серьезные приложения не пытаются установить самостоятельно свои зависимости при сборке. Можете проверить. Например: https://github.com/nginx/nginx?tab=readme-ov-file#...

Вы можете дополнительно к сборке приложения добавить и создание пакета для пакетного менеджера (или для нескольких пакетных менеджеров). Вот тут то вы и укажите необходимые приложению зависимости (в разных дистрибутивах линукс пакеты с зависимостями могут называться по разному). И тогда, когда пользователь будет устанавливать ваш пакет через пакетный менеджер все зависимости установятся автоматически.
В cmake есть механизм для создания пакетов для разных пакетных менеджеров: https://cmake.org/cmake/help/book/mastering-cmake/...
Похожие вопросы