A Brief History of GCC

本文回顾了GNU Compiler Collection (GCC) 的发展历程,从最初的GNU C编译器到现今支持多种语言及架构的编译器集合。文章详细介绍了GCC由Richard Stallman发起,经历了Cygnus时期的改进与扩展,并通过EGCS项目与其他分支合并,最终成为广泛使用的开源编译器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A Brief History of GCC

The very first (beta) release of GCC (then known as the "GNU C Compiler") was made on 22 March 1987:

   Date: Sun, 22 Mar 87 10:56:56 EST
   From: rms (Richard M. Stallman)

   The GNU C compiler is now available for ftp from the file
   /u2/emacs/gcc.tar on prep.ai.mit.edu.  This includes machine
   descriptions for vax and sun, 60 pages of documentation on writing
   machine descriptions (internals.texinfo, internals.dvi and Info
   file internals).

   This also contains the ANSI standard (Nov 86) C preprocessor and 30
   pages of reference manual for it.

   This compiler compiles itself correctly on the 68020 and did so
   recently on the vax.  It recently compiled Emacs correctly on the
   68020, and has also compiled tex-in-C and Kyoto Common Lisp.
   However, it probably still has numerous bugs that I hope you will
   find for me.

   I will be away for a month, so bugs reported now will not be
   handled until then.

   If you can't ftp, you can order a compiler beta-test tape from the
   Free Software Foundation for $150 (plus 5% sales tax in
   Massachusetts, or plus $15 overseas if you want air mail).

   Free Software Foundation
   1000 Mass Ave
   Cambridge, MA  02138

Since then, there have been several releases of GCC. It has grown to support more languages, many more architectures and sports many, many more optimisations.

The Early Days

Richard Stallman (a.k.a. RMS) wanted a Free C compiler for the GNU project he had started in 1984.

To quote from The GNU Project:

Shortly before beginning the GNU project, I heard about the Free University
Compiler Kit, also known as VUCK. (The Dutch word for "free" is written
with a V.) This was a compiler designed to handle multiple languages,
including C and Pascal, and to support multiple target machines. I wrote to
its author asking if GNU could use it.

He responded derisively, stating that the university was free but the compiler
was not. I therefore decided that my first program for the GNU project
would be a multi-language, multi-platform compiler.

Hoping to avoid the need to write the whole compiler myself, I obtained the
source code for the Pastel compiler, which was a multi-platform compiler
developed at Lawrence Livermore Lab. It supported, and was written in,
an extended version of Pascal, designed to be a system-programming
language. I added a C front end, and began porting it to the Motorola
68000 computer. But I had to give that up when I discovered that the
compiler needed many megabytes of stack space, and the available 68000
Unix system would only allow 64k.

I then realized that the Pastel compiler functioned by parsing the entire
input file into a syntax tree, converting the whole syntax tree into a chain
of "instructions", and then generating the whole output file, without ever
freeing any storage. At this point, I concluded I would have to write a new
compiler from scratch. That new compiler is now known as GCC; none of the
Pastel compiler is used in it, but I managed to adapt and use the C front
end that I had written.

The Cygnus Years

To quote Michael Tiemann from Open Sources

The GNU compiler already supported dozens of host environments and over a dozen target architectures (I had written six of the ports myself ), making it one of the most widely ported compilers of its time. [...]

First, GCC was in the process of transitioning from Version 1.42 to Version 2.0. While GCC Version 1 was good enough to beat most compilers on CISC machines like the m68k and the VAX, lots of new optimizations were needed to make it competitive on RISC platforms. When I did the first GCC port to the SPARC in 1988, GCC was 20% slower than Sun's compiler. I wrote an instruction scheduler in 1989 that narrowed the gap to 10%, and I worked on a branch scheduler that same year that, with the instruction scheduler, got GCC to within 5% of Sun's compiler. With the world transitioning from CISC to RISC, we went from having hands-down the best compiler in almost every regard to a more complex set of tradeoffs the customer would have to evaluate. It was no longer a simple, straightforward sell.

Second, GNU C++ was falling behind. I wrote GNU C++ in the fall of 1987, making it the first native-code C++ compiler in the world. C++ was a much more complex language than C, and it was still evolving when we started Cygnus. In 1990, several new, even more complex features became "standard," and with all the distractions of Cygnus, I had no time to keep GNU C++ current.

