Max Li
Max Li

Reputation: 591

How to avoid system standard C/C++ library on linux?

I installed a new version of GCC, which is sort contaminate my linux system. I plan to handle multiple versions of GCC in a better way. I plan to have all different versions installed under /opt/tools directory. And then my project makefile explicitly specifies the version to use. That includes all the binary executable, i.e. g++, gcc etc., and header files, libraries...

The benefit of this approach is clear. The build is more reproducible. It does not assume the version but pick the very specific one. Switching between different compiler versions all happens inside makefile.

To achieve that I use "-nostdinc" and put all include path explicitly into my compile command line. My code includes limits.h and it causes weird build error.

limits.h is part of libc6-dev installed in my debian. But it's not in gcc's include directory. Some online material says standard C lib is part of OS. My question is that is it practical to build code independent of system header files and libraries? I doubt there might be other headers are missing from gcc. Originally, I thought gcc comes with everything. It's not the case?

In other words, do system libraries and headers depends on specific GCC version that comes with the debian distribution? I kind of feeling uncomfortable that system headers and libs are from let's say GCC 4.7, and I am using GCC 5.3.

Upvotes: 3

Views: 1492

Answers (2)

user3159253
user3159253

Reputation: 17455

There're a few layers in a typical Linux/"free unix" system relevant to program compilation.

  1. Kernel. User-level programs rarely interact with kernel directly, although they can.
  2. Kernel-specific headers, used by kernel modules and bound to a particular build of Linux kernel. In a Debian these headers come in linux-headers-<kernel-version>. There could be multiple packages dedicated to corresponding kernel versions. You don't need them unless your program is a kernel-module or alike.
  3. Kernel-specific parts of libc. In a Debian system this comes in package linux-libc-dev. Usually this package isn't specific to a particular kernel version, but rather to a "generation of versions" (it evolves slowly and reflects appearance of new kernel user-level facilities, constants etc). You do need this package to compile a typical complex user-land program, because it contains important system-wide constants, and types definition
  4. libc. This library provides all usual "C library" functions, facilities etc, sometimes it wraps corresponding kernel facilities (think of open(), send(), brk() functions), sometimes it provides its own high-level features (e.g. qsort() implementation). You do need the library to build virtually any program. In a debian system it comes in several packages, headers are in libc6-dev. There could be multiple different libc instances running on top of a single Linux kernel at once (e.g. in chroots), but since the library depends on certain file hierarchy, typically there's only one.

  5. Compilers. Compilers come with their own sets of headers, but for a C-compiler there're much less compiler-specific headers than, for example, for a C++-compiler, because typically C++ compilers have their own STL implementation which is a header-library by language design. Most of these .h headers in C compiler are responsible for various compiler-specific tricks like varargs handling (stdarg.h) or Cilk stuff. For example, in gcc-4.7 package in Debian 7 there're only 47 .h files, most of them being a part of libgcc

Actually, in Debian you can have any number of compilers installed and they won't interfere with each other. For example, right now in my Ubuntu-16.04 there're 4 gcc versions instantly available for installation: 4.7.4, 4.8.5, 4.9.3, 5.3.1, — and 4 clang versions: 3.5, 3.6, 3.7 and 3.8. All these compilers of different versions can be installed with apt-get install <package-name>. I guess that a modern Debian has more or less the same set. Using relatively simple rules you can build a package for any given compiler and any given version.

A required C compiler may be chosen during compilation with CC environment variable and one doesn't need to change Makefile for that.

You may need -nostdinc only if you plan to use a completely different libc implementation, which usually is not a case. But sometimes it's useful, e.g. for building programs for initrd or other stages of system boot-up when there's no a "complete environment".

Upvotes: 4

GCC doesn't ship any C header files. The GNU C library or glibc for short is a separate project. It doesn't really make sense to have a libc agnostic toolchain as GCC needs a C library and it has nothing to do with the version of the GCC compiler. No, you don't need a VM or "Linux From Scratch", which is ill-suited because it tells you to compile the entire toolchain from source. It's really dead simple to install different versions of GCC to their own prefix (destination folder). It even allows you to add prefixes to the name of the executable to make things easier.

I seriously recommend you dive into Installing GCC. It's written by an actual GCC maintainer, and it's straight to the point. Don't make it harder than it is.

To compile GCC, do:

tar xzf gcc-VERSION.tar.gz
cd gcc-VERSION
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir
$PWD/../gcc-VERSION/configure --prefix=$HOME/gcc-VERSION --enable-languages=c,c++
make
make install

And the option I was talking about from the manual:

--program-prefix=prefix - GCC supports some transformations of the names of its programs when installing them. This option prepends prefix to the names of programs to install in bindir (see above). For example, specifying --program-prefix=foo- would result in gcc being installed as /usr/local/bin/foo-gcc.

Here /usr/local is just the default prefix for autotools. I strongly do not recommend you install GCC there. Do this for each version, and you can have gcc-4.8, gcc-5.3, etc.

Upvotes: 2

Related Questions