Hello folks,
I am helping a newcomer for packaging and he is packaging a game called stepmania : https://git.sr.ht/~xdbob/rpm-packages/tree/master/item/stepmania/stepmania.spec
This game installs itself in /usr/games and requires that the binary be in the same directory of its data.
Is this conform with Fedora Guidelines? AFAIK /usr/games is part of FHS, but I didn't find info regarding the location of the binary files.
The only doc I've found was from an old page from the Games SIG: https://fedoraproject.org/wiki/SIGs/Games/Packaging
Thanks for your feedback.
I'm not sure even with following FHS guidance for games we can have game data in /usr/games.
/usr/games
Can the game be patched to support traditional FHS load paths? For Lugaru, for example, there's a SYSTEM_INSTALL option that sets a build-time define to embed the correct data directory in the executable.
SYSTEM_INSTALL
You can see how it works here: https://gitlab.com/osslugaru/lugaru/-/blob/7f71daa62e89dae1567e999ea34586a6b4d74ead/CMakeLists.txt?ref_type=heads#L311-327
We could install in %{_datadir}/%{name} but the binary should then be in %{_datadir}/%{name}. If it is in %{_bindir}, it fails to load assets:
stepmania ////////////////////////////////////////////////////// Exception: Couldn't find 'Songs' ////////////////////////////////////////////////////// Error: Couldn't find 'Songs'
Fixing it involve lots of patching, not sure if it will be fully functioning:
From 42efa3378f473209fb084428c78ff01baab2da0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert-Andr=C3=A9=20Mauchin?= <zebob.m@gmail.com> Date: Sat, 14 Oct 2023 22:52:15 +0200 Subject: [PATCH] Split data, libraries and binary and try to respect the FHS on Linux --- src/CMakeLists.txt | 30 ++++++++++++++---- src/RageFileManager.cpp | 11 +++++-- src/RageFileManager.h | 6 ++-- src/arch/ArchHooks/ArchHooks.h | 4 +-- src/arch/ArchHooks/ArchHooks_MacOSX.mm | 10 +++--- src/arch/ArchHooks/ArchHooks_Unix.cpp | 32 ++++++++++---------- src/arch/ArchHooks/ArchHooks_Unix.h | 6 ++-- src/arch/LoadingWindow/LoadingWindow_Gtk.cpp | 2 +- src/config.in.h | 4 +++ 9 files changed, 68 insertions(+), 37 deletions(-) create mode 100644 src/config.in.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index feea706abd..866b9d7765 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,9 @@ endif() set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) # Main project is below. +if(UNIX OR LINUX) +include(GNUInstallDirs) +endif() include(CMakeData-arch.cmake) include(CMakeData-rage.cmake) @@ -514,6 +517,7 @@ else() # Unix / Linux endif() target_link_libraries("${SM_EXE_NAME}" ${SMDATA_LINK_LIB}) +target_include_directories("${SM_EXE_NAME}" PRIVATE ${CMAKE_BINARY_DIR}) list(APPEND SM_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} @@ -600,12 +604,26 @@ endif() target_include_directories("${SM_EXE_NAME}" PUBLIC ${SM_INCLUDE_DIRS}) -if(WIN32) - set(SM_INSTALL_DESTINATION ".") -else() - set(SM_INSTALL_DESTINATION "stepmania-5.0") +if (NOT DEFINED SM_INSTALL_DESTINATION) + if(WIN32) + set(SM_INSTALL_DESTINATION "." CACHE PATH "Installation directory") + elseif(APPLE) + set(SM_INSTALL_DESTINATION "stepmania-5.0" CACHE PATH "Installation directory") + else() + set(SM_INSTALL_DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/stepmania" CACHE PATH "Installation directory") + endif() endif() +if (NOT DEFINED SM_LIBDIR_DESTINATION) + if(UNIX OR LINUX) + set(SM_LIBDIR_DESTINATION "${CMAKE_INSTALL_LIBDIR}/stepmania" CACHE PATH "Libraries directory") + else() + set(SM_LIBDIR_DESTINATION "${SM_INSTALL_DESTINATION}" CACHE PATH "Libraries directory") + endif() +endif() + +configure_file(config.in.h "${CMAKE_BINARY_DIR}/config.h" @ONLY) + if(NOT APPLE) if(WIN32) set(SM_FULL_INSTALLATION_PATH_LIST "${SM_INSTALL_DESTINATION}" "Program") @@ -626,10 +644,10 @@ if(NOT APPLE) # install(FILES "${SM_WINDOW_DLL}" DESTINATION "${SM_INSTALL_DESTINATION}") # endforeach() else() - install(TARGETS "${SM_EXE_NAME}" DESTINATION "${SM_INSTALL_DESTINATION}") + install(TARGETS "${SM_EXE_NAME}" DESTINATION "${CMAKE_INSTALL_BINDIR}") endif() if (UNIX OR LINUX) - install(FILES "${SM_ROOT_DIR}/GtkModule.so" LIBRARY DESTINATION "${SM_INSTALL_DESTINATION}" OPTIONAL) + install(FILES "${SM_ROOT_DIR}/GtkModule.so" LIBRARY DESTINATION "${SM_LIBDIR_DESTINATION}" OPTIONAL) endif() install(DIRECTORY "${SM_ROOT_DIR}/Announcers" DESTINATION "${SM_INSTALL_DESTINATION}") install(DIRECTORY "${SM_ROOT_DIR}/BGAnimations" DESTINATION "${SM_INSTALL_DESTINATION}") diff --git a/src/RageFileManager.cpp b/src/RageFileManager.cpp index 84e175e415..fb09df5e88 100644 --- a/src/RageFileManager.cpp +++ b/src/RageFileManager.cpp @@ -1,3 +1,4 @@ +#include "config.h" #include "global.h" #include "RageFileManager.h" #include "RageFileDriver.h" @@ -25,6 +26,8 @@ static RageEvent *g_Mutex; RString RageFileManagerUtil::sInitialWorkingDirectory; RString RageFileManagerUtil::sDirOfExecutable; +RString RageFileManagerUtil::sDirOfData; +RString RageFileManagerUtil::sDirOfLibraries; struct LoadedDriver { @@ -279,6 +282,8 @@ static void ChangeToDirOfExecutable( const RString &argv0 ) { RageFileManagerUtil::sInitialWorkingDirectory = GetCwd(); RageFileManagerUtil::sDirOfExecutable = GetDirOfExecutable( argv0 ); + RageFileManagerUtil::sDirOfData = SM_INSTALL_DESTINATION; + RageFileManagerUtil::sDirOfLibraries = SM_LIBDIR_DESTINATION; /* Set the CWD. Any effects of this is platform-specific; most files are read and * written through RageFile. See also RageFileManager::RageFileManager. */ @@ -328,12 +335,12 @@ RageFileManager::RageFileManager( const RString &argv0 ) void RageFileManager::MountInitialFilesystems() { - HOOKS->MountInitialFilesystems( RageFileManagerUtil::sDirOfExecutable ); + HOOKS->MountInitialFilesystems( RageFileManagerUtil::sDirOfData ); } void RageFileManager::MountUserFilesystems() { - HOOKS->MountUserFilesystems( RageFileManagerUtil::sDirOfExecutable ); + HOOKS->MountUserFilesystems( RageFileManagerUtil::sDirOfData ); } RageFileManager::~RageFileManager() diff --git a/src/RageFileManager.h b/src/RageFileManager.h index c6ef53520c..3d5d25e21c 100644 --- a/src/RageFileManager.h +++ b/src/RageFileManager.h @@ -5,6 +5,8 @@ namespace RageFileManagerUtil { extern RString sInitialWorkingDirectory; extern RString sDirOfExecutable; + extern RString sDirOfData; + extern RString sDirOfLibraries; } class RageFileDriver; diff --git a/src/arch/ArchHooks/ArchHooks.h b/src/arch/ArchHooks/ArchHooks.h index d1b6d5fcac..dd1de85271 100644 --- a/src/arch/ArchHooks/ArchHooks.h +++ b/src/arch/ArchHooks/ArchHooks.h @@ -89,12 +89,12 @@ public: /* * Add file search paths, higher priority first. */ - static void MountInitialFilesystems( const RString &sDirOfExecutable ); + static void MountInitialFilesystems( const RString &sDirOfData ); /* * Add file search paths for user-writable directories. */ - static void MountUserFilesystems( const RString &sDirOfExecutable ); + static void MountUserFilesystems( const RString &sDirOfData ); /* * Platform-specific code calls this to indicate focus changes. diff --git a/src/arch/ArchHooks/ArchHooks_MacOSX.mm b/src/arch/ArchHooks/ArchHooks_MacOSX.mm index d434b622f1..a9ffd1e180 100644 --- a/src/arch/ArchHooks/ArchHooks_MacOSX.mm +++ b/src/arch/ArchHooks/ArchHooks_MacOSX.mm @@ -307,26 +307,26 @@ static void PathForFolderType( char dir[PATH_MAX], OSType folderType ) FAIL_M( "FSRefMakePath() failed." ); } -void ArchHooks::MountInitialFilesystems( const RString &sDirOfExecutable ) +void ArchHooks::MountInitialFilesystems( const RString &sDirOfData ) { char dir[PATH_MAX]; CFURLRef dataUrl = CFBundleCopyResourceURL( CFBundleGetMainBundle(), CFSTR("StepMania"), CFSTR("smzip"), NULL ); - FILEMAN->Mount( "dir", sDirOfExecutable, "/" ); + FILEMAN->Mount( "dir", sDirOfData, "/" ); if( dataUrl ) { CFStringRef dataPath = CFURLCopyFileSystemPath( dataUrl, kCFURLPOSIXPathStyle ); CFStringGetCString( dataPath, dir, PATH_MAX, kCFStringEncodingUTF8 ); - if( strncmp(sDirOfExecutable, dir, sDirOfExecutable.length()) == 0 ) - FILEMAN->Mount( "zip", dir + sDirOfExecutable.length(), "/" ); + if( strncmp(sDirOfData, dir, sDirOfData.length()) == 0 ) + FILEMAN->Mount( "zip", dir + sDirOfData.length(), "/" ); CFRelease( dataPath ); CFRelease( dataUrl ); } } -void ArchHooks::MountUserFilesystems( const RString &sDirOfExecutable ) +void ArchHooks::MountUserFilesystems( const RString &sDirOfData ) { char dir[PATH_MAX]; diff --git a/src/arch/ArchHooks/ArchHooks_Unix.cpp b/src/arch/ArchHooks/ArchHooks_Unix.cpp index d70ec997b7..85841caad8 100644 --- a/src/arch/ArchHooks/ArchHooks_Unix.cpp +++ b/src/arch/ArchHooks/ArchHooks_Unix.cpp @@ -368,7 +368,7 @@ RString ArchHooks_Unix::GetClipboard() #include <sys/stat.h> static LocalizedString COULDNT_FIND_SONGS( "ArchHooks_Unix", "Couldn't find 'Songs'" ); -void ArchHooks::MountInitialFilesystems( const RString &sDirOfExecutable ) +void ArchHooks::MountInitialFilesystems( const RString &sDirOfData ) { #if defined(UNIX) /* Mount the root filesystem, so we can read files in /proc, /etc, and so on. @@ -382,10 +382,10 @@ void ArchHooks::MountInitialFilesystems( const RString &sDirOfExecutable ) RString Root; struct stat st; - if( !stat(sDirOfExecutable + "/Packages", &st) && st.st_mode&S_IFDIR ) - Root = sDirOfExecutable; - else if( !stat(sDirOfExecutable + "/Songs", &st) && st.st_mode&S_IFDIR ) - Root = sDirOfExecutable; + if( !stat(sDirOfData + "/Packages", &st) && st.st_mode&S_IFDIR ) + Root = sDirOfData; + else if( !stat(sDirOfData + "/Songs", &st) && st.st_mode&S_IFDIR ) + Root = sDirOfData; else if( !stat(RageFileManagerUtil::sInitialWorkingDirectory + "/Songs", &st) && st.st_mode&S_IFDIR ) Root = RageFileManagerUtil::sInitialWorkingDirectory; else @@ -394,7 +394,7 @@ void ArchHooks::MountInitialFilesystems( const RString &sDirOfExecutable ) FILEMAN->Mount( "dir", Root, "/" ); } -void ArchHooks::MountUserFilesystems( const RString &sDirOfExecutable ) +void ArchHooks::MountUserFilesystems( const RString &sDirOfData ) { /* Path to write general mutable user data when not Portable * Lowercase the PRODUCT_ID; dotfiles and directories are almost always lowercase. diff --git a/src/arch/ArchHooks/ArchHooks_Unix.h b/src/arch/ArchHooks/ArchHooks_Unix.h index fc1962f874..47b2baf4eb 100644 --- a/src/arch/ArchHooks/ArchHooks_Unix.h +++ b/src/arch/ArchHooks/ArchHooks_Unix.h @@ -12,7 +12,7 @@ public: void SetTime( tm newtime ); int64_t GetMicrosecondsSinceStart(); - void MountInitialFilesystems( const RString &sDirOfExecutable ); + void MountInitialFilesystems( const RString &sDirOfData ); float GetDisplayAspectRatio() { return 4.0f/3; } bool GoToURL( RString sUrl ); diff --git a/src/arch/LoadingWindow/LoadingWindow_Gtk.cpp b/src/arch/LoadingWindow/LoadingWindow_Gtk.cpp index 1931ef007d..5c0a6eac72 100644 --- a/src/arch/LoadingWindow/LoadingWindow_Gtk.cpp +++ b/src/arch/LoadingWindow/LoadingWindow_Gtk.cpp @@ -29,7 +29,7 @@ RString LoadingWindow_Gtk::Init() { ASSERT( Handle == NULL ); - Handle = dlopen( RageFileManagerUtil::sDirOfExecutable + "/" + "GtkModule.so", RTLD_NOW ); + Handle = dlopen( RageFileManagerUtil::sDirOfLibraries + "/" + "GtkModule.so", RTLD_NOW ); if( Handle == NULL ) return ssprintf( "dlopen(): %s", dlerror() ); diff --git a/src/config.in.h b/src/config.in.h new file mode 100644 index 0000000000..5201dc3843 --- /dev/null +++ b/src/config.in.h @@ -0,0 +1,4 @@ +#pragma once + +#define SM_INSTALL_DESTINATION "@CMAKE_INSTALL_PREFIX@/@SM_INSTALL_DESTINATION@" +#define SM_LIBDIR_DESTINATION "@CMAKE_INSTALL_PREFIX@/@SM_LIBDIR_DESTINATION@" -- 2.41.0
Log in to comment on this ticket.