LINUX.ORG.RU

Использовать ли FHS?

 , , ,


0

1

Делаю игру на C++. Не могу определиться, куда правильнее складывать файлы при установке, вижу 3 варианта:

  • Соблюдать FHS, складывая бинарник в /usr/local/bin, локали в /usr/local/share/locale, иконки текстурки всякие в /usr/local/share/игра, настройки в ~/.config/игра, остальные файлы в /usr/lib/игра, тогда становится непонятно, как бинарник будет находить, где все эти файлы лежат, ведь префикс может отличаться, получается нужно юзать либо относительные директории, что, вроде как, плохое решение, либо ещё что-то.
  • Складывать всё это в папку игры, как вроде делают сейчас большинство разработчиков игр.
  • Сделать что-то среднее, что будет работать в обеих случаях, задавая директории в скрипте через переменные окружения.

Ещё игра кроссплатформенная, и хотелось бы по-минимуму платформозависимого кода.

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

префикс известен при компиляции

Harald ★★★★★ ()

На винде не будет ничего страшного, если файлы будут лежать в префиксе в соответствии с принципами FHS, т.е. C:\Program Files\MyGame\bin\game.exe, C:\Program Files\MyGame\lib и т.д., но путь к директориям скорей всего определять придётся относительно бинарника.

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

Harald ★★★★★ ()

Я за 2 варианта установки - stanalone и FHS, задаваемые при сборке. В SDL2 есть SDL_GetPrefPath(), которая вернет тебе каталог настроек независимо от платформы, его можно использовать для обоих вариантов, и SDL_GetBasePath, которая вернет директорию запуска (там можно держать либы и ассеты).

eagleivg ★★★★★ ()

Все просто, если это кусок со своими зависимостями и только, то кидайте в /opt/TheGameName/ или какие-то игры про которые Вы говорите. В случае с /opt/ FHS соблюдён как и надо. Если есть системные зависимости – то в /usr/local, ну или /home/username/.local/. Steam вообще кладёт всё в /home/.steam/где-то там.

kostyarin_ ()
Ответ на: комментарий от Meyer

Если планируешь публиковать в Steam, придется про FHS забыть.

Я не спец по стиму, но вангую, что там можно создать свои bin, lib и share, чтобы взаимное расположение файлов было такое же, как в FHS

annulen ★★★★★ ()

Если возникает такой вопрос, значит определенности со способом распространения пока нет. Тогда лучше сделай инсталляцию в префикс таким образогм, чтобы если префикс /usr или /usr/local, то все было по FHS. Для инсталляции в /opt или юзерский каталог используется такая же схема, только с другим значением префикса. Внутри кода приложения используй пути относительно главного бинарника (как уже подсказали выше), тогда префикс будет «портабельным»

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

Вот я хочу усесться на все стулья одновременно, что бы можно было сделать и пакет, и просто распаковать с архива, и чтоб по возможности исходный код (тот, который на C++) в этих вариантах не отличался. Вот фаерфокс можно и пакетом поставить, и простым архивом с официального сайта, и причём в нём нет директорий lib, bin. Хотелось бы узнать, как принято это реализовывать.

mirai65536 ()

Складывать всё это в папку игры, как вроде делают сейчас большинство разработчиков игр.

Нет, большинство с разной степенью кривости используют XDG.

anonymous ()

Когда делал свой пакет забивал на все правила. Бинарник в /usr/bin, библиотеки в /usr/lib/appname. Чтобы библиотеки искались создал в /etc/ld.so.conf.d/ свой conf файл и там прописал путь.

Надеюсь меня за это в ад не упекут.

ox55ff ★★ ()

Проприетарщина или СПО? Если первое - делай тяп ляп как бог на душу положит, для уродов это нормально.

А если СПО и/или для людей и/или нормально поддерживающее опакечивание, то так:

бинарник в /usr/local/bin, локали в /usr/local/share/locale, иконки текстурки всякие в /usr/local/share/игра

Да, только надеюсь под /usr/local ты имел в виду ${PREFIX} который задаётся при установке. Да, PREFIX обычно /usr/local по умолчанию.

настройки в ~/.config/игра

Да, если имелось в виду ${XDG_CONFIG_HOME}/игра, где XDG_CONFIG_HOME берётся из окружения, а по умолчанию ~/.config. К слову, save обычно кладут в ${XDG_DATA_HOME}/игра, где XDG_DATA_HOME по умолчаиню ~/.local/share (на винде могут быть другие умолчания).

остальные файлы в /usr/lib/игра

Какие такие остальные файлы? lib, как ни странно место для библиотек или модулей. «Остальные файлы» - в share/игра.

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

Обычно ${PREFIX} вкомпиливается на этапе сборки. Особо умные вместо этого лезут в /proc, берут оттуда путь к бинарнику и от него считают остальные пути, но это мгновенно ломается там где нет никаких /proc впомине. При опакечивании эту дурость обычно выпиливают.

Сделать что-то среднее, что будет работать в обеих случаях, задавая директории в скрипте через переменные окружения.

