我想定义程序使用的外部全局符号(const char*
)。在链接时添加具有给定值的符号。例如,这对于提交哈希或构建时间很有用。
我发现--defsym
还在做其他事情。 Go链接器通过-X
选项支持此功能。 (是的,我知道,Go Strings是托管的,但我所说的是普通的旧的零终止的c字符串)
例如:
extern const char *git_commit;
int main(int argc, char *argv[]) {
puts(git_commit);
return 0;
}
gcc main.o -Wl<something here that adds git_commit and set it to '84e5...'>
我知道config.h
方法和构建包含这些字符串的目标文件。但它的2019年就知道了。这样简单的任务应该很容易。
编辑更精确的问题
gcc / binutils中有与Go Linker的-X
选项等效的选项。
答案 0 :(得分:4)
在编译/预处理时间上有一个变化,请考虑以下问题:
#include <stdio.h>
const char * git_commit = GIT_COMMIT;
int main(int argc, char ** argv) {
puts(git_commit);
return 0;
}
并在命令行中:
gcc -o test test.c -DGIT_COMMIT="\"This is a test\""
假设您使用的是GCC编译器。
答案 1 :(得分:1)
一种方法:
echo "char const* git_commit = \"$(git rev-parse HEAD)\";" > git_commit.c
gcc -c -o git_commit.o git_commit.c
gcc -o main main.o git_commit.o
在makefile文件中实现此功能时,您可能只想在修订版本更改时重新创建git_commit.c
,以便它不会在每次make
调用时重新链接。
答案 2 :(得分:0)
我不知道有任何方法可以使用一个常用的链接程序直接通过一个标志来完成您想要的操作。通常,如果要将此类对象的定义链接到程序中,则必须提供一个包含适当符号定义的对象文件。
最简单的方法可能是调用编译器来编译变量的定义,内容是通过命令行定义的宏来馈送的,就像其他答案中已经建议的那样。如果要避免创建临时源文件,gcc也可以直接从stdin接收输入:
echo "const char git_commit[] = GIT_COMMIT;" | gcc -DGIT_COMMIT=\"asdf\" -c -o git_commit.obj -xc++ -
在您的代码中,只需将其声明为
extern const char git_commit[];
注意:我使用的是const char git_commit[]
而不是const char* git_commit
。这样,git_commit
将直接是一个适当大小的数组,该数组的大小初始化为容纳提交哈希的内容。另一方面,const char* git_commit
将创建一个全局指针对象,该对象将初始化为保存单独的字符串文字对象的地址,这意味着您引入了不必要的间接寻址。并不是说这里真的很重要,但是跳过效率低下并不会花费您任何钱,尽管它可能很小……
还有objcopy
实用程序,可用于将任意二进制内容包装在目标文件中,请参见此处How do I embed the contents of a binary file in an executable on Mac OS X?。甚至可以通过以下方式将输入直接传递给objcopy:以及标准输入。最后,您还可以编写自己的工具,直接编写包含适当符号定义的目标文件。但是,请考虑一下,最终,您正在寻求生成一个可以与构成程序的其他目标文件链接的目标文件。简单地使用与编译其余代码相同的编译器,可能是实现此目的最可靠的方法。使用其他解决方案,您将始终必须手动确保目标文件在目标体系结构,内存布局等方面都是兼容的。
答案 3 :(得分:0)
您可以将其嵌入为资源文件,例如:
GitInfoHTML HTML "GitInfo.html"
这将由链接器(在链接时间时)放入可执行文件中,然后可以加载。
有关更多信息,请参见: https://docs.microsoft.com/en-us/cpp/windows/resource-files-visual-studio?view=vs-2019