【问题标题】:Invoking GCC as "cc" versus "gcc"将 GCC 调用为“cc”与“gcc”
【发布时间】:2010-10-30 17:05:52
【问题描述】:

我知道在大多数 GNU/Linux 系统上,GCC 可以通过命令行中的名称“cc”调用(而不是“gcc”)。以一种方式调用 GCC 与另一种调用时,GCC 的行为有什么不同吗?

例如,我知道通过名称“g++”而不是“gcc”调用 GCC 会导致 GCC 的行为不同(它将 .c 文件视为 C++ 源代码并在 C++ 标准库中链接)。 “gcc”和“cc”在行为上有什么相似的区别吗?

编辑:到目前为止,没有一个答案给出了明确的“是”或“否”,即如果以一种方式调用 GCC 与另一种方式调用,GCC 的行为是否会有所不同.然而,深入研究源代码以检查其行为的想法使我走上了这条道路。根据我在那里的发现,我现在认为答案是:

没有。无论是通过“gcc”还是“cc”调用,GCC 的行为都是一样的

【问题讨论】:

  • 似乎是相同的 aa gawk 与 awk,gmake 与 make 等。我会向我推销他们总是平等的。在 solaris 系统上,我听说 make 与 gmake(gnu make)不同。也许在某些系统上类似的事情适用于 gcc 和 cc。

标签: c linux gcc compiler-construction gnu


【解决方案1】:

在我的 Mac 上来自 man gcc:

在 Apple 的 GCC 版本中,cc 和 gcc 实际上是指向 a 的符号链接 编译器命名为 gcc-version。 类似地,c++ 和 g++ 是指向 a 编译器命名为 g++-version。

基于此,我会假设 cc 和 gcc 的行为方式相同。

【讨论】:

  • 在 Unix 世界中,为同一个可执行文件设置多个链接是很常见的,它会根据调用时使用的名称更改一些默认值。
  • 哇,没有解释就投了反对票 - 非常有帮助......也许他们不喜欢什么?
  • 也许他们不知道 Mac OS X 是完全兼容 posix 的 Unix 系统
  • 不,也许他们考虑混淆以下逻辑链:“符号链接到相同的可执行文件 -> 相同的行为”。例如,您所有的基本命令行工具都可以符号链接到最小系统上的 busybox,但作为完全独立的工具运行
【解决方案2】:

考虑到这是来自 UNIX,我会说“cc”是通用名称,“gcc”是实际的编译器。即“gcc”提供“cc”,因此寻找“cc”的程序会找到并使用“cc”,而完全不知道正在使用的实际编译器。

另外,UNIX 程序应该不知道调用它们的实际名称(想想 Windows 桌面快捷方式——检查快捷方式的名称是没有意义的),所以,不,“gcc”和“cc” " 如果 "cc" 是指向 "gcc" 的链接,则执行相同的操作。

当然,除非“cc”不是符号链接,而是调用 gcc 的 shellscript。

【讨论】:

  • gzip 检查其名称。如果它的名字是 gunzip 它假定 -d。
  • “另外,UNIX 程序应该不知道用于调用它们的实际名称” 这绝对不是真的。你听说过多调用二进制文件吗? IE。忙箱? busybox.net
  • 而且,毕竟,“sh”通常是“bash”的符号链接,这使它表现得像一个 POSIX shell。 shbash 实际上与 ccgcc 非常相似。
  • 嗯,gzipgunzip 是同一个实用程序提供两个不同实用程序的案例。在 gcccc 的情况下,它提供了一件事。我确实对 argv[0] 不可知的 unix 工具进行了概括,但在大多数情况下,它们只是因为如果重命名它们会损坏。如果一个二进制文件提供了多个实用程序,那么,是的,直接调用它和调用它创建的符号链接来提供相关工具是有区别的,但是 gcccc 不是这样的:除非语义(即预期的行为) 变化,它们是历史原因的同义词。
【解决方案3】:

在我看来,cc(链接到一些旧的 SUS 规范)旨在成为系统编译器的供应商中立接口。它被标记为旧版:

c89 实用程序提供与 ISO C 标准的接口,但 cc 实用程序接受 C 语言的未指定方言:它可能是标准 C、通用 C 或其他一些变体。可移植 C 程序的编写应符合 ISO C 标准并使用 c89 编译。

POSIX 有一个名为c99 的实用程序,我相信它是c89 的继承者。它说

