【问题标题】:Linux/Makefile: Creating a binary that executes as if it were in a specific directoryLinux/Makefile:创建一个像在特定目录中一样执行的二进制文件
【发布时间】:2015-04-17 08:45:35
【问题描述】:

我有以下文件夹结构:

include/
src/
data/
binary-file
makefile

我会像这样执行二进制文件:./binary-file

但现在我希望我的二进制文件在它自己的文件夹中,如下所示:

bin/ <- binary-file is in here now
include/
src/
data/
makefile

当我从主文件夹执行它时一切正常:bin/binary-file

但是如果我在主文件夹以外的另一个文件夹中,程序将表现不佳,并且无法找到#include 的路径。例如,如果我在 bin/ 文件夹中,如果我像这样执行它,程序将表现不佳:./binary-file

我的问题是:如何让我的 makefile 或二进制文件像在主文件夹中一样从系统上的任何位置执行?

在我的 makefile 中,我所做的只是:

$(CC) $(CFLAGS) -I$(IDIR) -I$(BDIR) -I$(DDIR) -o $(PROG) $^ $(LFLAGS)

$(CC) $(CFLAGS) -I$(IDIR) -I$(BDIR) -I$(DDIR) -o $(BDIR)/$(PROG) $^ $(LFLAGS)

【问题讨论】:

  • 您的 makefile/编译与此无关。您的二进制文件需要能够通过绝对路径或通过其已知目录结构中的相对路径找到其数据文件。
  • @EtanReisner 这是否意味着我必须将所有#include "file.h" 更改为 #include "../file.h"?
  • 编译器使用这些路径而不是您的二进制文件。不,那些-I 参数应该没问题,假设IDIR 是你的include 目录的路径。
  • 一旦你的程序被编译成可执行文件,包含文件(你用#include file.h包含的那些是完全没有意义的。我强烈怀疑你在混淆事情。你是混淆了编译结果的执行还是执行make 来构建最终产品?
  • @thurizas 我的 DDIR 中有一些我的二进制文件使用的数据(“data/xml/file.xml”)。当我从主文件夹执行二进制文件时:/bin/binary-file,一切正常。但是当我从 /bin/ 文件夹执行二进制文件:./binary-file 时,它​​无法加载“data/xml/file.xml”。

标签: c linux makefile


【解决方案1】:

好的,基于你最近的通讯

@thurizas 我的 DDIR 中有一些我的二进制文件使用的数据(“data/xml/file.xml”)。当我从主文件夹执行二进制文件时:/bin/binary-file,一切正常。但是当我从 /bin/ 文件夹执行二进制文件:./binary-file 时,它​​无法加载“data/xml/file.xml”

  1. 硬编码数据文件的绝对路径(比如 /home/brandonto/projects/data/xml/file.xml .... 假设是 *nix 类型的文件系统)。显然,优点是无论您的可执行文件位于何处,它都可以找到数据文件。不利的一面是,如果您移动二进制文件,它将停止工作。

  2. 添加命令行选项来设置数据路径。例如,假设您选择应用程序数据文件的默认位置为/usr/share/brandonto/myapp/data,您可以将其硬编码到应用程序中。现在允许用户使用命令行参数来调整文件的位置。如果给出命令行参数,您的逻辑将是使用它,否则使用默认位置。好处是您可以从任何地方执行,用户可以根据个人喜好移动内容,并且如果需要,您可以拥有两组数据文件(例如一组用于测试,一组用于生产)。不利的一面是,您的程序变得有点复杂,如果用户确实将数据文件移动到某个不寻常的地方,那么每次他启动应用程序时都必须输入更多内容。比如;

    ./myapp   -- would use the default location for the data files
    ./myapp -f <somepath> -- would use the files in <somepath> over ridding the default
    

还有一些其他选项,例如配置文件(这让我们回到了与您最初的问题非常相似的内容:))

【讨论】:

    【解决方案2】:

    您的数据文件名必须是"../data/xml/file.xml"

    "../" 是一个相对路径,意思是“返回一个文件夹”。 "../../etc" 意味着返回两个文件夹。

    【讨论】:

    • 我试图使路径相对,但无济于事。当前目录会根据您从何处执行文件而更改: bin/SpaceShooter argc = 1 argv[0] = bin/SpaceShooter dirname(argv[0]) = bin 和 ./SpaceShooter argc = 1 argv[0] = 。 /SpaceShooter 目录名(argv[0]) = .
    • 所以,您更改了问题,可执行文件现在位于其他位置。您的路径必须是相对的、绝对的或在预定义的默认路径上,尽管这通常适用于可执行文件,而不是数据。
    • 不,二进制文件仍在 bin/ 文件夹中。但是现在执行二进制文件时我不在 bin/ 文件夹中。我最初的问题是如何制作它,以便您可以从系统上的任何位置执行二进制文件,无论您在输入 pwd 时位于哪个目录。
    • 如果您想提交答案,这里有一个更清晰的问题:stackoverflow.com/questions/28549606/…
    【解决方案3】:

    您可能问了一个错误的问题:构建系统与程序执行无关。

    但是,如果您寻找答案,如何使我的程序正确使用与程序安装相关的数据,而不是这里的答案。

    当你程序main被执行时,它获取二进制路径作为第一个参数(索引0)。该路径可以是相对的或绝对的,但无论如何它都允许您找到 base 目录。

    这些也是有用的链接:

    这里如何使用第一个参数:

    #include <linux/limits.h>
    #include <stdio.h>
    #include <string.h>
    #include <libgen.h>
    
    int main(int argc, char *argv[])
    {
      char datadir[PATH_MAX];
      strncpy(datadir, argv[0], sizeof(datadir));
      dirname(datadir);
      strncat(datadir, "/../data", sizeof(datadir));
    
      printf("Data dir: %s\n", datadir);
    
      return 0;
    }
    

    该程序假定以下部署:

    ROOT <- Can be anywhere on file system
    +--bin
    |  +--- <- application is here...
    +--data
       +--- <- Data files are located here...
    

    【讨论】:

    • 我试图使路径相对,但无济于事。 argv[0] 会根据您执行文件的位置而有所不同: bin/SpaceShooter argc = 1 argv[0] = bin/SpaceShooter dirname(argv[0]) = bin 和 ./SpaceShooter argc = 1 argv[0] = ./SpaceShooter 目录名(argv[0]) = .
    • 如果您想提交答案,这里有一个更清晰的问题:stackoverflow.com/questions/28549606/…
    猜你喜欢
    • 1970-01-01
    • 2012-06-17
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 2021-05-02
    • 1970-01-01
    • 2021-09-09
    相关资源
    最近更新 更多