编译C ++ - 没有文件的代码

时间:2013-07-17 14:46:45

标签: c++ compilation g++

我正在尝试使用您的标准g ++编译器编译一些C ++代码。 但是,而不是从文件编译:

main.cpp中:

#include <iostream>

int main(){
    std::cout << "Hello World!\n";
    return 0;
}

我更喜欢做

之类的事情
g++ ... "#include <iostream>\n int main(){ std::cout << \"Hello World!\n\"; return 0;}"

stackoverflow的前一个post显示

echo "int main(){}" | gcc -Wall -o testbinary -xc++ -

有效,但我想知道它是如何工作的,如果有办法做到这一点,而不需要管道内容。

编辑:

我正在进行运行时代码生成,我需要生成一个共享库并加载创建的函数。

我以为会有一个标志告诉编译器“嘿,我给你的是源代码而不是文件”。

再次感谢您的帮助!

6 个答案:

答案 0 :(得分:4)

  

echo“int main(){}”| gcc -Wall -o testbinary -xc ++ -

     

有效,但我想知道它是如何工作的,如果有办法做到这一点,而不需要管道内容。

或者你可以说(例如在shell脚本中):

gcc -Wall -o testbinary -xc++ - << EOF
int main(){}
EOF

答案 1 :(得分:2)

编译器从输入源读取 - stdin或提供的文件。你需要一个管道来从别处向编译器提供一些东西。没有其他选择(当然,有些编译器可能没有选择从stdin读取)

答案 2 :(得分:2)

你提到动态生成C(或C ++)代码,然后编译它并dlopen - 它。

我在MELT(扩展GCC的特定领域语言)中也这样做。

我没有看到任何有效的理由避免将代码放入某个(临时)文件中。编写甚至一百万行生成的C或C ++行非常快(在MELT中,不到几秒钟,大部分时间不是I / O!)。编译速度要慢得多(至少几十秒),并且生成C或C ++代码的兴趣尤其在于利用GCC(或其他一些编译器)提供的优化。避免生成文件只会赢得你几毫秒(你甚至无法显着衡量差异)。

所以只需在一些临时*.c文件中生成你的文件(你可以使用哈希或时间戳技术生成一个唯一的文件名),然后让GCC将它编译成一些*.so(可能是{{} 1}} - 一些fork进程,就像我在MELT中那样),然后删除该临时文件(可能使用make)。

BTW,这种技术实际上与当前PC上的人机交互兼容。 MELT有一个read-eval-print-loop,在每次交互上生成几百行的新C ++文件,编译和dlopen-s,它非常实用!

避免文件的生成是痛苦的,并且收益绝对可以忽略不计。您可以在Linux上的某些atexit文件系统中生成它(例如在tmpfs中)。大部分时间都是由GCC编译该文件所花费的(特别是如果你使用一些优化进行编译,例如/tmp/)。将它写在磁盘上(由您的程序)并通过GCC读取它(甚至为C解析)的时间可以忽略不计。使用GCC的-ftime-report选项来了解GCC花费时间的地方,一旦您将gcc -O -fPIC -shared somefile.c -o someplugin.so传递给GCC,就不会解析。

某些版本的GCC或其他C编译器可能拒绝 stdin 作为输入;某些C编译器可能希望-O C源文件(例如,使用mmap作为Glibc上"rm"的模式)。通常,将不是fopen文件的内容编译为 C 是非标准的等等......所以最好避免这样做,因为增益可以忽略不计。 < / p>