c99 实用程序基于最初在 ISO POSIX-2:1993 标准中引入的 c89 实用程序。 c89 的一些变化包括对标准库部分内容的修改,以考虑新的标题和选项;例如,添加到 -l rt 操作数,以及为跟踪函数添加 -l 跟踪操作数。

我对所有这些不同的标准都不是很熟悉,但看起来更新的 SUSv3 (POSIX:2004) 和更新的 POSIX:2008(似乎还没有 SUS 编号)没有不再指定名为cc 的实用程序,但只指定名为c99 的实用程序。顺便说一句,我的 Linux 系统 (Arch_Linux) 包含 c99 的联机帮助页,但不包含 c89,但只包含一个名为 cc 的实用程序,但既不包含 c89 也不包含 c99。那里有很多混乱:)

【讨论】:

  • 有趣的链接。有人可能应该告诉 GNU Make 的人这件事,因为如果你不覆盖 ${CC},它仍然会调用“cc”作为默认值。显然,他们应该默认使用其他实用程序之一。根据标准,似乎 c89 应该是首选实用程序。
  • OTOH,因为那是 1997 年写的,也许现在首选的实用程序应该是 c99。
  • 是的,SUSv3 不再包含 c89。只有我链接到的旧版本推荐它(SUSv2)
【解决方案4】:

cc 只是调用编译器的 UNIX 方式,它适用于所有 Unices。

【讨论】:

  • 这并没有解决问题。
  • 其实是这样,cc在Unix上的意思是“C编译器”,仅此而已。
  • 提问者也询问了cc和gcc的区别。这也可以作为答案并解决问题,imo
【解决方案5】:

GCC 文档中没有任何内容表明如果 GCC 的可执行文件名称不是 gcc 而是 cc,则 GCC 的行为会有所不同。 GNU Fortran 编译器甚至mentions that:

gcc 命令的一个版本(也可以作为系统的 cc 命令安装)