The Cygnus GNUPro toolkit included GCC support for over 175 host/target combinations by 1999.

EGCS

GCC development in the early days was a bit too conservative for the tastes of many an eager hacker. Several of the frustrated developers started their own forks of GCC in the hopes of getting their changes much faster to end users. In 1997, several of these hackers got together to create the EGCS project. From the original EGCS announcement:

From: gumby@cygnus.com (D.V. Henkel-Wallace)
Subject: A new project to merge the existing GCC forks
Date: Fri, 15 Aug 1997 16:31:29 -0700
To: egcs@egcs.cygnus.com

A bunch of us (including Fortran, Linux, Intel and RTEMS hackers) have
decided to start a more experimental development project, just like
Cygnus and the FSF started the gcc2 project about 6 years ago.  Only
this time the net community with which we are working is larger!  We
are calling this project 'egcs' (pronounced 'eggs').

Why are we doing this?  It's become increasingly clear in the course
of hacking events that the FSF's needs for gcc2 are at odds with the
objectives of many in the community who have done lots of hacking and
improvement over the years.  GCC is part of the FSF's publicity for the
GNU project, as well as being the GNU system's compiler, so stability
is paramount for them.  On the other hand, Cygnus, the Linux folks,
the pgcc folks, the Fortran folks and many others have done
development work which has not yet gone into the GCC2 tree despite
years of efforts to make it possible.

This situation has resulted in a lot of strong words on the gcc2
mailing list which really is a shame since at the heart we all want
the same thing: the continued success of gcc, the FSF, and Free
Software in general.  Apart from ill will, this is leading to great
divergence which is increasingly making it harder for us all to work
together -- It is almost as if we each had a proprietary compiler!
Thus we are merging our efforts, building something that won't damage
the stability of gcc2, so that we can have the best of both worlds.

As you can see from the list below, we represent a diverse collection
of streams of GCC development.  These forks are painful and waste
time; we are bringing our efforts together to simplify the development
of new features.  We expect that the gcc2 and egcs communities will
continue to overlap to a great extent, since they're both working on
GCC and both working on Free Software.  All code will continue to be
assigned to the FSF exactly as before and will be passed on to the
gcc2 maintainers for ultimate inclusion into the gcc2 tree.

Because the two projects have different objectives, there will be
different sets of maintainers.  Provisionally we have agreed that Jim
Wilson is to act as the egcs maintainer and Jason Merrill as the
maintainer of the egcs C++ front end.  Craig Burley will continue to
maintain the Fortran front end code in both efforts.

What new features will be coming up soon?  There is such a backlog of
tested, un-merged-in features that we have been able to pick a useful
initial set:

    New alias analysis support from John F. Carr.
    g77 (with some performance patches).
    A C++ repository for G++.
    A new instruction scheduler from IBM Haifa.
    A regmove pass (2-address machine optimizations that in future
                    will help with compilation for the x86 and for now
                    will help with some RISC machines).

This will use the development snapshot of 3 August 97 as its base --
in other words we're not starting from the 18 month old gcc-2.7
release, but from a recent development snapshot with all the last 18
months' improvements, including major work on G++.

We plan an initial release for the end of August.  The second release
will include some subset of the following:
  global cse and partial redundancy elimination.
  live range splitting.
  More features of IBM Haifa's instruction scheduling,
      including software pipelining, and branch scheduling.
  sibling call opts.
  various new embedded targets.
  Further work on regmove.
The egcs mailing list at cygnus.com will be used to discuss and
prioritize these features.

How to join: send mail to
egcs-subscribe@egcs.cygnus.com.
That list is under majordomo.

We have a web page that describes the various mailing lists and has
this information at:
http://egcs.cygnus.com.

Alternatively, look for these releases as they spread through other
projects such as RTEMS, Linux, etc.

Come join us!
David Henkel-Wallace
(for the egcs members, who currently include, among others):
 Per Bothner
 Joe Buck
 Craig Burley
 John F. Carr
 Stan Cox
 David Edelsohn
 Kaveh R. Ghazi
 Richard Henderson
 David Henkel-Wallace
 Gordon Irlam
 Jakub Jelinek
 Kim Knuttila
 Gavin Koch
 Jeff Law
 Marc Lehmann
 H.J. Lu
 Jason Merrill
 Michael Meissner
 David S. Miller
 Toon Moene
 Jason Molenda
 Andreas Schwab
 Joel Sherrill
 Ian Lance Taylor
 Jim Wilson

