【问题标题】:Accessing resources from program in Debian package structure从 Debian 包结构中的程序访问资源
【发布时间】:2013-03-11 12:59:58
【问题描述】:

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

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

【问题讨论】:

    标签: c++ linux debian deb


    【解决方案1】:

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

    【讨论】:

    • 我发现这非常有用,但我想为 Windows 编译相同的代码,而不使用任何类型的“if windows”。我忘了在我的问题中提到这一点。
    【解决方案2】:

    这并不完全是特定于 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() 作为方法。

    【讨论】:

    • 谢谢!我会检查链接。我编辑了我的问题,我忘了提到我希望为 Windows 编译相同的代码,而不使用任何类型的“如果 Windows”。
    • 我看到了你发布的链接,它们详细解释了如何在 Debian 中打包,将每种文件放在哪里,但我认为他们假设你只会为 Linux 编译你的程序,或者您正在处理代码内部的路径。
    猜你喜欢
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多