如果您根本不关心优化并希望将C(而不是C ++)快速编译成非常慢的机器代码,请考虑使用 tinycc (至少在32位机器上使用,64它可能是错误的,它有一个能够在字符串中编译一些C代码的库。 *.c及其tcc能够非常快速地编译(超过10倍GCC)一些C代码,但生成的机器代码的性能非常差(非常慢,未经优化的代码)。

一旦GCC编译了您生成的C代码,您当然可以libtcc.a生成的源代码文件。 (您甚至可以在remove编辑后删除.so

顺便说一下,您可以使用dlopen来编译生成的C ++文件。您可以使用LLVM(并生成内部LLVM表示,而不使用任何文件)。

另见this answer

答案 3 :(得分:1)

如何popen("gcc -o -xc++ -“,”w“); ? Gives you a FILE *`但输出直接进入GCC。

顺便说一下,使用-Wall标志毫无意义。这是供人类消费的。事实上,-w -Wfatal-errors是有道理的。无论是编译还是不编译。

答案 4 :(得分:0)

在Unix上,您可以使用shell自动化创建C / C ++程序的所有过程。

1.创建文件(例如run_c.sh)

2.将代码粘贴到此文件

#!/bin/bash

# Generate random filename
RANDOM_FILENAME=`cat /dev/urandom | tr -dc 'A-Za-z0-9' | fold -w 20 | head -n 1`
RANDOM_FILENAME=_$RANDOM_FILENAME
readonly RANDOM_FILENAME

# random filename for a C file
RANDOM_FILENAME_C=$RANDOM_FILENAME.c
readonly RANDOM_FILENAME

# catch stdin as code
CODE=$1

# names headers of the C standart language
declare -a C_STANDART_LIBRARY=('stdio' 'errno' 'assert' 'math' 'stdarg' 'stdbool' 'stdlib' 'string' 'time')

# create the C file
touch $RANDOM_FILENAME_C

# write a first line to the file
printf '// Compile C code from stdin\n\n' >> $RANDOM_FILENAME_C

# make include all headers to the file
for header in "${C_STANDART_LIBRARY[@]}"
do
    printf '#include <%s.h>\n' $header >> $RANDOM_FILENAME_C
done

# make include all headers to the file
printf "\nint main(int argc, char *argv[]) {\n" >> $RANDOM_FILENAME_C

# split the code from stdin by ';' to an array lines
IFS=';' read -r -a LINES_CODE <<< "$CODE"

# write line by line the code
for line in "${LINES_CODE[@]}"
do
    printf '%s;\n' "$line" | sed -e 's/^[[:space:]]//' | sed -e 's/^/\t/' >> $RANDOM_FILENAME_C
done

# write ending the function 'main'
printf "\treturn 0;\n}\n" >> $RANDOM_FILENAME_C

# uncomment for display the C code
# cat $RANDOM_FILENAME_C

# compile the file
gcc -Wall -std=c11 -o $RANDOM_FILENAME $RANDOM_FILENAME_C

# run programm if no errors
if [ -f "$RANDOM_FILENAME" ];
    then
    ./$RANDOM_FILENAME
fi

# rm the file with source code
rm $RANDOM_FILENAME_C
# rm the compliled file

if [ -f "$RANDOM_FILENAME" ];
    then
        rm $RANDOM_FILENAME
fi

3.将此文件设为可执行文件

$ chmod +x run_c.sh 
$ ls -l | grep run_c.sh 
-rwxr-xr-x 1 setivolkylany setivolkylany 1589 Dec 26 11:19 run_c.sh

<强>用法:

$ ./run_c.sh 'int a = 4; int b = 6; int c = a + b; printf("%d + %d = %d\n", a, b, c)'
4 + 6 = 10

$ ./run_c.sh 'puts("Worked");'
Worked

测试环境

$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 8.6 (jessie)
Release:    8.6
Codename:   jessie
$ uname -a
Linux localhost 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux

灵感来自http://django-notes.blogspot.com/2013/01/compiling-c-from-stdin.htmlhttps://github.com/vgvassilev/cling

答案 5 :(得分:0)

-x 用于指定您将编译的语言。

这是一个例子:

gcc -x c - <<eof
#include <stdio.h>

void foo()
{
    int a = 10;
    static int sa = 10;

    a += 5;
    sa += 5;

    printf("a = %d, sa = %d\n", a, sa);
}


int main()
{
    int i;

    for (i = 0; i < 10; ++i)
        foo();
}
eof