LINUX.ORG.RU

Чем нынче принято собирать проекты на плюсах в приличном обществе?

 , , ,


0

3

После долгого перерыва начинаю новый проект на плюсах. Кроссплатформенный, с гуем на dear imgui и парой либ в зависимостях. Хочется кроссплатформенной сборки без бубнов и обмазывания скриптами + управление зависимостями. Попробовал vcpkg + cmake и чёт оно какое-то костыльное, аж блевать тянет. Неужто за все эти годы ничего нормального для плюсов не сделали?

На CMake принято делать.

Если нужно делать инсталяки/пакеты/подпись, то все равно под каждую платформу будешь гемроиться.

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

rumgot ★★★★★
()

vcpkg + cmake

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

И если его использование под Виндой я понимаю, то для Linux его необходимость воспринимаю с трудом.

WatchCat ★★★★★
()
Ответ на: комментарий от dictator2000

Головняк, конечно, тот, но если разберёшься, то дальше норм. Я сборку сделал для хоста и для RPi4. Больше ушло время на тулчейн и на sysroot. Как раз vcpkg/cmake/manifest, sdl, asio, imgui. Потребовался свой триплет. И тулчейн файл нужно подключать как для своего проекта через «VCPKG_CHAINLOAD_TOOLCHAIN_FILE», так и в триплете:

set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/../toolchain-cross-raspberry_pi-linux-w64.cmake)

А в самом тулчейне потребуется хак вроде:

if (NOT DEFINED ENV{PROJ_DIR})
    set(ENV{PROJ_DIR} ${CMAKE_CURRENT_LIST_DIR})
endif()

set(PROJ_DIR $ENV{PROJ_DIR})

если нужно ссылаться на что-то относительно проектной директории. У меня используется для компиляторов и sysroot:

set(CMAKE_C_COMPILER   ${PROJ_DIR}/toolchain/cross-pi-gcc-13.2.0-64/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${PROJ_DIR}/toolchain/cross-pi-gcc-13.2.0-64/bin/aarch64-linux-gnu-g++)
...
SET(ROOTFS ${PROJ_DIR}/rootfs)

и обязательно не затирать CMAKE_FIND_ROOT_PATH:

# Don't use SET here. Frameworks like vcpkg may provide additional
# paths for find_library() and find_path() work when CMAKE_FIND_ROOT_PATH_MODE_xxx sets to ONLY
list(APPEND CMAKE_FIND_ROOT_PATH ${ROOTFS})

Итого:

vcpkg.json

{
    "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
    "dependencies": [
        "asio",
        "cxxopts",
        "sdl2pp",
        {
            "features": [
                "sdl2-renderer-binding",
                "sdl2-binding"
            ],
            "name": "imgui"
        },
        "simpleini"
    ],
    "name": "pet-project",
    "version-string": "0.0.1"
}

vcpkg-configuration.json:

{
  "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg-configuration.schema.json",
  "overlay-ports": [
    "./custom-ports"
   ],
  "overlay-triplets": [ "./custom-triplets" ]
}

toolchain-cross-raspberry_pi-linux-w64.cmake:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_CROSSCOMPILING TRUE)

# specify the cross compiler
#set(CMAKE_C_COMPILER   aarch64-linux-gnu-gcc)
#set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

if (NOT DEFINED ENV{PROJ_DIR})
    set(ENV{PROJ_DIR} ${CMAKE_CURRENT_LIST_DIR})
endif()

set(PROJ_DIR $ENV{PROJ_DIR})

set(CMAKE_C_COMPILER   ${PROJ_DIR}/toolchain/cross-pi-gcc-13.2.0-64/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${PROJ_DIR}/toolchain/cross-pi-gcc-13.2.0-64/bin/aarch64-linux-gnu-g++)

message(STATUS "PROJ_DIR: ${PROJ_DIR}")

SET(ROOTFS ${PROJ_DIR}/rootfs)
# Setting CMAKE_SYSROOT break builds in most cases
#SET(CMAKE_SYSROOT  ${ROOTFS})
# Don't use SET here. Frameworks like vcpkg may provide additional
# paths for find_library() and find_path() work when CMAKE_FIND_ROOT_PATH_MODE_xxx sets to ONLY
list(APPEND CMAKE_FIND_ROOT_PATH ${ROOTFS})

message(STATUS "CMAKE_FIND_ROOT_PATH: ${CMAKE_FIND_ROOT_PATH}")

# TBD
#SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${ROOTFS}/usr/include")
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${ROOTFS}/usr/include")

# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories.
# If pointed ONLY, than find_path() and find_library() will work only with
# paths in the CMAKE_FIND_ROOT_PATH
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

