你能直接将你的代码传递给gcc吗?例如:gcc -? 'int main(){return 0;}'。

3

您能直接将代码传递给gcc吗?如果可以,它的命令行选项是什么?

例如:

g++ -? 'int main(){return 0;}'

我需要知道,因为我正在使用系统命令,而我不想生成文件:
system("g++ -C "+code_string+" -o run.out");

Basile Starynkevitch的解决方案可行,但是当我使用换行符时,我遇到了编译错误:

echo '#include\nint main(){printf("Hello World"); return 0;}' | g++ -x c++ -Wall -o myprog /dev/stdin

编辑:已修复

echo -e '#include\nint main(){printf("Hello World"); return 0;}' | g++ -x c++ -Wall -o myprog /dev/stdin

在哪个操作系统和哪个版本的GCC上? - Basile Starynkevitch
为什么你在问呢?是什么动机驱使你这样做呢?如果我知道的话,我可以改进我的回答。所以请您编辑您的问题 - Basile Starynkevitch
我正在使用gcc 4.8.4和ubuntu 14.04。我想要能够在程序中编译代码,但我不想检查未使用的文件名,创建文件,运行命令,然后删除文件。 - ClemsonCoder
创建临时文件非常容易。稍后删除它也很容易(例如使用 atexit(3) ...)。 - Basile Starynkevitch
顺便提一下,请避免在评论中提出问题。请编辑您的问题以改进它(例如为将来参考)。 - Basile Starynkevitch
我仍然非常好奇你的实际动机是什么。你是要生成一些随机的独立程序,还是想生成一些调用你程序内部函数的插件代码? - Basile Starynkevitch
1个回答

5
你可以要求GCC从标准输入读取。阅读其文档中的调用GCC章节。使用其-x选项/dev/stdin-
 echo 'int main(){return 0;}' | g++ -x c++ -O -Wall -o myprog /dev/stdin

顺便说一下,因为int main(){return 0;}是一个有效的C程序,所以你可以使用它。

 echo 'int main(){return 0;}' | gcc -x c -O -Wall -o myprog -

程序上,你应该考虑使用 popen(3) 来获取一个用于 pipe(7)FILE* 句柄(所以FILE* f = popen("g++ -x c++ -O -Wall -o myprog /dev/stdin", "w"); 然后检查 f 不是空),并将内容写入其中,最后使用 pclose 关闭。别忘了测试 pclose 的状态。
然而,GCC 花费的大部分时间并非 解析(使用 -ftime-report 开发者选项 可以查看)。通常您需要要求它进行 优化(例如使用 -O2 -march=native 或仅使用 -O),并且肯定需要要求所有 警告(至少使用 -Wall,也可以使用 -Wextra)。
如果你想要从发射的C++代码/tmp/myemitted.cc中生成一些插件代码/tmp/someplugin.so,以便在Linux上动态加载它,那么请将其编译为位置无关代码,并将其编译为共享对象动态库。例如:
g++ -o /tmp/someplugin.so -fPIC -shared -Wall -O /tmp/myemitted.cc

等等,然后在/tmp/someplugin.so上使用dlopen(3),再用dlsym(3)获取一些已加载符号。我的GCC MELT正在执行此操作。

由于解析时间可以忽略不计,因此您可以在某个临时文件中编写C或C++代码(位于/tmp//run内,这在大多数Linux系统上通常是一些快速的tmpfs,因此写入它不需要磁盘I/O)。

最后,最近的GCC(至少使用GCC 6)还具有GCCJIT(实际上是libgccjit)。您可以使用它构建一些生成代码的表示,然后请求GCC进行编译。

请参阅thisthat。阅读C++ dlopen mini howtoProgram Library HowTo,以及Drepper的How To Write Shared Libraries

我不想创建文件

生成临时文件(参见mkstemp(3)等),你几乎也可以在/tmp/下生成一些以.c结尾的随机文件名,然后在其上注册一个函数使用atexit(3)执行unlink(2)...这样做非常快速(但在从中发出C++或C代码之前,应在内存中构建某种AST)。使用一些Makefile通过一些make命令编译生成的代码具有优势(对于高级用户)可更改编译器或选项(通过编辑该Makefile来配置make)。

据我看来,你在避免使用临时文件方面是错误的(请注意,gccg++也会生成和删除临时文件,例如包含一些汇编代码的文件)。相反,我建议生成一个临时文件(匹配/tmp/mytemp*.cc),并使用一些随机数(参见random(3);不要忘记在main中早期使用例如srandom(time(NULL));种子PRNG)。它可以非常简单。

char tmpbuf[80];
bool unique;
do { // in practice, this loop is extremely likely to run once
  snprintf(tmpbuf, sizeof(tmpbuf), "/tmp/mytemp_%lx_p%d.cc", 
           random(), (int)getpid());
  unique = access(tmpbuf, F_OK);
} while (unique);
// here tmpbuf contains a unique temporary file name

你编写了以下代码:

system("g++ -C "+code_string+" -o run.out");

注意,+通常不是字符串连接符。你可以使用snprintf(3)asprintf(3)构建字符串。或者在C++中使用std::string。如果你使用system(3)函数,你应该检查它的返回代码:
char cmdbuf[128];
snprintf(cmdbuf, sizeof(cmdbuf), "g++ -Wall -O %s -o run.out", tmpbuf);
fflush(NULL);
if (system(cmdbuf) != 0) {
   fprintf(stderr, "compilation %s failed\n", cmdbuf);
   exit(EXIT_FAILURE);
}

顺便提一下,你的示例有误(缺少<stdio.h>),这是C代码,而不是C++代码。应该是:

echo -e '#include <stdio.h>\nint main(){printf("Hello World"); return 0;}' \
     |  gcc -x c -Wall -O -o myprog -

PS. 我的回答是针对 Linux 的,但你可以根据你的操作系统进行调整。


完全偏题,但-mcpu已弃用。请使用-mtune或(最好)-march - Tim
除了换行符之外,它可以工作,我已经更新了我的帖子。 echo '#include\nint main(){printf("Hello World"); return 0;}' | g++ -x c++ -Wall -o myprog /dev/stdin - ClemsonCoder
2
你也可以使用“-”代替“/dev/stdin”(对于没有该设备的系统非常有用):echo ... | gcc -x c <options> - - Keith Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接