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

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

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.

Related

How can I use gcc to compile C program whose name does not end with ".c"?

Compiling C program using gcc is very simple. Just such a command:
gcc code.c -o executable
However, if the code file name does not end with ".c", gcc will treat it as a linker script. How can I use gcc to compile C program whose name does not end with ".c"?
Use -x switch to specify the language.
gcc -xc -o executable anything
You can even read from stdin:
echo 'int main() { printf("Hello world"); }' | gcc -xc -o executable -
With GCC, the -x switch specifies the language to compile for:
gcc -x c code.foo -o executable

Changing OCaml's gcc after installation

I installed OCaml via OPAM, and by default it uses gcc as the command to compile .c files. For instance, if I run ocamlopt -verbose file.c, I obtain:
+ gcc -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT -g
-fno-omit-frame-pointer -c -I'/home/user/.opam/4.02.1+fp/lib/ocaml' 'test.c'
I'd like to change the GCC binary that is used by OCaml, for instance to replace it with gcc-5.1 or /opt/my-gcc/bin/gcc.
Is it possible to do so without reconfiguring and recompiling OCaml? I suppose I could add a gcc alias to a directory in the PATH, but I'd prefer a cleaner solution if there is one.
To check if gcc was not chosen based on a textual configuration file (that I could easily change), I searched for occurrences of gcc in my /home/user/.opam/4.02.1+fp directory, but the only occurrence in a non-binary file that I found was in lib/ocaml/Makefile.config, and changing it does nothing for the already-compiled binary.
ocamlopt uses gcc for three things. First, for compiling .c files that appear on the command line of ocamlopt. Second, for assembling the .s files that it generates internally when compiling an OCaml source file. Third, for linking the object files together at the end.
For the first and third, you can supply a different compiler with the -cc flag.
For the second, you need to rebuild the OCaml compiler.
Update
Here's what I see on OS X when compiling a C and an OCaml module with the -verbose flag:
$ ocamlopt -verbose -cc gcc -o m m.ml c.c 2>&1 | grep -v warning
+ clang -arch x86_64 -c -o 'm.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlasm461f1b.s' \
+ gcc -c -I'/usr/local/lib/ocaml' 'c.c'
+ clang -arch x86_64 -c -o \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartupb6b001.s'
+ gcc -o 'm' '-L/usr/local/lib/ocaml' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/usr/local/lib/ocaml/std_exit.o' 'm.o' \
'/usr/local/lib/ocaml/stdlib.a' 'c.o' \
'/usr/local/lib/ocaml/libasmrun.a'
So, the compiler given by the -cc option is used to do the compilation of the .c file and the final linking. To change the handling of the .s files you need to rebuild the compiler. I'm going to update my answer above.

windows equivalent of command substitution in makefiles

I want to display current build(hg revision) number in the about box of my program. I thought about using a "define" (std::string rev = REVISION;) in the code and pass the value to g++ via makefile:
$(CPP) -c main.cpp -o main.o -DREVISION=`hg id -i`
would work like a charm, but im developing on windows for windows, so my Q: how to create such a behavior on windows.
If you're using g++ then your assumption is mostly right, excepting that passing a macro definition is done using -D option, not -d. Also, $(CPP) in Make usually refers to C PreProcessor. C++ compiler is $(CXX).
$(CXX) -c main.cpp -o main.o -DREVISION=`hg id -i`
Regarding command substitution, it should work fine if you run your build in UNIX-ish compatibility layer, like Cygwin or MinGW. If not, you could avoid using command substitution at all, and pass the result of hg id -i to the compiler literally, e.g. as follows:
REVISION := $(shell hg id -i)
...
$(CXX) -c main.cpp -o main.o -DREVISION=$(REVISION)

How can I tell, with something like objdump, if an object file has been built with -fPIC?

