【问题标题】:How to get full path to source file in C?如何在C中获取源文件的完整路径?
【发布时间】:2019-03-12 17:51:13
【问题描述】:

我知道我可以执行以下操作从 C 程序中打印源文件:

printf("__FILE__: %s\n", __FILE__);

但是,根据docs,这会产生“预处理器打开文件的路径”。在这种情况下,它给出:

__FILE__: common.c

我进一步知道我也可以使用以下clang feature 来打印源文件:

void *pc = __builtin_return_address(0);
char pc_desc[1024];
__sanitizer_symbolize_pc(pc, "%p %F %L", pc_desc, sizeof(pc_desc));
printf("__sanitizer_symbolize_pc: %s\n", pc_desc);

同样,它只打印相对路径:

__sanitizer_symbolize_pc: 0x10563a873 in Y common.c:4

当两个文件在不同子目录的同一行上具有相同的静态函数(在本例中为 Y)时,这是一个问题,例如:

__sanitizer_symbolize_pc: 0x10563a873 in Y common.c:4
__sanitizer_symbolize_pc: 0x10563a933 in Y common.c:4

当然可以重构代码,或者程序运行后与源代码匹配二进制,或者编译过程可以更改为从更高的父文件夹编译common.c文件。但是在这个例子中,如何从 C 程序本身获取源文件的完整路径?

clang 的 IR 似乎保留了in metadata 的目录信息,但不清楚它是如何访问的。例如,common.ll 文件包含以下行:

!1 = !DIFile(filename: "common.c", directory: "/full/path/to/subdir")

我在 Mac OS 上使用手动编译的 clang 7.0.1。

【问题讨论】:

  • 如果您使用一个工作目录编译了不同子目录中的所有文件,通常 cmake 会这样做,那么您将避免所描述的短文件名问题。
  • 你希望文件名被预编译器访问,比如__FILE__,还是在运行时得到它可以吗?
  • @NeilEdelman 无论哪种方式都可以。我认为__sanitizer_symbolize_pc 已经是一个运行时调用,尽管我猜测它使用了编译时的调试符号。
  • @NeilEdelman 谢谢!虽然看起来另一个问题是获取可执行文件的名称而不是源文件的名称。

标签: c clang llvm


【解决方案1】:

可以考虑在编译时给它一个完整的路径吗?

如下所示,调用realpath 获取完整路径

SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
CFLAGS = -g -Wall
CC = clang
BIN = test

$(BIN) : $(OBJS)
    $(CC) $^ -o $@

%.o : %.c
    $(CC) $(CFLAGS) -c $(realpath $<)

clean:
    rm -f $(OBJS) $(BIN)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-31
    • 2015-11-03
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    相关资源
    最近更新 更多