Hasty Briefsbeta

Bilingual

C extensions, portability, and alternative compilers

3 hours ago
  • #C Programming
  • #Portability
  • #Compiler Development
  • Real-world C code often relies on non-standard behaviors and compiler extensions, not just for features but to work around bugs and gaps in compilers and libraries.
  • System C library headers (e.g., glibc's sys/cdefs.h) use preprocessor checks for compiler-specific macros, but these can be broken for non-GCC/clang compilers, affecting ABI compatibility.
  • Compiler-builtin headers (e.g., stddef.h, limits.h) are required for freestanding implementations, but POSIX adds platform-specific constants, leading to complex header dependencies.
  • Feature detection in projects like SDL_endian.h can be flawed, assuming GCC-style inline assembly for unknown compilers based on ISA macros, ignoring builtin availability.
  • Inline function semantics (e.g., __only_inline in OpenBSD) are messy due to conflicts between C99, GCC pre-C99 behavior, and C++, requiring compiler-specific workarounds.
  • Gnulib's compatibility code for extern inline highlights widespread broken implementations, with convoluted preprocessor logic to handle different compilers and versions.
  • Bionic (Android's libc) heavily uses clang-specific extensions (e.g., _Nonnull), requiring command-line flags to define them away for other compilers.
  • Compiler developers face challenges: patching upstream incompatibilities, gaining popularity for dedicated support, distributing patches, or pretending to be GCC to minimize disruption.
  • Clang defines __GNUC__ to claim GCC 4.2.1 compatibility but avoids bumping version macros to prevent unchecked use of newer GCC extensions, advocating for feature test macros instead.
  • The GCC/clang duopoly dominates *NIX land, but independent C compilers (tcc, cproc, etc.) persist, highlighting the difficulties of C portability and compiler compatibility.