我有以下文件夹结构:
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文件的相对路径。
答案 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 question和this 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";