【讨论】:

    【解决方案6】:

    对于咧嘴笑,我只是从 gcc (main.c -> top_lev.c -> opts.c -> langhooks.c) 中追踪argv[0] 是如何使用的,看来argv[0] 目前用于无非就是在malloc 失败时报告一些东西。如果argv[0] 不是gcc,则似乎没有任何行为变化。

    【讨论】:

    • 我遇到的唯一问题是“cc --version”与“gcc --version”的输出略有不同(它说“cc”而不是“海合会”)。所以里面的something一定是在看argv[0]。
    • 您的回答促使我自己研究源代码。我发现 argv[0] 确实被分配给“程序名”,最终被传递给其他函数(并存储在环境中)。虽然我没有进行 exhaustive 搜索,但据我所知,它仅用于显示目的(例如,在“--version”输出、“usage”输出、错误消息、等)。
    • 我刚刚注意到,只有当 cc 和 gcc 是相同的可执行文件时,这才是正确的。系统可能有不同的二进制文件吗?想象一下,cc 可能会链接到 clang 二进制文件,而 gcc 可能会链接到 gcc。老实的问题,我不知道。
    【解决方案7】:

    我今天也有同样的疑问,我试图自己找到它:

    $ which cc
     /usr/bin/ccc
    
    $file /usr/bin/cc
     /usr/bin/cc: symbolic link to '/etc/alternatives/cc'
    
    $file /etc/alternatives/cc
     /etc/alternatives/cc: symbolic link to '/usr/bin/gcc'
    
    $which gcc
     /usr/bin/gcc
    

    所以,基本上cc 指向gcc

    您也可以使用cc -vgcc -v 进行检查。如果他们打印出同样的东西,那就意味着他们完全一样。

    【讨论】:

    • 请注意 Javier 对 stefanB 的回答的评论——Unix 将“程序名称”作为第 0 个命令行参数提供给程序,并且 Unix 中的许多程序都设置为来自许多不同名称的符号链接,并根据用于调用它们的名称来改变它们的行为。 (例如,gunzip 是 gzip 的链接,但是如果您调用 gzip,它会压缩东西,如果您调用 gunzip,它会解压缩它们。)因此,如果您通过名为 'cc' 的符号链接运行 GCC 可能会有不同的行为,这是完全合理的。 .
    【解决方案8】:

    即使 gcc 的运行方式与 argv[0] 的值无关,但无论您指定哪个编译器,并非所有软件的运行方式都相同。

    在 RHEL 5.5 (gcc 4.1.2) 上构建 zlib 1.2.5 时:

    $ md5sum $(which cc)
    69a67d3029b8ad50d41abab8d778e799  /usr/bin/cc
    $ md5sum $(which gcc)
    69a67d3029b8ad50d41abab8d778e799  /usr/bin/gcc
    

    但是:

    $ CC=$(which cc) ./configure
    Checking for shared library support...
    Tested /usr/bin/cc -w -c -O ztest20557.c
    Tested cc -shared -O -o ztest20557.so ztest20557.o
    /usr/bin/ld: ztest20557.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
    ztest20557.o: could not read symbols: Bad value
    collect2: ld returned 1 exit status
    No shared library support; try without defining CC and CFLAGS
    Building static library libz.a version 1.2.5 with /usr/bin/cc.
    Checking for off64_t... Yes.
    Checking for fseeko... Yes.
    Checking for unistd.h... Yes.
    Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
    Checking for vsnprintf() in stdio.h... Yes.
    Checking for return value of vsnprintf()... Yes.
    

    还有:

    $ CC=$(which gcc) ./configure
    Checking for shared library support...
    Building shared library libz.so.1.2.5 with /usr/bin/gcc.
    Checking for off64_t... Yes.
    Checking for fseeko... Yes.
    Checking for unistd.h... Yes.
    Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
    Checking for vsnprintf() in stdio.h... Yes.
    Checking for return value of vsnprintf()... Yes.
    Checking for attribute(visibility) support... Yes.
    

    configure 脚本没有考虑 Linux 系统上的 cc 可能是 gcc 的可能性。所以,要小心你的假设有多远。

    【讨论】:

    • 这是不言而喻的。编译器的行为没有任何不同。这是configure 脚本的一个缺点。该脚本知道gcc 可以生成共享库,并且它知道gcc 在Linux 上编译共享库时需要-fPIC 选项。如果编译器不是gcc,那么configure会尝试测试编译器是否可以生成共享库。 但是它无法预测它不知道的编译器需要哪些编译器标志,因此用户必须提供它们。您需要在命令行上提供必要的标志(例如通过CFLAGS=-fPIC)。
    • 这是一个辅助警告,而不是一个答案。在上述情况下将 gcc 调用为 cc 不会导致其操作不同,但调用软件以不直观的方式操作,导致出现不同的行为。
    【解决方案9】:

    "不。无论是否通过 'gcc' 调用,GCC 的行为都是相同的 或‘抄送’。”

    [引自原帖]

    根据我在 Ubuntu 14.04 中的经验,情况并非如此。

    当我编译我的程序时:

    gcc -finstrument-functions test.c
    

    我的代码行为没有任何变化。但是当我编译使用

    cc -finstrument-functions test.c
    

    它的行为确实不同。 (在这两种情况下,我都将适当的更改合并到here 描述的代码中,以使 -finstrument-functions 工作)。

    【讨论】:

      【解决方案10】:

      这个帖子可能很旧,但我想给它加点东西 (也许将来有人会找到它)。

      如果你编译了这个程序

      #include <stdio.h>
      #include <stdlib.h>
      
      void
      myFunction(char *args)
      {
         char buff1[12];
         char buff2[4] = "ABC";
      
         strcpy(buff1,args);
      
         printf("Inhalt Buffer2: %s",buff2);
      
      }
      
      int main(int argc, char *argv[])
      {
      
         if(argc > 1)
         {
            myFunction(argv[1]);
         }
         else
            printf("no arguments sir daimler benz");
      
         getchar();
      
         return 0;
      }
      

      使用“gcc”,并且您将“AAAAAAAAAAAAAAAAAAAAAAAAA”作为参数传递,它不会溢出到缓冲区2,而如果您使用“cc”编译它会溢出,这对我来说是一个提示,如果您使用“gcc”,内存管理的工作方式不同,可能是通过在字段 buff1 和 buff2 的内存段之间放置空间?

      也许有更多经验的人可以在这里把光明变成黑暗。

      【讨论】:

      • 我试过这个(在 gcc 版本 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) 上),关闭和打开堆栈保护器,并且都以 分段错误结束或 检测到堆栈粉碎,最后 cc 链接到 /etc/alternatives/cc,也就是链接到 /usr/bin/gcc。正如@abcoep 所说,cc 和 gcc 仅在制表符完成方面有所不同(据我所知)。
      【解决方案11】:

      对于我的操作系统 (Ubuntu 14.04),cc 不允许制表符补全,而 gcc 允许。

      【讨论】:

        猜你喜欢
        • 2018-02-23
        • 2015-03-04
        • 2010-12-03
        • 2013-11-18
        • 1970-01-01
        • 1970-01-01
        • 2017-05-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多