How can I tell, with something like objdump, if an object file has been built with -fPIC?
The answer depends on the platform. On most platforms, if output from
readelf --relocs foo.o | egrep '(GOT|PLT|JU?MP_SLOT)'
is empty, then either foo.o was not compiled with -fPIC, or foo.o doesn't contain any code where -fPIC matters.
I just had to do this on a PowerPC target to find which shared object (.so) was being built without -fPIC. What I did was run readelf -d libMyLib1.so and look for TEXTREL. If you see TEXTREL, one or more source files that make up your .so were not built with -fPIC. You can substitute readelf with elfdump if necessary.
E.g.,
[user#host lib]$ readelf -d libMyLib1.so | grep TEXT # Bad, not -fPIC
0x00000016 (TEXTREL)
[user#host lib]$ readelf -d libMyLib2.so | grep TEXT # Good, -fPIC
[user#host lib]$
And to help people searching for solutions, the error I was getting when I ran my executable was this:
root#target:/# ./program: error while loading shared libraries: /usr/lib/libMyLi
b1.so: R_PPC_REL24 relocation at 0x0fc5987c for symbol 'memcpy' out of range
I don't know whether this info applies to all architectures.
Source: blogs.oracle.com/rie
I assume, what you really want to know is whether or not a shared library is composed from object files compiled with -fPIC.
As already mentioned, if there are TEXTRELs, then -fPIC was not used.
There is a great tool called scanelf which can show you the symbols that caused .text relocations.
More information can be found at HOWTO Locate and Fix .text Relocations TEXTRELs.
-fPIC means that code will be able to execute in addresses different form the address that was compile for.
To do it , disasambler will look like this....
call get_offset_from_compilation_address
get_offset_from_compilation_address: pop ax
sub ax, ax , &get_offset_from_compilation_address
now in ax we have an offset that we need to add to any access to memory.
load bx, [ax + var_address}
readelf -a *.so | grep Flags
Flags: 0x50001007, noreorder, pic, cpic, o32, mips32
This should work most of the time.
Another option to distinguish whether your program is generated wit -fPIC option:
provided that your code has -g3 -gdwarf-2 option enabled when compiling.
other gcc debug format may also contains the macro info:
Note the following $'..' syntax is assumes bash
echo $' main() { printf("%d\\n", \n#ifdef __PIC__\n__PIC__\n#else\n0\n#endif\n); }' | gcc -fPIC -g3
-gdwarf-2 -o test -x c -
readelf --debug-dump=macro ./test | grep __PIC__
such a method works because gcc manual declares that if -fpic is used, PIC is defined to 1, and
if -fPIC used, PIC is 2.
The above answers by checking the GOT is the better way. Because the prerequest of -g3 -gdwarf-2 I guess seldom being used.
From The Linux Programming Interface:
On Linux/x86-32, it is possible to create a shared library using
modules compiled without the –fPIC option. However, doing so loses
some of the benefits of shared libraries, since pages of program text
containing position-dependent memory references are not shared across
processes. On some architectures, it is impossible to build shared
libraries without the –fPIC option.
In order to determine whether an existing object file has been
compiled with the –fPIC option, we can check for the presence of the
name _GLOBAL_OFFSET_TABLE_ in the object file’s symbol table, using
either of the following commands:
$ nm mod1.o | grep _GLOBAL_OFFSET_TABLE_
$ readelf -s mod1.o | grep _GLOBAL_OFFSET_TABLE_
Conversely, if either of the following equivalent commands yields any
output, then the specified shared library includes at least one object
module that was not compiled with –fPIC:
$ objdump --all-headers libfoo.so | grep TEXTREL
$ readelf -d libfoo.so | grep TEXTREL
However, neither above quoting nor any answer of this question works for x86_64.
What I've observed on my x86_64 Ubuntu machine is that, whether specifying -fPIC or not, it would generate fPIC .o. That is
gcc -g -Wall -c -o my_so.o my_so.c // has _GLOBAL_OFFSET_TABLE_
gcc -g -Wall -fPIC -c -o my_so_fpic.o my_so.c // has _GLOBAL_OFFSET_TABLE_
readelf -s my_so.o > 1.txt && readelf -s my_so_fpic > 2.txt && diff 1.txt 2.txt
has no difference and both my_so.o and my_so_fpic.o can be used to create a shared library.
In order to generate non fpic object file, I found a gcc flag called -fno-pic in the first comment of How to test whether a Linux binary was compiled as position independent code? .
This works,
gcc -g —Wall -fno-pic -c -o my_so_fnopic.o my_so.c // no _GLOBAL_OFFSET_TABLE_
and
gcc -g -Wall -shared -o libdemo.so my_so_fnopic.o
gives error:
/usr/bin/ld: my_so_fnopic.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
collect2: error: ld returned 1 exit status
can not create a shared library with non pic .o.

gcc link error occurred

I compiled with gcc
gcc -l. 'net-snmp-config --cflags'
-fPlC -shared -c -o matsu_object.o tsu_object.c
but this error occurred
gcc: -lcrypto: Because a link was
not completed, the input file of the
linker was not used
What's wrong?
Did you mistype the question? There's no way for that to output the message you write, and I would expect that the proper command is something more like
gcc -L. `net-snmp-config --cflags` -fPIC -shared -c -o matsu_object.o tsu_object.c
Notice the -L uppercase, backticks instead of single quotes, and upper-case I in PIC.
Also, you don't say what you're trying to do, but net-snmp-config should also take at least one of --libs or --agent-libs as well.
Ah, I didn't read closely enough...
-c means "compile", that is: generate from tsu_object.c, a compiled matsu_object.o.
Without -c, the compiler actually links, that is: generate from *.o, a.out or other specified file.
-shared (and linker flags like -l and -L) are only meaningful when linking. They're meaningless when compiling, as you are doing here because of -c.
Please correct the command-line in the question to accurately reflect what you're running, and give some more explanation as to what you're trying to do.
I think you are using ticks ' instead of back ticks `. Does --cflags really give linker options? I think you are at the link step here. Also what is the effect of -c at a link. I thought -c was compile only and not attempt to link.
You used single quotes instead of backquotes.
Instead of this:
gcc -l. 'net-snmp-config --cflags' -fPlC -shared -c -o matsu_object.o tsu_object.c
You should type:
gcc -l. `net-snmp-config --cflags`-fPlC -shared -c -o matsu_object.o tsu_object.c
net-snmp-config is a program. When you run it with --cflags, it evaluates to the correct cflags that you should be using to compile your program.
But you know what? You should be using autoconf. Even for something this small, it usually makes sense to do the work. Most people I know need to compile on more than one platform...

Resources