Can you pass your code directly into gcc? For example: gcc -? 'int main(){return 0;}'

≡放荡痞女 提交于 2021-01-27 18:54:19

问题


Can you pass your code directly into gcc? If so what is the command line option for it?

For example:

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

I need to know because I am using a system command and I rather not make files:

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

Basile Starynkevitch solution worked, however I am getting compile errors when I use newlines:

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

Edit: fixed it

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

回答1:


You could ask GCC to read from stdin. Read the Invoking GCC chapter of its documentation. Use its -x option with /dev/stdinor with -:

 echo 'int main(){return 0;}' | g++ -x c++ -O -Wall -o myprog /dev/stdin

BTW, since int main(){return 0;} is a valid C program, you could use

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

Programatically, you should consider using popen(3) to get a some FILE* handle for a pipe(7) (so FILE* f = popen("g++ -x c++ -O -Wall -o myprog /dev/stdin", "w"); then check that f is not null) and fprintf into it then pclose it at last. Don't forget to test the status of pclose.

However, most of the time spent by GCC is not parsing (use -ftime-report developer option to find out). You often want to ask it to optimize (with -O2 -march=native or just -O for example), and you surely want to ask for all warnings (with at least -Wall and perhaps also -Wextra).

If you want to produce some plugin code in /tmp/someplugin.so from some emitted C++ code in /tmp/myemitted.cc to be dynamically loaded on Linux, compile it as position-independent code into a shared object dynamic library with e.g.

g++ -o /tmp/someplugin.so -fPIC -shared -Wall -O /tmp/myemitted.cc

etc.... then use dlopen(3) on /tmp/someplugin.so with dlsym(3) to fetch some loaded symbols. My GCC MELT is doing this.

Since parsing time is negligible, you could instead write C or C++ code in some temporary file (inside /tmp/ or /run which is often some fast tmpfs on most Linux systems, so writing into it does not require disk I/O).

At last, recent GCC (use at least GCC 6) also has GCCJIT (actually libgccjit). You could use it to build some representation of generated code then ask GCC to compile it.

See also this and that. Read the C++ dlopen mini howto and the Program Library HowTo, and Drepper's How To Write Shared Libraries

I rather not make files

Generating a temporary file (see mkstemp(3) etc... and you practically could also general some random file name under /tmp/ ending with .c, then register its removal with atexit(3) passed some function doing unlink(2)...) is really quick (but you should build some kind of AST in memory before emitting C++ or C code from it). And using some Makefile to compile the generated code with some make command has the advantage (for the advanced user) to be able to change compilers or options (by editing that Makefile to configure make).

So you are IMHO wrong in avoiding temporary files (notice that gcc & g++ are also generating and deleting temporary files, e.g. containing some assembler code). I would suggest on the contrary generating a temporary file (matching /tmp/mytemp*.cc) using some random numbers (see random(3); don't forget to seed the PRNG with e.g. srandom(time(NULL)); early in your main). It could be as simple as

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

You coded:

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

Beware, + is usually not string catenation. You might use snprintf(3) or asprintf(3) to build strings. Or use in C++ std::string. And if you use system(3) you should check its return code:

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);
}

BTW, your example is wrong (missing <stdio.h>); it is C code, not C++ code. It should be

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

PS. My answer is focused on Linux, but you could adapt it for your OS.



来源:https://stackoverflow.com/questions/38299086/can-you-pass-your-code-directly-into-gcc-for-example-gcc-int-mainreturn

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!