gnatmake -o flag produces incorrect object file name - gcc

I am attempting to compile a .adb file with gnatmake, and the -o flag isn't producing the object file name I want:
$ gnatmake --GCC=g++ -D bin/src/ghdl_grt/ -f -u -c src/ghdl_grt/grt-vstrings_io.adb -o bin/src/ghdl_grt/grt-vstrings_io.adb.o
g++ -c -Isrc/ghdl_grt/ -I- -o /home/jon/controlix-code/bin/src/ghdl_grt/grt-vstrings_io.o src/ghdl_grt/grt-vstrings_io.adb
As you can see, it gets the path correct, but the filename should end with .adb.o and it only ends with .o. Any ideas?

For gnatmake, -o 'chooses an alternate executable name'. But even using gcc (or g++) on its own fails, at any rate on macOS, because gnat1: incorrect object file name.
I found that you can compile to assembler and then compile that. Using a local file I happened to have lying about,
$ g++ -D $PWD -c gator2.adb -S -o gator2.adb.s
$ g++ -D $PWD -c gator2.adb.s

Well, that's a weird naming scheme, but...
gnatmake only allows you to specify alternate executable names with -o:
-o name Choose an alternate executable name
You can, however, tell gnatmake to pass on options to the compiler:
-cargs opts opts are passed to the compiler
And similarly, to the binder and linker:
-bargs opts opts are passed to the binder
-largs opts opts are passed to the linker
Thus,
$ gnatmake --GCC=g++ -D bin/src/ghdl_grt/ -f -u -c src/ghdl_grt/grt-vstrings_io.adb -cargs -o bin/src/ghdl_grt/grt-vstrings_io.adb.o

Related

How to compile a test snippet nicely with gnu make?

I don't have a configure stage in my baseline (for various reasons), but I need to check whether my C compiler can support the -mavx2 flag or not.
If I have an empty file, call it test.cc then I can do something like:
$(CC) -mavx2 -c test.cc -o test.o
And check the return status code. Obviously I don't want to leave those test.* files lying around though, but can't think of a good way to generate/test/delete them outside of a recipe. Does anyone know of a good pattern to do this?
Or, you could just take input from stdin, and output to /dev/null:
SUPPORTS_MAVX2:=$(shell echo 'void main(){}' | \
gcc -x c -maxv3 -o /dev/null - 2>/dev/null; \
echo $$?)
Then there are no artifact files to be deleted. The -x c is necessary to tell gcc what language it is (as it can't determine that from the filename in this case), and you need the trailing - as well.
Turns out you can use "eval" to remove the temporary file and return the status code, so this works:
AVX2 = $(shell touch test.cc; $(CC) -mavx2 -c test.cc -o /dev/null >& /dev/null; eval "rm -f test.cc; echo $$?")
Edit and without the temporary file (assuming a sane system):
AVX2 = $(shell $(CC) -mavx2 -c /usr/include/stdlib.h -o /dev/null >& /dev/null; echo $?)

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

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.

Redirecting input separated with spaces

Hi I've a question about feeding inputs to this simple bash script I wrote. All it does is add a set of flags to my compile operation to save me having to write them in myself every time. I can run it by using echo myprogram.c -o myprogram -llibrary | ./Compile.
But I can't find a way to run it in the way I expected to be able to, ./Compile < myprogram.c -o myprogram -llibrary
I've tried a few combinations of quotes and brackets to no avail, can anyone tell me how to feed the same input as produced by echo using the redirect input command.
#!/bin/bash
# File name Compile
#Shortcut to compile with all the required flags, name defaulting to
#first input ending in .c
echo "Enter inputs: "
read inputs
gcc -Wall -W -pedantic -std=c89 -g -O $inputs
exit 0
Just change your shell to:
#!/bin/bash
gcc -Wall -W -pedantic -std=c89 -g -O "$#"
Then you can only write(no redirection needed):
./Compile myprogram.c -o myprogram -llibrary
BTW, don't explicitly write exit 0 at end of this shell. It is redundant when gcc succeeds, and is wrong when gcc fails(exit code 1 will be overwritten).
You can use process substitution:
./Compile < <( echo myprogram.c -o myprogram -llibrary )
the above line produces the same result as your original command:
echo myprogram.c -o myprogram -llibrary | ./Compile

How do I link with gcc on MinWG

Is this syntax incorrect?
C:\Users\Brett\Compilers>gcc -I MinGW\include -l MinGW\lib\libgdi32.a -o hello
world helloworld.c
The directory's are all fine, I mist be including and linking in the wrong order or something?
Here is the output:
c:/users/Brett/compilers/mingw/bin/../lib/gcc/mingw32/4.6.2/../../../../mingw
2/bin/ld.exe: cannot find -lMinGW\lib\libgdi32.a
collect2: ld returned 1 exit status
The syntax for -l switch is the library name without lib prefix and without the extension. If it cannot be found, it's directory should be given with -L option. So I would write:
gcc -I MinGW\include -L MinGW\lib -lgdi32 -o helloworld helloworld.c
Maybe -L is not needed, maybe you also need -mwindows to tell the linker you want windows app. To specify a library file explicitly, give it without any letter option, like this:
gcc -I MinGW\include MinGW\lib\libgdi32.a -o helloworld helloworld.c
Here is the gcc reference: linking options.

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)

Resources