Compiling GNU C into C89 - c

I have a project where the target will probably be an embedded system of some type with a compiler that's probably C89 or equivalent. However, I would like to use the GCC extensions from GNU C.
Is there a way to tell GCC to compile to C89? Maybe some assembly/disassembly process?

Compiling to C89 is not the same the same as gcc with extensions, unfortunately. They are in fact mutually exclusive.
You need to decide for sure which you want for your project, and then look at the -std=c89 (and possibly -pedantic) options to gcc if you really want to stick to C89. If you want GNU extensions, look at the gcc docs, there is a fairly extensive set of options for the -std= argument.
There are also a number of gcc cross-compilers in existence, take a look at those and see if they fit your embedded target platform, you may have an easier path available.

I don't know about GCC 5 and higher, but before the default was actually C89 with GNU extensions.
If you want to be explicit use the -std flag, like -std=gnu89.
See Options Controlling C Dialect in the online manual.
If you want to use GNU extensions, then you must use a compiler that actually support them, like GCC. If you don't want to use GNU extensions then you can use any compliant compiler.
Also note that GCC is very portable. While the later versions might not support your target platform, there are probably earlier versions that does.

Related

Should I use gcc or cc when programming in C?

I searched a little bit and one google search was enough to discover the differences between the gcc and cc compilers, but I did not find the advantages in using one or another to compile C programs
Which compiler should I use? and why?
The compiler installed as part of X-Code on OS/X is a recent version of clang whose development is sponsored by Apple.
gcc is not provided nor supported by Apple.
Unless you install gcc explicitly from one of its distributions, gcc is an alias for clang on OS/X, just like cc.
The reason for this is to support packages that use gcc explicitly as the C compiler.
On your system, it does not matter which alias you use, the compiler invoked will be clang, which has a high degree of compatibility with gcc extensions but generates different code. Both are very advanced and dependable.

MSVC's supported subset of C

So Microsoft's MSVC from Visual Studio 2019 doesn't support C99 (or later), but it does support C89 and some constructs from C99.
Is there an option for the GCC C-compiler (not C++-compiler) to use a standard that would guarantee that the source can also be compiled with MSVC? If it compiles with -std=iso9899:199409 -pedantic under GCC, can MSVC compile it?
Is there a reason you need to care if MSVC can compile it? GCC ("mingw") can target Windows PE object files with ABI compatible with MSVC, so users could build with that, or you could even ship them binary object files/library files to use so they don't need any tooling.
Policing your code base for compatibility with a known-broken/intentionally-broken compiler does not seem like a worthwhile activity unless you actually have reason to want to use that compiler, rather than just allowing users of that compiler to link with your code.
Pretty much the only way to you can ensure it builds with MSVC and GCC is to build the code with both toolsets. In addition to language constructs, there are a number of differences in the handling of compiler-defined preprocessor symbols, differences in what the preprocessor can handle, etc.
Personally I've been doing a lot of work getting C++ code to build with MSVC and Clang, and I've hit many minor issues that have to be fixed to get things to build with both toolsets. The C/C++ language standards help make the code portable, but you still have to run it through more than one toolset to get it to build 'cleanly'.
If you want your code to be robustly portable you also should build it for multiple architectures.
For my GitHub libraries, I build for ARM, ARM64, x86, x64 on MSVC, VS 2015 Update 3/VS 2017/VS 2019, targeting Win32 desktop, UWP, and Xbox One. I also build with clang for Windows for x86 and x64. Each one finds slightly different issues, but the end result is a lot more portable.

Can I safely assume all (or most) "cc" supports "-Wall" on *nix systems?

I want to write in Makefile like this
foo: foo.c
$(CC) -o foo -Wall foo.c
but I'm not sure if all cc implementations support -Wall.
No, there is no standard regarding the command-line interface of C compilers.
The Microsoft compiler (in Windows) for instance does not accept options starting with - at all, since that's not the syntax typically used with Windows programs.
No, the closest thing you can do to use only portable options is to restrict yourself to the POSIX C89 and C99 options. -Wall is not one of them. See the Opengroup's Unix Specification for c99 for options which are. And that only gives answers for unixy systems, not Microsoft.
-Wall was (AFAIK) introduced by GNU gcc and inherited by clang to be compatible with GNU gcc.
If you are not afraid to research other build tools, there are some that support multi-OS or multi-toolchain builds out of the box. I believe scons and cmake can do this.