Reunification

In April 1999, after a long period of behind-the-scenes negotiation, EGCS and GCC reunited, and EGCS was accepted as the GNU Project's official GCC.  At that time, GCC was renamed from "GNU C Compiler" to "GNU Compiler Collection", which conveniently has the same acronym. The first compiler version released after the reunification was GCC version 2.95.

Modern Times

GCC development these days follows a well-defined development plan under the able guidance of the GCC Steering Committee.

/* * Copyright(c) 2025 Shenzhen TP-LINK Technologies Co.Ltd. * * file work2.c * brief This is a sample of coding criterion for prime checking. * * author Lin Zihao * version 1.0.1 * date 25Jul31 * * history \arg 1.0.1, 25Jul31, Lin Zihao, Create the file. */ #include <stdio.h> #include <math.h> /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ #define MAX_RANGE 1000 /* 定义用户输入的最大范围 */ #define MIN_RANGE 2 /* 定义用户输入的最小范围 */ /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* EXTERN_PROTOTYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* LOCAL_PROTOTYPES */ /**************************************************************************************************/ static int is_prime(int x); /**************************************************************************************************/ /* VARIABLES */ /**************************************************************************************************/ /**************************************************************************************************/ /* LOCAL_FUNCTIONS */ /**************************************************************************************************/ /* * Function: is_prime * Purpose: Checks whether a given integer is a prime number。 * Parameters: * n - The integer to be checked * Return value: * Returns 1 if the number is prime, 0 otherwise. */ int is_prime(int x) { if (x <= 1) return 0; /* Numbers less than 2 are not prime */ double x1 = x; for (int i = 2; i <= sqrt(x1); i++) { /* Check only odd numbers up to n-1 */ if (0 == x % i) return 0; /* If divisible by any odd number, it's not prime */ } return 1; /* If no divisors found, the number is prime */ } /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ /**************************************************************************************************/ /* GLOBAL_FUNCTIONS */ /**************************************************************************************************/ /* * Function: main * Purpose: Entry point of the program. Demonstrates the use of the is_prime function. * Parameters: * n - Represents the upper limit of the range within which the program identifies. * dentifies. * count - An integer counter used to manage the formatting of the output. * Return value: * 0 on successful execution, non-zero otherwise. * Notes: * This function is for demonstration purposes only. */ int main() { int n, count = 0; // Define variables: n for user input limit, count for tracking output formatting printf("Enter a positive integer n: "); scanf("%d", &n); if(n <MIN_RANGE || n>MAX_RANGE){ /* Validate input range */ printf("Error!Please enter a number between 2 and 1000."); }else{ printf("Prime numbers up to %d are:\n", n); for (int i = 2; i <= n; i++) { if (is_prime(i)) { if (0 == count % 10 && 0 != count) { /* Start a new line after every 10 primes */ printf("\n"); } if (0 != count % 10) { /* Add comma separator except before the first number in a line */ printf(", "); } printf("%4d", i); /* Print prime number with 4-character width formatting */ count++; } } printf("\n"); } return 0; } ——tarting build... /usr/bin/gcc -fdiagnostics-color=always -g /home/linzihao/Code/test/coursework/work2/work2.c -o /home/linzihao/Code/test/coursework/work2/work2 /home/linzihao/Code/test/coursework/work2/work2.c: In function ‘is_prime’: /home/linzihao/Code/test/coursework/work2/work2.c:53:17: error: expected expression before ‘double’ double x1 = double(x); ^~~~~~ Build finished with error(s). * The terminal process failed to launch (exit code: -1). * Terminal will be reused by tasks, press any key to close it. * Executing task: C/C++: gcc 生成活动文件 Starting build... /usr/bin/gcc -fdiagnostics-color=always -g /home/linzihao/Code/test/coursework/work2/work2.c -o /home/linzihao/Code/test/coursework/work2/work2 /tmp/ccdeW4BH.o:在函数‘is_prime’中: /home/linzihao/Code/test/coursework/work2/work2.c:54:对‘sqrt’未定义的引用 collect2: error: ld returned 1 exit status Build finished with error(s). * The terminal process failed to launch (exit code: -1). * Terminal will be reused by tasks, press any key to close it. 运行报错如上,怎么回事
08-05
/* Copyright(c) 2008-2025 Shenzhen TP-LINK Technologies Co.Ltd. * * file bulk_mem_copy.c * brief This is the third programming exercise * * author Zhang Yixing * version 1.0.0 * date 25Jul30 * * history \arg 1.0.0, 25Jul30, Zhang Yixing. Finish the exercise. * */ #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/time.h> #include <time.h> /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ /* * brief Number of bytes aligned in memory. */ #define ALIGN_BYTES_DIGITS (4) #define TEST_ITERATIONS 10000 /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* VARIABLES */ /**************************************************************************************************/ /**************************************************************************************************/ /* FUNCTIONS */ /**************************************************************************************************/ /* * fn int bulk_mem_copy(unsigned char *to, unsigned char *from, int len) * brief New memory copy function. * details Considering memory alignment and memory overlap. * * param[in] *to Destination address. * param[in] *from Source address. * param[in] len The memory length of the copy. * * return flag Indicates whether the memory copy was successful. * */ int bulk_mem_copy(unsigned char *to, unsigned char *from, int len) { if (to == NULL || from == NULL || len <= 0) return -1; /* Consider memory overlap: copy from back to front. */ if (from < to && to < from + len) { unsigned char *dst_end = to + len - 1; unsigned char *src_end = from + len - 1; /* Consider memory alignment, copying in 32-bit units. */ uintptr_t tail_unaligned = (uintptr_t)(dst_end + 1) % ALIGN_BYTES_DIGITS; while (tail_unaligned-- && len--) { *dst_end-- = *src_end--; } unsigned int *dst_end_32 = (unsigned int *)(dst_end + 1 - ALIGN_BYTES_DIGITS); unsigned int *src_end_32 = (unsigned int *)(src_end + 1 - ALIGN_BYTES_DIGITS); while (len >= ALIGN_BYTES_DIGITS) { *dst_end_32-- = *src_end_32--; len -= ALIGN_BYTES_DIGITS; } dst_end = (unsigned char *)(dst_end_32 + 1) - 1; src_end = (unsigned char *)(src_end_32 + 1) - 1; while (len--) { *dst_end-- = *src_end--; } } else { uintptr_t head_unaligned = ALIGN_BYTES_DIGITS - (uintptr_t)to % ALIGN_BYTES_DIGITS; while (head_unaligned-- && len--) { *to++ = *from++; } unsigned int *dst_32 = (unsigned int *)to; unsigned int *src_32 = (unsigned int *)from; while (len >= ALIGN_BYTES_DIGITS) { *dst_32++ = *src_32++; len -= ALIGN_BYTES_DIGITS; } to = (unsigned char *)dst_32; from = (unsigned char *)src_32; while (len--) { *to++ = *from++; } } return 0; } 为这个函数,帮我生成功能测试,以及与原生memcpy的性能对比,用gtest
08-02
任务要求: 实现简单的 Socket 通信: 两台 PC 间使用 TCP 通信 客户端和服务器之间可以互相发送消息,收到之后在终端上打印出来 server.c:/* Copyright© 2025 Shenzhen TP-LINK Technologies Co.Ltd. * file server.c brief TCP server implementation for socket communication author [Your Name] version 1.0.1 date 2025-07-31 history \arg 1.0.1, 2025-07-31, [Your Name], Create the file. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> // /* DEFINES */ // #define PORT 8080 // Default port number #define BUFFER_SIZE 1024 // Communication buffer size #define MAX_PENDING_CONN 5 // Maximum pending connections #define SERVER_TERM_CMD “shutdown” // Server shutdown command // /* TYPES */ // // /* EXTERN_PROTOTYPES */ // // /* LOCAL_PROTOTYPES */ // // /* VARIABLES */ // // /* LOCAL_FUNCTIONS */ // // /* PUBLIC_FUNCTIONS */ // // /* GLOBAL_FUNCTIONS */ // /* Function: main Purpose: Entry point for TCP server application Parameters: None Return value: 0 on successful execution, non-zero otherwise. Notes: Listens for client connections and handles bidirectional communication */ int main() { int server_fd, new_socket; struct sockaddr_in address; int addrlen = sizeof(address); char buffer[BUFFER_SIZE] = {0}; // Create TCP socket if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } // Configure server address address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; // Accept any IP address.sin_port = htons(PORT); // Listen port // Bind socket to address if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("Bind failed"); close(server_fd); exit(EXIT_FAILURE); } // Start listening if (listen(server_fd, MAX_PENDING_CONN) < 0) { perror("Listen failed"); close(server_fd); exit(EXIT_FAILURE); } printf("Server listening on port %d\n", PORT); // Accept client connection if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("Accept failed"); close(server_fd); exit(EXIT_FAILURE); } printf("Client connected from %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port)); // Communication loop while (1) { // Receive client message memset(buffer, 0, BUFFER_SIZE); ssize_t valread = recv(new_socket, buffer, BUFFER_SIZE - 1, 0); if (valread <= 0) { if (valread == 0) { printf("Client disconnected\n"); } else { perror("Receive error"); } break; } printf("Client: %s\n", buffer); // Check for shutdown command if (strcmp(buffer, SERVER_TERM_CMD) == 0) { printf("Received shutdown command\n"); break; } // Send response to client printf("Server: "); if (fgets(buffer, BUFFER_SIZE, stdin) == NULL) { perror("Input error"); break; } buffer[strcspn(buffer, "\n")] = 0; // Remove newline if (send(new_socket, buffer, strlen(buffer), 0) < 0) { perror("Send failed"); break; } } close(new_socket); close(server_fd); printf("Server shutdown\n"); return 0; } client.c:/* Copyright© 2025 Shenzhen TP-LINK Technologies Co.Ltd. * file client.c brief TCP client implementation for socket communication author [Your Name] version 1.0.1 date 2025-07-31 history \arg 1.0.1, 2025-07-31, [Your Name], Create the file. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> // /* DEFINES */ // #define PORT 8080 // Default port number #define SERVER_IP “127.0.0.1” // Loopback address #define BUFFER_SIZE 1024 // Communication buffer size #define MAX_CONN_ATTEMPTS 5 // Maximum connection attempts #define CONN_RETRY_DELAY 2 // Retry delay in seconds // /* TYPES */ // // /* EXTERN_PROTOTYPES */ // // /* LOCAL_PROTOTYPES */ // // /* VARIABLES */ // // /* LOCAL_FUNCTIONS */ // // /* PUBLIC_FUNCTIONS */ // // /* GLOBAL_FUNCTIONS */ // /* Function: main Purpose: Entry point for TCP client application Parameters: None Return value: 0 on successful execution, non-zero otherwise. Notes: Establishes connection to server and handles bidirectional communication */ int main() { int sock = 0; struct sockaddr_in serv_addr; char buffer[BUFFER_SIZE] = {0}; int conn_attempts = 0; // Create TCP socket if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } // Configure server address structure serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // Convert IP address to binary format if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) { perror("Invalid address format"); close(sock); exit(EXIT_FAILURE); } // Attempt connection with retry logic while (conn_attempts < MAX_CONN_ATTEMPTS) { if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("Connection attempt failed"); conn_attempts++; sleep(CONN_RETRY_DELAY); } else { break; } } if (conn_attempts >= MAX_CONN_ATTEMPTS) { fprintf(stderr, "Failed to connect after %d attempts\n", MAX_CONN_ATTEMPTS); close(sock); exit(EXIT_FAILURE); } printf("Connected to server at %s:%d\n", SERVER_IP, PORT); // Communication loop while (1) { // Send message to server printf("Client: "); if (fgets(buffer, BUFFER_SIZE, stdin) == NULL) { perror("Input error"); break; } buffer[strcspn(buffer, "\n")] = 0; // Remove newline if (send(sock, buffer, strlen(buffer), 0) < 0) { perror("Send failed"); break; } // Check for exit command if (strcmp(buffer, "exit") == 0) { printf("Terminating connection\n"); break; } // Receive server response memset(buffer, 0, BUFFER_SIZE); ssize_t valread = recv(sock, buffer, BUFFER_SIZE - 1, 0); if (valread <= 0) { if (valread == 0) { printf("Server disconnected\n"); } else { perror("Receive error"); } break; } printf("Server: %s\n", buffer); } close(sock); return 0; } ——分析下代码有没有问题,需不需要makefile文件,怎么运行这两个代码文件实现通信,不用修改代码,在程序窗口把代码打印出来方便我复制
最新发布
08-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值