In the sake of automatically-detecting native GCC installation from within a program, I would like to get the current path to gcc.exe or its root folder.
But when I type gcc -print-prog-name=gcc it simply prints back gcc which is obviously not what I was expecting.
How do I use gcc or other components supposedly installed on the system alongside gcc to retrieve the path to the gcc installation or executable?
For Linux at least, the "native GCC installation" might reasonably be
interpreted as the GCC installation that is invoked through /usr/bin/gcc.
But on that interpretation, there can be no doubt about its installation
path.
Whenever you invoke gcc, if such a program is found at all, it is
simply the first program called gcc that that is found in one of the
directories listed in the value of environment variable PATH, in the
environment of the invocation. True on Linux and other Unix-like OSes.
True on Windows.
Imagine that gcc had an option --whereami that made it print its installation
path on the standard output. The answer you will get will be the answer
given by the first installation of gcc that is found in the operative PATH at
the time of invocation. There might be any number of GCC installations on
a system each of which will yield a different answer for gcc --whereami whenever
that installation is the first to be discovered in the operative PATH.
Selection of different GCC installations via different PATH settings is
commonplace on Windows, where the notion of "the native installation of GCC"
has no meaning. But it is applicable on Linux too and sometimes used. The point is: no
matter what command you run to find out where gcc is installed, any
answer you get is in principle dependent on the operative PATH -
unless you run the command with an absolute filename:
/usr/bin/gcc --whereami
which of course amounts to deciding the answer before you ask the question.
The only cross-platform method by which you can discover the directory from
which gcc will be run, if at all, by a command gcc ..., is to get the
operative PATH (programmatically, use getenv),
parse out the the directories it contains left to right and for successive
directories query the filesystem for the existence of an executable gcc
within it, stopping when you find one.
And since this can only give an answer for the operative PATH,
and since the value of PATH needs parsed differently on Windows and
Unix-like OSes, you might just as well invoke the OS-specific utility that does the same
thing.
Unix-like:
$ which gcc
/usr/bin/gcc
Windows:
C:\>where gcc
C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev0\mingw64\bin\gcc.exe
And note that in the Windows case, I needed to select my mingw-w64 terminal environment to get an answer.
To execute commands and get their output programmatically, see How can I run an external program from C and parse its output?. On Windows, call _popen
instead of popen.
Related
First, I want to check all the c++ compilers I have installed on my mac.
I most probably have Clang and GCC both. So now I want to delete GCC.
please tell me how to do these 2 things.
You probably have clang pretending to be gcc (type gcc --version to check). But there's no clear definition of "installed" on Mac. You can place a compiler anywhere and run it from there (and I often have). But you can look in each part of your PATH (echo $PATH), and see what is in each directory. Or you can just use which clang and which gcc to see what would be picked up by default. You could even try locate gcc to find copies in some less usual locations that won't be run by default like versioned copies in homebrew (the first time you run this, it will tell you how to start the locate service).
But I expect that you really only have one compiler installed (clang). That's the normal situation. It just has hardlinks to gcc for backward compatibility.
This question already has an answer here:
GCC unable to compile Go Program
(1 answer)
Closed 5 years ago.
I'm attempting to use a library at github.com/hajimehoshi/ebiten. Regardless of what I do, I'm met with this error:
# github.com/go-gl/glfw/v3.2/glfw
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
# github.com/go-gl/gl/v2.1/gl
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
I've attempted updating MinGW
mingw-get udpate
I've set the PATH variable for MinGW.
I've downloaded MinGW-w64 here.
I've gone here and downloaded the tdm-gcc 64 bundle.
And still, I'm met with the same error. How do I circumvent this?
Read the cgo manual,
notice there how the go tool calls the compilers for the foreign
languages it supports.
Run
go env
and see at the variables CC and CXX it'll show you:
that are the C and C++ compilers the go toolchain would call to compile
C and C++ code, respectively.
I bet it will show "bare" names such as gcc and g++, respectively.
Notice that when a program on Windows is being run without specifying
its full pathname (that is, beginning with a drive letter and
followed by that :\ fun construct and then the rest of the path—
ending in the actual program file's name), the program's file is looked
up in a set of paths defined by the contents of the so-called
environment variable called "PATH".
That PATH env. variable can be system-wide and per-user;
the latter trumps the former.
In a shell, run
echo %PATH%
and see whether there are listed any pathnames of the installed
C/C++ compilers.
I bet there will be a path of some 32-bit GCC but not your 64-bit suite.
Make sure your PATH env. variable contains an entry for the directory
containing the executable program of your 64-bit compiler whose name matches
the appropriate name listed in the go env output.
Please refer to the installation manual of your compiler for more details.
If all else fails, please ask a concrete question about installing that compiler over there at the https://superuser.com.
I want to use frama-c for static C code analysis. It already took me some effort to install it (hopefully) properly. The files are located at C:\CodeAnalysis\frama-c. I want to apply it via Windows console, e.g.:
C:\CodeAnalysis\frama-c\bin\frama-c hello.c
hello.c is just a simple hello-world-program (I am no C programmer btw and a newbie in programming)
#include <stdio.h>
main()
{
printf("Hello World \n");
}
So when running the above command there is the following output:
[kernel] preprocessing with "gcc -C -E -I. hello.c"
C:/Strawberry/c/x86_64-w64-mingw32/include/stdio.h:141:[kernel] user error: syntax error
[kernel] user error: skipping file "hello.c" that has errors.
[kernel] Frama-C aborted: invalid user input
Yes, I have Perl installed but have no idea why Frama uses it. To me it seems that there is somehow something wrong with the stdio.h. Can this be? But I can compile my program successfully.
C:\Strawberry\c\bin\gcc hello.c produces a nicely working exe file.
When removing the include statement from the file, there is the following output:
[kernel] preprocessing with "gcc -C -E I. hello.c"
hello.c:5:[kernel] warning: Calling undeclared function printf. Old style K&R code?
So frama itself does work and this is the kind of output I expected to have.
I also have MinGW installed and tried to make Frama use this for compiling. So I removed the Strawberry entries in my Windows Path. After that calling frama-c produces the same output.
When completely uninstalling Strawberry Perl, frama doesn't work (stating gcc is an unknown command), although C:\MinGW\mingw64\bin is also added to my Windows Path, even as very first entry.
C:\MinGW\mingw64\bin\gcc hello.c works, gcc hello.c doesn't.
When Perl is installed gcc hello.c works, even when I delete the Strawberry parts from the Windows Path variable. Wtf?
How can I make things work properly?
There are several issues here, and we have to isolate them in order to fix things.
Strawberry Perl installs its own gcc (based on MinGW), binutils, C headers, etc., by default on directory C:\Strawberry\c\bin. It adds this directory (among others) to the Windows Path variable. Frama-C expects gcc to be in the path, and it is Windows who decides which gcc to choose, if there are several directories in the path which contain a gcc binary. This is why Frama-C seems to use it.
One common mistake (not Windows-specific, but which happens more often in Windows due to the nature of its graphical applications) is to modify environment variables and forget to restart the processes which still have old copies of them (such as Command Prompt). echo %path% should confirm which directories are present in the path for the current command prompt, if there are any doubts about its value.
In case echo %path% contains the expected value, this is what might have happened (unfortunately I cannot reproduce your configuration to test it thoroughly): during installation of Frama-C, it may use the settings present during installation time to choose which directory contains gcc (in your case, C:\Strawberry\c\bin) and later hardcode this directory in its scripts.
This could explain why, after uninstalling Strawberry Perl, even if another gcc was in the path, it was not considered by Frama-C. Ideally, reinstalling Frama-C with a single gcc in the path could allow it to find the right version this time. Note that this is just a hypothesis, I may be completely wrong here.
In any case, the major problem you're having is not with gcc itself, but with the headers included with Strawberry Perl, as explained in the next item.
Concerning the error message:
C:/Strawberry/c/x86_64-w64-mingw32/include/stdio.h:141:[kernel] user error: syntax error
[kernel] user error: skipping file "hello.c" that has errors.
It is indeed not extremely informative and might change in future versions, but it does point to the source line which causes the error (file stdio.h, line 141):
int __cdecl __mingw_vsscanf (const char * __restrict__ _Str,
const char * __restrict__ Format,va_list argp);
In particular, it seems that __restrict__ is the source of the error here (Frama-C Sodium accepts restrict and __restrict, but not __restrict__; this may change in future versions).
Unfortunately, even fixing this (by adding e.g. #define __restrict__ restrict before #include <stdio.h> in your file) does not guarantee that the rest of the file will be parsed, since it seems to be a Windows-specific, C++-prone header that likely contains other C definitions/extensions that are not in the C99 standard, and possibly not accepted by Frama-C.
The best solution would be to ensure Frama-C uses its own stdio.h header, instead of Strawberry Perl's. It is usually installed in share/frama-c/libc (that is, it could be in C:\CodeAnalysis\frama-c\share\frama-c\libc in your installation), but depending on your configuration the headers might not have been found during execution, and Strawberry Perl's headers were included instead.
A quick hack for this specific case might be replacing:
#include <stdio.h>
with:
#include "C:\CodeAnalysis\frama-c\share\frama-c\libc\stdio.h"
But it is far from ideal and likely to lead to other errors.
If you manage to find out how to prevent Strawberry Perl's headers from being included, and ensure Frama-C's header files are included instead, you should be able to run Frama-C.
Note about Cygwin/MinGW path issues
I've had some issues when using a MinGW compiler and a Cygwin build (which is not necessarily a good idea), so here are some quick instructions on how to build Frama-C Sodium with a MinGW-based OCaml compiler using a Cygwin shell (but not a Cygwin-based OCaml compiler), in case it might help someone:
When running ./configure, you'll need to specify a --prefix using a Windows-based path instead of a Cygwin-based one, such as:
./configure --prefix="C:/CodeAnalysis/build"
If you don't, when running Frama-C (after make/make install) it will fail to find the libc/__fc_builtin_for_normalization.i file because it will try to use the Cygwin-based path, which will not work with the MinGW-based OCaml compiler.
Note that you cannot use backslashes (\) when specifying the prefix path, since they will not be correctly converted later.
I had to use the following command to ensure the makefile worked correctly:
make FRAMAC_TOP_SRCDIR="$(cygpath -a -m $PWD)"
Again, this is due to Cygwin paths not being recognized by the MinGW compiler (in particular, the absolute paths used by the plug-ins).
The previous steps are sufficient to compile and run Frama-C (plus the GUI, if you have lablgtk and other dependencies installed). However, there are still some issues, e.g. absolute Windows filenames are not always handled correctly. This can often be avoided by specifying the file names directly in the command line with relative paths (e.g. frama-c-gui -val hello.c), but in the general case, MinGW+Cygwin is not a very robust combination and other issues may arise.
Overall, mixing Cygwin and MinGW is not a good idea due to path issues, but it is nevertheless possible to compile and run Frama-C in such conditions.
I downloaded
Ruben’s build of
Cygwin GCC.
However upon running it seems unable to compile any files
$ touch foo.c
$ gcc foo.c
gcc: error: spawn: No such file or directory
As a workaround, I found this to work
i686-w64-mingw32-gcc foo.c
I had the same problem and solved it by installing the g++ package in addition to gcc-core
I had this same problem on Cygwin64, and the solution was PATH related..kinda.
Turns out, there are copies of gcc in /usr/bin and /bin (at least, there is in my install).
Executing /bin/gcc failed with the error above -- I'm guessing due to incorrectly assumed relative paths???
Executing /usr/bin/gcc works as expected!
In my case, the "problem" was that I had inadvertently injected "/bin" into my PATH environment variable, resulting in /bin/gcc being executed, instead of /usr/bin/gcc. Removing the "/bin" from the path solved the problem.
Still unclear why there are two gcc binaries (which appear to be identical) in different places... but maybe the Cygwin gurus can answer that; or maybe my installation is just foo-barred.
Ruben's builds are not Cygwin GCC packages, rather they are cross-compilers which run on various platforms but target native Windows using the MinGW-w64 toolchain.
In any case, you shouldn't be using them on Cygwin. If you want to compile Cygwin executables, install the gcc4 packages; if you want to cross-compile for Windows, install the mingw64-i686-gcc (for Win32) or mingw64-x86_64-gcc (for Win64) packages instead.
Gcc isn't really the compiler. It's a front end program that orchestrates the execution of any necessary compiler, assembler, and linker components. Typically these others are separately compiled programs.
So, gcc is trying (kind of) to tell you that it can't find the compiler. I guess it needs to be on your PATH or in an expected location.
If you are executing this from a Windows DOS box then it definitely needs a windows PATH setting.
I like to install Cygwin, making sure to include rxvt. At that point, you can configure a purely sh(1) path and your environment is rather more civilized.
I had the same error when I tried to extract a couple of executables from cygwin installation dirctory and copied them into another location.
strace shows me the file which was not found by spawn:
/lib/gcc/x86_64-pc-cygwin/6.4.0/cc1.exe
When I copied cc1.exe into the location relative to
<dir with sh.exe and cpp.exe>/../lib/gcc/x86_64-pc-cygwin/6.4.0/cc1.exe
it works fine.
This error occurs whenever cygwin cc can't find a required file.
For those running stuff within cygwin's bin directly from a Windows shell, a gotcha to watch out for is that Windows allow you to run programs from the command line like this:
e:cyg/bin/gcc -flags
Notice that there is no slash between e: and cyg.
So this command would successfully start cygwin gcc from the Windows shell, but halfway through the run it will error out because some component(s) of gcc will utilize the first argument of the input e:cyg/bin/gcc and unlike mingw, this is not a valid path for cygwin gcc.
This can be fixed simply by changing the command to:
e:/cyg/bin/gcc -flags
Notice the slash in between e: and cyg.
A similar gotcha is due to Windows allowing paths like e:/../folder1 as an alternative to e:/folder1. Windows does not give you an error if you are at the root folder and try to go up another folder using ...
So you could start running cygwin gcc using the command:
e:/../cyg/bin/gcc -flags
..or even:
e:/../../../../../../../../../cyg/bin/gcc -flags
However, it would fail halfway with gcc: error: spawn: No such file or directory because some component(s) of cygwin gcc would attempt to run gcc using the first argument of the command input itself, and unlike mingw, e:/../cyg/bin/gcc is not recognized as a valid path by cygwin because you are going up a folder when there's no folder to go up to.
As like above, this can be fixed by keeping the path valid:
e:/cyg/bin/gcc -flags
Make sure the source file extension is in lowercase (i.e. main.c, not main.C):
$ gcc -o main main.C
$ gcc: error: spawn: No such file or directory
$ gcc -o main main.c
$ # all good
This only refers to the case of the extension as given to the gcc, the actual source file can have the extension in whatever case you want.
Explanation: This is from my experimenting with cygwin and gcc, I don't know the actual reason for this behavior.
I have a problem with the implicit LIBRARY_PATH modification of g++ between two versions (g++ -v gives this info). I set the LIBRARY_PATH to a single local directory where I have custom libraries. However, it turned out that only one version of the g++ (let's call it version A) correctly linked, the other (version B) linked to the system-default, which was not desired. Apparently, the order of directories was mixed up and my specification was not properly respected. It is a similar issue to LIBRARY_PATH not used before /usr/lib anymore in gcc 4.2 and later? although not with these versions.
Somehow I came along the idea to have a look at the specs files of the two different versions (got them via g++ -dumpspecs > specs). I then tried to see if running the version of g++ (B; that was producing the *un*expected modifications) with the specs file of the other version (A) would still yield that modification and to my relief the LIBRARY_PATH was now exactly as I expected it (matching version A)!
I further traced down the place of this weird modification to happen at the following line:
. !m64 !m32;.:../lib64 m64 !m32;.:../lib32 !m64 m32;
Besides appearing to affect the setting/modification of LIBRARY_PATH, I sadly have no clue what this line means.
Therefore I hope that some of you is able to "decipher" this line and explain what it means so that I can try to modify it according to my requirements.
Thank you!
That line affects how libraries are found relative to GCC's $PREFIX/lib directory (where $PREFIX is the directory GCC was installed to.)
There are three parts to it:
$PREFIX/lib/. is used when neither -m32 or -m64 is used on the command-line.
$PREFIX/lib/.:$PREFIX/lib/../lib64 is used when -m64 is used.
$PREFIX/lib/.:$PREFIX/lib/../lib32 is used when -m32 is used.
This suggests to me you are using Debian or Ubuntu, I don't think a vanilla GCC build from the FSF sources would have that in the specs. Were both your GCC versions from .deb packages or did you install them yourself? (The Multi Arch support in recent Debian/Ubuntu releases moves library directories and so breaks vanilla GCC, I think Debian and Ubuntu patch the GCC code for their .deb packages.)
Could you add the output of linking with g++ -v for each of your versions, to see the exact library search paths used by each version?
Also, why not just use -L instead of LIBRARY_PATH? Directories specified with -L always come first, before the system dirs or GCC's own dirs or the ones specified in LIBRARY_PATH.