如何避免linux上的系统标准C / C ++库?

时间:2016-06-04 04:34:16

标签: c++ c linux gcc

我安装了GCC的新版本,这对我的linux系统造成了污染。我计划以更好的方式处理GCC的多个版本。我计划在/ opt / tools目录下安装所有不同的版本。然后我的项目makefile显式指定要使用的版本。这包括所有二进制可执行文件,即g ++,gcc等,以及头文件,库......

这种方法的好处很明显。构建更具可重复性。它不承担版本,而是选择非常具体的版本。在不同的编译器版本之间切换都发生在makefile中。

为了实现这一点,我使用“-nostdinc”并将所有include路径显式地放入我的编译命令行。我的代码包含limits.h,它会导致奇怪的构建错误。

limits.h是我的debian中安装的libc6-dev的一部分。但它不在gcc的include目录中。一些在线资料称标准C lib是操作系统的一部分。我的问题是,构建独立于系统头文件和库的代码是否实用?我怀疑gcc可能缺少其他标题。最初,我认为gcc带有一切。情况并非如此?

换句话说,系统库和头文件是否依赖于debian发行版附带的特定GCC版本?我觉得系统头文件和库是GCC 4.7,而我使用的是GCC 5.3,我感觉很不舒服。

2 个答案:

答案 0 :(得分:4)

在与程序编译相关的典型Linux /“free unix”系统中有几层。

  1. 内核。用户级程序很少直接与内核交互,尽管它们可以。
  2. 内核特定的头文件,由内核模块使用并绑定到Linux内核的特定版本。在Debian这些标题中有linux-headers-<kernel-version>。可能有多个专用于相应内核版本的包。除非您的程序是内核模块或类似程序,否则您不需要它们。
  3. libc的内核特定部分。在Debian系统中,这包含在linux-libc-dev包中。通常这个包不是特定于特定的内核版本,而是特定于“版本的一代”(它发展缓慢并反映新内核用户级设施,常量等的外观)。你需要这个包来编译一个典型的复杂用户土地程序,因为它包含重要的系统范围常量和类型定义
  4. libc。这个库提供了所有常用的“C库”函数,工具等,有时它包装了相应的内核工具(想到open()send()brk()函数),有时它提供了自己的高级函数级别功能(例如qsort()实现)。您需要库来构建几乎任何程序。在debian系统中,它有几个包,标题在libc6-dev可以是同时在单个Linux内核上运行的多个不同的libc实例(例如在chroot s中),但由于库依赖于某些文件层次结构,通常只有一个。

  5. 编译器。编译器带有自己的头文件集,但是对于C编译器来说,编译器特定的头文件比例如C ++编译器要少得多,因为通常C ++编译器有自己的STL实现,这是一个头库通过语言设计。 C编译器中的大多数.h标头负责各种特定于编译器的技巧,如varargs处理(stdarg.h)或Cilk。例如,在Debian 7的gcc-4.7包中,只有47个.h个文件,其中大多数是libgcc的一部分

  6. 实际上,在Debian中你可以安装任意数量的编译器,它们不会相互干扰。例如,现在我的Ubuntu-16.04即可立即安装4个gcc版本:4.7.44.8.54.9.35.3.1, - 和4 clang个版本:3.53.63.73.8。所有这些不同版本的编译器都可以与apt-get install <package-name>一起安装。我想现代的Debian或多或少都有相同的设置。使用相对简单的规则,您可以为任何给定的编译器和任何给定的版本构建一个包。

    在使用CC环境变量进行编译时,可以选择所需的C编译器,并且不需要更改Makefile

    仅当您计划使用完全不同的 libc 实施时,您可能需要-nostdinc,这通常不是这种情况。但有时它很有用,例如用于在没有“完整环境”的情况下为initrd或其他系统启动阶段构建程序。

答案 1 :(得分:2)

GCC不提供任何C头文件。 GNU C库或简称glibc是一个单独的项目。由于GCC需要C库而且与GCC编译器的版本无关,因此拥有与libc无关的工具链并没有多大意义。不,您不需要VM或“Linux From Scratch”,这是不合适的,因为它告诉您从源代码编译整个工具链。将不同版本的GCC安装到他们自己的前缀(目标文件夹)真的很简单。它甚至允许您为可执行文件的名称添加前缀,以简化操作。

我认真地建议你潜入Installing GCC。它是由一个真正的GCC维护者编写的,而且直截了当。不要让它变得比它更难。

要编译GCC,请执行:

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

我正在讨论from the manual的选项:

  

--program-prefix=prefix    - 安装时,GCC支持对程序名称进行一些转换。此选项将前缀添加到程序名称之前   在bindir中安装(见上文)。例如,指定   --program-prefix=foo-会导致gcc被安装为   /usr/local/bin/foo-gcc

此处/usr/local只是autotools的默认前缀。我强烈建议你不要在那里安装GCC。为每个版本执行此操作,您可以gcc-4.8gcc-5.3