I need to find out the available (installed in the system) GCC version (Major and minor) inside the execution of a c program (in runtime). Meaning, programatically extract the version of the available gcc (same as if I was in a shell and typed gcc --version, but in a c program).
The __GNUC__ and __GNUC_MINOR__ are only useful in compile time and I've found the gnu_get_libc_version() function from gnu/libc_version.h, but it only gets me the libc version and I need the GCC version. If there is something similar for GCC it would be great...
I would really like to avoid calling a shell command to do this.
There is a simple way:
$ gcc -dumpversion
4.6
Invoke the gcc shell command with the parameter --version; it's the correct way to do this. See popen() to do that.
Or you can invoke GCC with to compile a program which prints the values for __GNUC__ and __GNUC_MINOR__. But that will not work if the GCC in question is configured for cross compilaton.
Alternatives would be to search the binary for version strings and hoping that you get the right one, that the format doesn't change and that the version string is distinct enough for you to recognize it with enough confidence.
In 1.5 words: Don't.
I need to find out the available (installed in the system) GCC version (Major and minor)
What are you going to do with the information?
You can't get a meaningful answer to your question, because
The user may not have any GCC installed in /usr/bin
May have 5 different versions installed elsewhere on the system
May have a version in /usr/bin which pretentds to be gcc-X.Y, but is actually gcc-Z.W, or Clang, or icc, etc.
But if you insist on getting a meaningless answer, popen("gcc --version") and parse the resulting output.
Related
How a C compiler like GCC defines the preprocessor macro to detect the current OS?
I looked into GCC's source code and found this builtin_define ("_WIN32"); but I'm not sure if this is where the macros are defined.
TL;DR: Basically, yes. The built-in macros are defined in a target description header file.
There is so often a Fine Manual To Read; in this case, it's the GCC internals manual. (Specifically, in the section on Run-time target specification, but don't start reading there; you'll need some context.)
There is a complete compendium of GCC documentation in case you need more information. (The internals documents are at the bottom of that page.)
(If you're comfortable using the GNU info reader and you're using a Ubuntu/Debian system, you can install the GCC documentation for your current GCC version with sudo apt-get install gcc-doc; that includes the GCC internals documentation.)
The carefully crafted, self-including code in this IOCCC winning entry from 1988:
http://www.ioccc.org/years.html#1988_isaak
...was still too much for certain systems back then. Also, ANSI C was finally emerging as a stable alternative to the chaotic K&R ecosystem. As a result, the IOCCC judges also provided an ANSI version of this entry:
http://www.ioccc.org/1988/isaak.ansi.c
Its main attraction is its gimmick of including <stdio.h> in the last line (!) with well-thought-out #defines, both inside the source and at compile time, to only allow certain parts of the code into the right level. This is what allows the <stdio.h> header to be ultimately included at the latest stage possible, just before it is necessary, in the source fed to the compiler.
However, this version still fails to produce its output when compiled today, with the provided compiler settings:
gcc -std=c89 -DI=B -DO=- -Dy isaak.ansi.c
tcc -DI=B -DO=- -Dy isaak.ansi.c
Versions used: GCC 9.3.0, TCC 0.9.27
There isn't any evident reliance on the compiled binary filename, hence I left it to the compiler's choice. Even when using -o isaak or -o isaak.ansi, the same result happens: no output.
What is causing this? How are the output functions failing? What can be done to correct this?
Thanks in advance!
NOTE: The IOCCC judges, realising that this entry had portability issues that would detract from its obfuscation value, decided to also include a UUENCODEd version of the code's output:
http://www.ioccc.org/1988/isaak.encode
There is nothing remotely portable about this program. As I see it tries to overwrite the exit standard library function with its own code, expecting that return from empty main() would call that exit(), which is not true. And even then, such behaviour is not standard-conforming - even C89 said it would have undefined behaviour.
You can "fix" the program on modern GCC / Linux by actually calling exit(); inside main - just change the first line to
main(){exit(0);}
I compiled gcc -std=c89 -DI=B -DO=- -Dy isaak.ansi.c and run ./a.out and got sensible output out.
Code as below:
int main (int argc, char *argv[]) {
long pid = (long)getpid();
long test = pid + 1;
}
Have not included any head files, still can compile code successfully and still can run program successfully.
Why?
Environment info: Ubuntu 18.04.2 LTS, gcc (Ubuntu 4.8.5-4ubuntu8) 4.8.5
Have not included any head files,still can compile code successfully.
still can run program successfuly.Why?
Why not?
All question of whether the particular code presented conforms to the language standard notwithstanding, language non-conformance does not imply that compilation or execution must fail. Instead, you get undefined behavior, which can manifest in any manner within the power of the machine to produce, including compiling successfully and running as intended.
In your particular case, however, you are using GCC 4.8.5. The GCC 4.8 series defaults to compiling for the C90 standard, with GNU extensions. C90 allows calls to functions with no in-scope declaration, for compatibility with earlier, pre-standardization practice. That is no longer allowed in C99 or later, but many implementations nevertheless continue to accept it as an extension.
It should be understood, however, that C interprets some argument lists differently when the called function has an in-scope prototype than when it doesn't (which may be the case even for functions that are declared, because not all declarations provide prototypes). You may be able to get away with calling undeclared functions under some circumstances, but it is poor style, and if you do it enough then it will bite you at some point.
Note also that GCC 4 definitely has the ability to emit warnings about usage such as yours, even when compiling in C90 or GNU90 mode. You would be well served to turn on the -Wall option when you compile, and maybe additional warning options as well.
Normally, to use a dynamic library function you would have to link against the specified library at compile time through the -l switch, like for example gcc -lm prog.c when using the mathematic functions (from libm).
However, since it's so common, GCC always links the standard C library by default, meaning that doing gcc prog.c is actually the same as doing gcc -lc prog.c. This is always done whether you include any header or not.
The second thing that makes this work, is that GCC assumes any function that has not been declared at compile time to have the signature int func(void). In this case, the signature is quite similar to the one of the real getpid() function.
If you take a look at your compiled program with the ldd tool to show which dynamic libraries are required, you'll see that the program is linked against libc:
$ ldd prog
linux-vdso.so.1 (0x00007ffede7d0000)
==> libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0f47018000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0f475b9000)
When your program runs, it asks the dynamic loader where (at which address) to find the getpid function before calling it the first time. The dynamic loaders checks the loaded libraries, and finds a function with that name in libc, so everything seems to work without a problem.
You can tell GCC to not link against the standard library by default using the -nostdlib compiler switch, but this is not that useful in your case. The real solution is to always treat warnings about implicit function declarations as errors (-Werror=implicit-function-declaration).
If your compiler doesn't give this warning by default, I would suggest you to upgrade it to a newer version. GCC 4 is definitely not the latest version available for Ubuntu 18.
$ sudo apt update
$ sudo apt upgrade
It seems that getopt behaves differently in Windows than in Linux. Windows requires a strict ordering of parameters while in Linux I can put the arguments in any order. Consider a program test which uses getopt compiled for Linux (gcc) and Windows (MinGW) and take this command line for example:
test file1.bin file2.bin -o output.txt
Executing this command in Linux would correctly parse -o output.txt as an option(+parameter) regardless of where I put -o output.txt. It could be between file1.bin and file2.bin as well and getopt parsing would still work correctly since it sorts the arguments by putting the optional ones infront of the mandatories.
Executing this command in Windows however results in incorrect parsing, giving me a wrong index in optind variable. It seems that the exact same code when compiled in Windows does not do the sorting part for me. Why is this, can we workaround this?
Transferring my comments to an answer as requested.
GNU getopt() permutes the arguments (so options can occur after non-option arguments) by default. Standard POSIX getopt() does not allow that. You can make GNU getopt() conform to POSIX by exporting the environment variable POSIXLY_CORRECT=1, or by starting the options argument with a + symbol.
Check the manual (or source) for MinGW getopt(), or the Microsoft implementation of it. Given what you see, it probably doesn't do the permutation. However, the linked source code does support permutation — you'll need to investigate what goes on there.
If you decide to use GNU getopt(), you'll need to get a copy of the GNU getopt() source code (maybe from GitHub getopt.c) and include it in your build process. If you use that, you'll also need ansidecl.h and getopt.h at minimum and you will need to tweak the configuration appropriately.
Or you'll have to decide that the GNU extension of permuting options isn't portable and therefore shouldn't be used at all.
I am using ubuntu through windows linux bash and it happens that I am trying to compile a file and I am getting this error:
"error: ‘for’ loop initial declarations are only allowed in C99 mode".
But actually I would like not to use C99 mode but use C11 instead. How can I set my compiler to use C11 mode by default without having to pass any flags?
My GCC version is 4.8.4 running at ubuntu 14.04.3.
Thanks.
You need to specify -std=c99 or -std=gnu99 or higher to allow initial declarations in for loops. Or, just declare the variable first and use it in the for loop later.
For c11 of course, -std=c11 is the way. I don't know of a way of setting this default and perhaps there is no way. But recent gcc compilers 5.x have c11 default.
Alternative to re-building GCC yourself (complicated and error prone), update GCC (newer GCCs may not be able to compile the kernel, The kernel-developers and the GCC-developers go not always, how shall I put it ... d'accord) and typing -std=c11 every time, you can set an alias. Put the following line at the end of your .bashrc
alias gcc11="gcc -std=c11"
Let the shell re-read it's config file by source ~/.bashrc (If I remember Ubuntu correctly) and try it out.
You can call the alias gcc, too, but that might break 3rd-party makefiles.