二进制文件的相对路径

时间:2015-02-16 20:16:22

标签: c linux executable

我有以下文件夹结构:

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

在我的代码中,我使用相对路径来访问我的数据。所以“../data/xml/xmlFile.xml”。如果我从bin /文件夹执行二进制文件,这很好:

brandonto@computer:~/PATH-TO-PROJECT/bin$ ./binary-file 
argv[0] = ./binary-file
dirname(argv[0]) = .

但是,如果我从主文件夹(或任何其他不是bin /文件夹的文件夹)执行二进制文件:

brandonto@computer:~/PATH-TO-PROJECT$ bin/binary-file 
argv[0] = bin/binary-file
dirname(argv[0]) = bin

找不到xml文件,因为“../data”现在会从主文件夹(或执行程序时的任何文件夹)上升到一个目录。

我怎样才能使二进制文件可以从我系统上的任何目录执行?

使问题更清晰:

brandonto@brandonto-Aspire-S3-391:~/cpp-workspace/sdl-projects/sdl-space-shooter/bin$ ~/cpp-workspace/sdl-projects/sdl-space-shooter/bin/SpaceShooter 
argv[0] = /home/brandonto/cpp-workspace/sdl-projects/sdl-space-shooter/bin/SpaceShooter
dirname(argv[0]) = /home/brandonto/cpp-workspace/sdl-projects/sdl-space-shooter/bin

brandonto@brandonto-Aspire-S3-391:~/cpp-workspace/sdl-projects/sdl-space-shooter/bin$ cd ..
brandonto@brandonto-Aspire-S3-391:~/cpp-workspace/sdl-projects/sdl-space-shooter$ ~/cpp-workspace/sdl-projects/sdl-space-shooter/bin/SpaceShooter 
argv[0] = /home/brandonto/cpp-workspace/sdl-projects/sdl-space-shooter/bin/SpaceShooter
dirname(argv[0]) = /home/brandonto/cpp-workspace/sdl-projects/sdl-space-shooter/bin
Unable to load image ../data/graphics/background/darkPurple.png! SDL_image Error: Couldn't open ../data/graphics/background/darkPurple.png
Unable to load image ../data/graphics/sprites/meteorBrown_big1.png! SDL_image Error: Couldn't open ../data/graphics/sprites/meteorBrown_big1.png

在这里,我从bin /文件夹中执行了一次二进制文件,然后从主文件夹中执行了一次。二进制文件在bin /文件夹内运行正常,但无法从主文件夹中找到.png文件的相对路径。

5 个答案:

答案 0 :(得分:2)

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

但是,如果你寻找答案,如何使我的程序正确使用数据,这是相对于程序安装而言,这是一个答案。

当你编写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;
}

答案 1 :(得分:0)

我相信您可以使用getpid命令找到您的进程ID(pid),并执行函数以在Ask Ubuntu上以类似于this question的方式提取目录。

答案 2 :(得分:0)

我会以某种方式(组织上)将数据与可执行文件所在的bin目录相关联。

然后,在运行例程时,如果提供了完整路径(通过检查arg [0]注明),则可以找到数据目录。如果提供了相对路径,则按顺序搜索搜索路径,直到找到可执行文件,然后您就可以找到数据目录。

不需要pids。 (我认为这就是Python找到它的方式,或者至少它是如何使用它的。)

答案 3 :(得分:0)

我通常用程序设置来解决这个问题。在过去的好时光中,我将这些设置放在.ini文件中,该文件将随可执行文件一起提供。某些设置可以在程序中进行配置,所有设置都可以使用文本编辑器进行编辑。如果文件丢失或缺少任何设置,则默认情况下会创建它们。

对于程序数据的位置,我会使用其完整的绝对路径名。例如,它可能是

Datapath = D:\os50k

然后程序会根据需要将单个文件名附加到路径中。

目前,在Windows中,系统注册表用于此目的。但是,您的问题标记为Linux,它将设置存储在各个位置,包括程序目录。

This questionthis question更全面地描述了这个过程。

答案 4 :(得分:0)

如果可以在构建时确定路径(即,您的项目将永远不需要安装到另一个目录),则可以通过构建系统注入路径作为预处理器定义。这是CMake的示例:

file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/resources" RESOURCE_DIR) # Normalize Windows/Linux paths
add_custom_command(
    TARGET my_target POST_BUILD
    COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/resources ${RESOURCE_DIR}
)
target_compile_definitions(my_target PUBLIC RESOURCE_DIR=${RESOURCE_DIR})

#define VAL(x) #x
#define STR(x) VAL(x)
const char* my_resource = STR(RESOURCE_DIR) "/my_resource.abc";