二进制文件的相对路径
Relative paths from binary file
我有以下文件夹结构:
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 文件的相对路径。
我相信您可以使用 getpid 命令找到您的进程 ID (pid),并以类似于 this question 的方式执行提取目录的功能 Ubuntu。
我会让数据以某种方式(有组织地)与可执行文件所在的 bin 目录相关联。
然后,当运行例程时,如果提供了完整路径(通过检查arg[0]注明),则可以找到数据目录。如果提供了相对路径,则依次搜索搜索路径,直到找到可执行文件,然后就可以找到数据目录。
不需要 pid。 (我认为这就是 Python 找到它的方式,或者至少它过去是如何找到它的方式。)
你可能问错了问题:构建系统与程序执行无关。
但是,如果您要寻找答案,如何让我的程序正确使用相对于程序安装定位的数据,那么这里就是答案。
当您的程序 main
被执行时,它会获取二进制路径作为第一个参数(索引 0
)。该路径可以是相对路径或绝对路径,但无论如何它都可以让您找到 base 目录。
这些也是有用的链接:
- How do I find the location of the executable in C?
- Finding current executable's path without /proc/self/exe
在这里你可以如何使用第一个参数:
#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;
}
我一般都是通过程序设置来解决这个问题。在过去的美好时光里,我会将这些设置放在可执行文件附带的 .ini
文件中。一些设置可以在程序中配置,所有设置都可以使用文本编辑器进行编辑。如果文件丢失或任何设置丢失,它们将默认创建。
对于程序数据的位置,我会使用它的完整绝对路径名。例如它可能是
Datapath = D:\os50k
然后程序会根据需要将各个文件名附加到路径中。
这些天在 Windows 系统注册表用于此目的。但是,您的问题被标记为 Linux
,它将设置存储在各个地方,包括程序目录。
This question, and this question 更全面地描述过程。
如果您的路径可以在构建时确定(即您的项目永远不需要安装到另一个目录),您可以通过构建系统将路径作为预处理器定义注入。这是 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";
我有以下文件夹结构:
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 文件的相对路径。
我相信您可以使用 getpid 命令找到您的进程 ID (pid),并以类似于 this question 的方式执行提取目录的功能 Ubuntu。
我会让数据以某种方式(有组织地)与可执行文件所在的 bin 目录相关联。
然后,当运行例程时,如果提供了完整路径(通过检查arg[0]注明),则可以找到数据目录。如果提供了相对路径,则依次搜索搜索路径,直到找到可执行文件,然后就可以找到数据目录。
不需要 pid。 (我认为这就是 Python 找到它的方式,或者至少它过去是如何找到它的方式。)
你可能问错了问题:构建系统与程序执行无关。
但是,如果您要寻找答案,如何让我的程序正确使用相对于程序安装定位的数据,那么这里就是答案。
当您的程序 main
被执行时,它会获取二进制路径作为第一个参数(索引 0
)。该路径可以是相对路径或绝对路径,但无论如何它都可以让您找到 base 目录。
这些也是有用的链接:
- How do I find the location of the executable in C?
- Finding current executable's path without /proc/self/exe
在这里你可以如何使用第一个参数:
#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;
}
我一般都是通过程序设置来解决这个问题。在过去的美好时光里,我会将这些设置放在可执行文件附带的 .ini
文件中。一些设置可以在程序中配置,所有设置都可以使用文本编辑器进行编辑。如果文件丢失或任何设置丢失,它们将默认创建。
对于程序数据的位置,我会使用它的完整绝对路径名。例如它可能是
Datapath = D:\os50k
然后程序会根据需要将各个文件名附加到路径中。
这些天在 Windows 系统注册表用于此目的。但是,您的问题被标记为 Linux
,它将设置存储在各个地方,包括程序目录。
This question, and this question 更全面地描述过程。
如果您的路径可以在构建时确定(即您的项目永远不需要安装到另一个目录),您可以通过构建系统将路径作为预处理器定义注入。这是 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";