Is clang a standalone C compiler or does it need gcc?

I want to use clang on Windows to compile C code.
I'd like to know if it is in fact a standalone compiler that can do that, or are its aims somewhat different?
I've used it before, but it appears now that is was piggy-backing on top of whatever gcc compilers were lying around (mingw for example).
If I try a fresh binary installation of clang 64-bits (and I hide my mingw/gcc directories), then it can't find stdio.h for Hello World. This is running from directly inside the bin directory (C:\clang\bin). If I unhide mingw, it will compile, but then I get errors like this (one mingw compiler is in c:\win):
c:\win\bin\ld.exe cannot find -lgcc_s
Considering clang is a 438MB installation, you'd think it would have it's own include and library files! I want to use clang in place of gcc.
So, what am I doing wrong? (I've seen a few questions also about the inability to find stdio.h, but they weren't helpful. Surely clang must be able to compile Hello World by itself?!)
You are confusing compiler with linker with standard library.
Clang is a full featured independent compiler. But it does not provides the standard library (the library containing stdio.h). Traditionally, on Unix systems, the operating systems must provide the standard library it uses. But since you are using Windows, it doesn't, and for whatever reason it finds the ones from MingW installed. There are many free implementations of C standard library which are compatible with Clang.
Lastly, ld.exe is the linker, and it also, traditionally, must be provided by the system. There is one linker, lld, that I believe is being developed alongside Clang, but for whatever reason, the packager of the version you downloaded just chose to configure clang to simply call ld.
Clang is a completely separate compiler (written entirely from scratch, using LLVM). You don't need GCC to use Clang, as can be shown in the case of FreeBSD (they completely replaced GCC with Clang/LLVM and don't install GCC in the base anymore for licensing reasons). There are a variety of different C compilers other than GCC, it's just that GCC is the most common.
However, no compiler provides the standard C libraries (GCC provides some weird libraries like the one you're trying to use). C libraries are provided separately, and you need to install C libraries in order to compile any significant C program. The error message saying cannot find -lgcc_s tells me that you're trying to link against some library provided by GCC. In this case, you probably want to install that library by installing GCC (but note that you don't need GCC to use Clang.
It does appear that your version of Clang has been compiled to use GNU's linked ld, not LLVM's linked lld. As such, you'll need GCC's linker (or you can recompile clang to use LLVM's linker, or just compile the object files and use lld separately).
I think you are missing a path variable. After install you must manually add a PATH to the Windows Environment.

What GNU C extensions are available that aren't trivial to implement in C99?

How come the Linux kernel can compile only with GCC? What GNU C extensions are really necessary for some projects and why?
Here's a couple gcc extensions the Linux kernel uses:
inline assembly
gcc builtins, such as __builtin_expect,__builtin_constant,__builtin_return_address
function attributes to specify e.g. what registers to use (e.g. __attribute__((regparm(0)),__attribute__((packed, aligned(PAGE_SIZE))) ) )
specific code depending on gcc predefined macros (e.g. workarounds for certain gcc bugs in certain versions)
ranges in switch cases (case 8 ... 15:)
Here's a few more: http://www.ibm.com/developerworks/linux/library/l-gcc-hacks/
Much of these gcc specifics are very architecture dependent, or is made possible because of how gcc is implemented, and probably do not make sense to be specified by a C standard. Others are just convenient extensions to C. As the Linux kernel is built to rely on these extensions, other compilers have to provide the same extensions as gcc to be able to build the kernel.
It's not that Linux had to rely on these features of gcc, e.g. the NetBSD kernel relies very little on gcc specific stuff.
GCC supports Nested Functions, which are not part of the C99 standard. That said, some analysis is required to see how prevalent they actually are within the linux kernel.
Linux kernel was written to be compiled by GCC, so standard compliance was never an objective for kernel developers.
And if GCC offers some useful extensions that make coding easier or compiled kernel smaller or faster, it was a natural choice to use these extensions.
I guess it's not they are really that necessary. Just there are many useful ones and cross-compiler portability is not that much an issue for Linux kernel to forgo the niceties. Not to mention sheer amount of work it would take to get rid of relying on extensions.

Resources