2

我已经创建了一个 C++ 应用程序的 DEB 包。我希望此应用程序使用“数据”目录中的资源,在我的测试中(为方便起见),该目录与程序二进制文件位于同一位置,并且我通过其相对路径从代码内部调用它。在 Debian 操作系统中,有一些标准位置可以放置数据文件(例如 /usr/share/...),还有其他位置可以放置二进制文件(可能是 /usr/bin)。我不想将路径硬编码在我的程序中,我认为通过“data/img.png”访问图像比“/usr/share/.../data/img.png”更好”。所有 GNU 经典程序都尊重目录结构,我想他们做得很好。我尝试使用 dpkg 找出应用程序的结构,但这对我没有帮助。有没有更好的方法

PS:我还希望我的代码可以移植到 Windows(跨平台),尽可能避免使用“if WIN32”之类的变通方法。

4

2 回答 2

1

这并不完全是特定于 linux 或 debian 的。我认为这可能与 Linux Standard Base 或 POSIX 规范有关。我无法足够快地发现任何规范。

但是您不应该为每种类型的数据使用其中的一些“基本”目录和子目录。平台相关的代码应该属于/usr/lib/programname,平台无关的只读数据应该属于/usr/share/programname/img.png。/var/lib/programname/cache.db 中的应用程序更改的数据。或 ~/.programname/cache.db,取决于它是什么类型的应用程序以及它的作用。注意:当 /usr/share 已经存在非可执行数据时,不需要“数据”目录。

如果为 Debian 打包,您可能需要检查http://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html 。但它不是像 android 或 iphone 或 windows 文件中的资源。这些文件在软件包安装时作为真实文件提取到目标文件系统中。

编辑:见http://www.debian.org/doc/packaging-manuals/fhs/fhs-2.3.html

Edit2:至于多平台解决方案,我建议你做一些包装函数。在 Windows 上,它取决于安装程序,通常程序通常在注册表中具有安装它们的目录的路径。在 unix 上,数据的位置或多或少是给定的,您可以考虑更改目标前缀的构建选项,或使用环境变量覆盖默认路径。在 Windows 上,前缀也足够了,如果它不应该太灵活的话。

我建议一些函数,您将在其中传递对象的名称,它们将返回文件的路径。这取决于使用的工具包,Qt 库可能已经实现了类似的东西。

    #include <string>
    #ifdef WIN32
    #define ROOT_PREFIX "c:/Program Files/"
    const char DATA_PREFIX[] = ROOT_PREFIX "program/data";
    #else
    #define ROOT_PREFIX "/usr/"
    /* #define ROOT_PREFIX "/usr/local/" */
    const char DATA_PREFIX[] = ROOT_PREFIX "share/program";
    #endif

    std::string GetImageBasePath()
    {
      return std::string(DATA_PREFIX) + "/images";
    }

    std::string GetImagePath(const std::string &imagename)
    {
      // multiple directories and/or file types could be tried here, depends on how    sophisticated
      // it should be.
      // you may check if such file does exist here for example and return only image type that does exist, if you can load multiple types.
      return GetImageBasePath() + imagename + ".png";
    }

    class Image;
    extern Image * LoadImage(const char *path);

    int main(int argc, char *argv[])
    {
      Image *img1 = LoadImage(GetImagePath("toolbox").c_str());
      Image *img2 = LoadImage(GetImagePath("openfile").c_str());
      return 0;
    }

进行类设置可能是明智的,您可以在其中每次启动一次初始化平台相关的根路径,然后使用 Settings::GetImagePath() 作为方法。

于 2013-03-11T13:51:37.597 回答
1

在您的 Debian 软件包中,您确实应该将数据安装在 /usr/share/ 中。访问您的数据时,您应该使用XDG 标准,该标准指出 $XDG_DATA_DIRS 是以冒号分隔的要搜索的数据目录列表(另外,“如果 $XDG_DATA_DIRS 未设置或为空,则值等于 /usr/local /share/:/usr/share/ 应该被使用。”)。

于 2013-03-11T13:52:58.640 回答