Gcc exit status codes - gcc

I've noticed that when running gcc, if the compile failes, most of the time it returns an exit status code of '1'. However, it sometimes returns a status code of '4' (for example, if the input file does not exist). I haven't been able to find anything in the gcc documentation that covers what different error codes might mean -- does anyone know of any?

According to the official documentation of the command line switch -pass-exit-codes:
Normally the gcc program exits with the code of 1 if any phase of the compiler returns a non-success return code. If you specify -pass-exit-codes, the gcc program instead returns with the numerically highest error produced by any phase returning an error indication. The C, C++, and Fortran front ends return 4 if an internal compiler error is encountered.

Related

Let make fail, if Makefile encounters undefined variable

I had a mistake in my Makefile:
verify-prettier:
$(PRETTIER) --check **/*.yaml **/*.yml
The var PRETTIER was not set.
The result:
check **/*.yaml **/*.yml
bash: line 1: check: command not found
make: [Makefile:156: verify-prettier] Error 127 (ignored)
I would like to get an error (which does not get ignored), if I accidentaly have an undefined variable.
Is there a way to configure make accordingly?
Version: GNU Make 4.3
We don't need to support other make implementations.
I know this, but I want it to fail, not just a warning.
MAKEFLAGS=--warn-undefined-variables
Update, since this seem to be unavailable up to now, I created a feature request: https://savannah.gnu.org/bugs/?63737
As said in comments there is no way as of current (4.3) GNU Make versions. And any addition is likely to take forever before reaching the general public (WSL still stuck at 4.2.1!!!).
I can think of a few crutches that might work depending on circumstances:
Pass --warn-undefined-variables to make, then pipe output to e.g. grep testing absence of the warning message. Suitable for build automation where command line length and complexity doesn't matter, less so for interactive use.
Have blocks of ifndef and error at the end of the makefile. You'll need a specific block for each variable, however this isn't too far off how unit tests work and those are generally accepted :-)
Default initialize to something that will fail. In the case of $(PRETTIER) you could initialize it to false, silently eating any arguments and returning failure. Feasibility depends on how the variable is used. Works well for a variable used as a command, might get trickier for arguments though I'm sure some hack ought to work (because how hard can it be to intentionally write crashing code).

How to tell gcc not to generate particular instructions

I am using gcc to compile a set of c codes. And my question is: can I tell gcc not to generate some specific instructions?
e.g. I don't want gcc to generate MUL instruction, how should I do?
I'm working on self implemented MIPS cpu and related codes, and for some reasons, I don't want gcc to generate some weird instructions that I've not implemented. It seems that I need to hack the gcc a little bit.
Based on Krister Walfridsson's blog, the way to do it could be:
Add an command line option to the machine.opt file, so to create a global variable.
Find the instruction node in machine.md or other files, that emits the instruction you want to disable. Change the condition to be on the new variable you'v added. When the condition is not met, gcc would emit a call to a function that you'll supply in your .c file or lib file.
As a simpler example, take a look at the ft32 architecture directory. It creates an global variable NODIV based on a -mnodiv command line option. The instruction node in the ft32.md file contains:
(define_insn "divsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(div:SI
(match_operand:SI 1 "register_operand" "r,r")
(match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
"!TARGET_NODIV"
"div.l %0,%1,%2")
In this ft32 case, when the variable is not set, gcc emits div.l assembly code. When it is set, it would make a call to a function named __divsi3.
Though I have not tried this out. Will update with exact information when I get a chance to try it out.

Detect compiler and use compiler-specific flags when invoking

I'm handed a variable CC which contains the executable that refers to the compiler on the system. I need to take this executable and eventually call it with some compiler-specific link arguments.
My current approach seems very fragile:
def guess_compiler(cc):
out = subprocess.check_output((cc, '--version'))
for possible in (b'clang', b'gcc'):
if possible in out:
return possible.decode()
else:
# Fall back to gcc
return 'gcc'
From this I'm using a mapping of the specific linker arguments I care about:
return {
'clang': '-Wl,-undefined,dynamic_lookup',
'gcc': '-Wl,--unresolved-symbols=ignore-all',
}[cc]
In short, I'm hoping there's a better (less fragile) way to do what I've accomplished.
For those looking for why I want something like this, it's mostly for portability in a project I'm implementing.
I'd rather call a compiler with some dummy code and these flags passed in. This is also what tools like Autotools and CMake do.
The problem with your current approach is that text string you see in --version output can actually be arbitrary. For instance, when clang wasn't that popular, FreeBSD's cc --version have been giving
GCC 4.2.1 -compatible Clang bla bla
So, just call the compiler with each flag you are interested in and then look at exit code.
An example of how to do this:
for flag in FLAGS:
try:
subprocess.check_call((cc, 'test.c', flag), cwd=tmpdir)
return flag
except subprocess.CalledProcessError:
pass
else:
# wellp, none of them worked, fall back to gcc and they'll get a
# hopefully reasonable error message
return FLAG_GCC

osx: ld return codes

I am trying to link a few static libraries to create the final executable for iOS using a build script. My problem is that ldalways exits with code 136. My question is: how can I find out what code 136 means? man ld does not mention any return codes at all. I found two lists of system error codes but none for ld:
System error codes from 0 to -261, System error codes from 1 to 32767
Alternatively, how can I get ld to tell me the problem. I have tried all the options for logging but none of them get it to print anything.
Typically, exit codes greater than 127 mean that a signal terminated your program. The signal number is the exit code - 128. In your case,the signal with the number 8 is SIGFPE. Seems like a floating point exception was the cause of the abort.

What is wrong with this Fortran '77 snippet?

I've been tasked with maintaing some legacy fortran code, and I'm having trouble getting it to compile with gfortran. I've written a fair amount of Fortran 95, but this is my first experience with Fortran 77. This snippet of code is the problematic one:
CHARACTER*22 IFILE, OFILE
IFILE='TEST.IN'
OFILE='TEST.OUT'
OPEN(5,FILE=IFILE,STATUS='NEW')
OPEN(6,FILE=OFILE,STATUS='NEW')
common/pabcde/nfghi
When I compile with gfortran file.FOR, all lines starting with the common statement are errors (e.g. Error: Unexpected COMMON statement at (1) for each following line until it hits the 25 error limit). I compiled with -Wall -pedantic, but fixing the warnings did not fix this problem.
The crazy thing is that if I comment out all 4 lines starting with IF='TEST.IN', the program compiles and works as expected, but I must comment out all of them. Leaving any of them uncommented gives me the same errors starting with the common statement. If I comment out the common statement, I get the same errors, just starting on the following line.
I am on OS X Leopard (not Snow Leopard) using gfortran. I've used this very system with gfortran extensively to write Fortran 95 programs, so in theory the compiler itself is sane. What the hell is going on with this code?
Edit: Compiling with g77 gives:
test.FOR: In program `MAIN__':
test.FOR:154:
IFILE='TEST.IN'
1
test.FOR:158: (continued):
common/pabcde/nfghi
2
Statement at (2) invalid in context established by statement at (1)
Er, what context is established at (1)?
I don't think you can put COMMON statements below the executable statements in FORTRAN 77, see the specification, Sec. 3.5.
Just move the COMMON statement close to the beginning of the procedure, before any executable statement.

Resources