SET(ENV{PKG_CONFIG_SYSROOT_DIR} ${ROOTFS})
SET(ENV{PKG_CONFIG_LIBDIR} ${ROOTFS}/usr/lib/pkgconfig:${ROOTFS}/usr/share/pkgconfig:${ROOTFS}/usr/lib/aarch64-linux-gnu/pkgconfig)

#set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-z,relro ${CMAKE_SHARED_LINKER_FLAGS}")
#set(CMAKE_MODULE_LINKER_FLAGS "-Wl,-z,relro ${CMAKE_MODULE_LINKER_FLAGS}")
#set(CMAKE_EXE_LINKER_FLAGS    "-Wl,-z,relro ${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")%                                                                                                                              

custom-triplets/arm64-linux-rpi4.cmake:

set(VCPKG_TARGET_ARCHITECTURE arm64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Linux)

set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/../toolchain-cross-raspberry_pi-linux-w64.cmake)

message(STATUS "--htrd: VCPKG_CHAINLOAD_TOOLCHAIN_FILE: ${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}")
message(STATUS "--htrd: CMAKE_CURRENT_LIST_DIR: ${CMAKE_CURRENT_LIST_DIR}")

И вызывать всё это дело так:

cmake -S . -B build-cross -G Ninja \
    -DCMAKE_TOOLCHAIN_FILE=$(pwd)/vcpkg/scripts/buildsystems/vcpkg.cmake \
    -DVCPKG_TARGET_TRIPLET=arm64-linux-rpi4 \
    -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$(pwd)/toolchain-cross-raspberry_pi-linux-w64.cmake

cmake --build build-cross --target all

cmake --install build-cross --prefix build-cross-install/usr

Сборка компилятора и rootfs это было отдельной песней :)

hatred ★★★
()
Ответ на: комментарий от WatchCat

Пока не оказывается, что дистрибутивы разные у разработчиков, где-то может вообще не быть нужной зависимости или быть очень старой, или быть слишком новой и так далее. А нужна воспроизводимость билда. А! Ещё иногда нужно статику, а далеко не везде в дистрах строят статические либы. В общем ситуации разные бывают и инструмент подобный vcpkg нужен.

hatred ★★★
()
Ответ на: комментарий от hatred

Наоборот, надо делать сборку так, чтобы собиралась и работала на неком множестве основных дистибутивов, с тамошними версиями библиотек. А не тащить с собой 100500 библиотек. А то знаю я таких оригиналов которые на 6-м шланге до сих пор компилируют. Причём жёстко прописали его пути в cmake-е и чтобы собрать их поделие приходится выкачивать 100500 древних версий бинарных сборок.

WatchCat ★★★★★
()
Ответ на: комментарий от WatchCat

Понимаешь в чём дело, vcpkg вцелом отвязывается от проекта достаточно просто: достаточно не указывать vcpkg.cmake как тулчейн.

И, в целом, проектный файл должен уметь собираться так. Мой приведённый выше проект так умеет. Если не умеет, то задавайте вопросы, а лучше шлите патч (или вам тоже все должны?). Но… У меня две целевые платформы: Host x86_64 и RPi4 и, возможно, какой-то другой. И вот мне для отладки тупо нужно быть уверенным, что версии библиотек, основных, проектных, там идентичны. Более того, каждый раз пересобирать rootfs для кросс-сборки - упасите пожалуйста.

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

А для маинтейнеров пакетов. Ну ок, просто не указывается vcpkg. Если будут проблемы со сборкой: репорт или патч.

Плюс вы явно не сталкивались с ситуацией, когда:

  1. есть жёсткие временные ограничения и нужно сделать быстро.
  2. нужной библиотеки в системе нет, при этом vcpkg позволяет просто положить свой оверлей и собрать нужный пакет.
  3. софт корпоративный, использует для сборки внутренние библиотеки, которые шарятся с другими проектами. Можно, конечно, запакетировать, но у меня вызывают адовую боль спеки для сборки у того же Debian и птичий язык спеков RPM. Простой и понятный язык, разве что у PKGBUILD.

Ну и на последок: vcpkg можно указать, что бы он предпочитал использовать системные библиотеки, если есть.

Ругать импакт за то, что есть шуруповёрт глупо, как и наоборот :) Когда инструмент есть, но он тебе не нужен - это ок. Плохо, когда он нужен, а его нет.

hatred ★★★
()
Ответ на: комментарий от EXL

Там автор явно просто инструментов пользоваться не умеет. Если задача настолько проста, зачем ему вообще CMake? Это как импактом болтики в ноутбуке закручивать: можно, можно даже ничего не сломать, но зачем?

hatred ★★★
()
Ответ на: комментарий от next_time

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

hatred ★★★
()