Ну я лично не вижу лучше способа чем при сборке указывать флаг standalone/systemwide, так можно собрать так штуку которая будет запускаться из текущей директории (причём желательно сделать так чтобы это работало и прямо из репозитория), так и системный пакет.

if(STANDALONE)
    set(BINDIR "." CACHE STRING "Where to install binaries")
    set(DATAROOTDIR "." CACHE STRING "Root directory for data files")
    set(DATADIR "data" CACHE STRING "Where to install data files")  # если в репозитории данные лежат в data, то это позволит запускать игру прямо из чекаута, что удобно
    set(DESKTOPDIR "." CACHE STRING "Where to install .desktop file")
    set(DOCSDIR "." CACHE STRING "Where to install documentation")
else()
    # нынче правильнее было бы заиспользовать GNUInstallDirs
    set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE STRING "Where to install binaries")
    set(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE STRING "Root directory for data files")
    set(DATADIR "${DATAROOTDIR}/${CMAKE_PROJECT_NAME}" CACHE STRING "Where to install data files")
    set(DESKTOPDIR "${DATAROOTDIR}/applications" CACHE STRING "Where to install .desktop file")
    set(DOCSDIR "${DATAROOTDIR}/doc/${CMAKE_PROJECT_NAME}" CACHE STRING "Where to install documentation")
endif()

Понятное дело, путь нужно передать в приложение:

target_compile_definitions(xxx PRIVATE -DDATADIR="${DATADIR}")

Ну и в приложении что-то типа:

    std::string datapath(DATAPATH);  # передано из системы сборки
    std::string confpath;

    char* xdg_config_home = getenv("XDG_CONFIG_HOME");
    if (xdg_config_home != nullptr) {
        confpath = xdg_config_home;
    } else {
#ifdef WIN32
        TCHAR szPath[MAX_PATH];
        if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath)))
            throw std::runtime_error("Windows sux");
        confpath = szPath;
#else
        confpath = getenv("HOME") + "/.config"
#endif
    }
    confpath += "/mygame";
slovazap ★★★★★ ()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от slovazap

Проприетарщина или СПО?

CПО

Обычно ${PREFIX} вкомпиливается на этапе сборки.

Если не вкомпиливать, то можно будет преобразовывать standalone <-> systemwide без пересборки. Не могу определиться, как будет лучше.

mirai65536 ()

Складывать всё это в папку игры, как вроде делают сейчас большинство разработчиков игр

Ну так почему бы и не поступить именно так? Ты что, системное ПО делаешь? Нет, ты делаешь просто игру, как ты вообще додумался вспомнить про FHS для игры???

I-Love-Microsoft ★★★★★ ()

Не привязывайся к FHS, ты не часть OS. Не размазывай свои файлы по дереву директорий. Никто следить чтоб твое место в /etc, /usr/bin, ~/.local и т.д. не оказалось занятым не будет. Сделай чтоб твоя прога работала без мозгоклюйства где ее не положи. Как вариант все пути захардкодить относительно переменной базовой директории, базовый дир. передавать в параметрах командной стороки, если параметра нет, искать в карант директори, если в карант дир. нету искать в дир. где прога лежит. Так интеграторы смогут положить твою прогу где хотят и настрить запуск в .desktop файле.

anonymous ()

Второе - свалка со всеми зависимостями (или вообще snap/AppImage/whatever).
А о варианте с FHS пусть мейнтейнеры конкретных дистров заботятся. Только в коде для данных пропиши сразу пути поиска и там и там.

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

Если не вкомпиливать, то приложение ниоткуда его не узнает и соответственно его придётся всегда указывать руками.

можно будет преобразовывать standalone <-> systemwide без пересборки

А какой в этом смысл? Либо кто-то скачал репозиторий на посмотреть/ковыряет код, либо собирается пакет, не могу представить случай когда нужно сразу оба или из одного другое. Не, ну можно ещё --datadir поддержать, тогда да, можно будет делать что угодно.

slovazap ★★★★★ ()

С точки зрения пользователя размазывание программы тонким слоем по всей ФС крайне неудобное решение.
Нужны конфиги? Где они?
Ресурсы? А они где?
Сохранения? А хрен найдёшь!
Потерял скрипт для uninstall'а? Ну и хрен ты теперь наведёшь порядок.

И всё это ради чего? Плюсы где? А нет их.

ZweiStein ()
Ответ на: комментарий от monk

Вообще, нет. Если посмотришь на сигнатуру execve, увидишь что туда можно написать любую херню, даже никак не связанную с вызываемым бинарником. Это полностью на совести процесса вызывающего exec, а значит можно считать что не работает. На практике мне когда-то встречались шеллы которые пишут туда просто имя бинарника без полного (или относительного от $PWD) пути.

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

На практике мне когда-то встречались шеллы которые пишут туда просто имя бинарника без полного (или относительного от $PWD) пути.

Сообразил. Это даже общепринято. В смысле, argv[0] - имя, по которому программа вызвана. И при непустом PATH скорее всего как раз получишь имя без пути.

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

Да нет, если попробовать то у меня лично везде при вызове через PATH там как раз полный путь.

Странно, а какой shell? У меня bash 5.0. Там из командной строки.

monk ★★★★★ ()