编译C++与Fortran
GCC 是 GNU 编译器集合(GNU Compiler Collection)的首字母缩写词。GNU 编译器集合包含 C,C++,Objective-C,Fortran,Java 和 Ada 的前端以及这些语言对应的库(libstdc++,libgcj,……)。
前面我们只涉及到 C 语言,那么如何用 gcc 编译其他语言呢?本节将简单介绍 C++ 和 Fortran 编译的例子。
首先我们尝试编译简单的 C++ 的经典程序 Hello world:
#include <iostream> int main(int argc,char *argv[]) { std::cout << "hello, world" << std::endl; return 0; }
将文件保存为‘hello.cpp’,用 gcc 编译,结果如下:
$ gcc -Wall hello.cpp -o hello /tmp/cch6oUy9.o: In function `__static_initialization_and_destruction_0(int, int)': hello.cpp:(.text+0x23): undefined reference to `std::ios_base::Init::Init()' /tmp/cch6oUy9.o: In function `__tcf_0': hello.cpp:(.text+0x6c): undefined reference to `std::ios_base::Init::~Init()' /tmp/cch6oUy9.o: In function `main': hello.cpp:(.text+0x8e): undefined reference to `std::cout' hello.cpp:(.text+0x93): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)' /tmp/cch6oUy9.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status
出错了!!而且错误还很多,很难看懂,这可怎么办呢?在解释之前,我们先试试下面的命令:
$ gcc -Wall hello.cpp -o hello -lstdc++
噫,加上-lstdc++选项后,编译竟然通过了,而且没有任何警告。运行程序,结果如下:
$ ./hello hello, world
通过上节,我们可以知道,-lstdc++ 选项用来通知链接器链接静态库 libstdc++.a。而从字面上可以看出,libstdc++.a 是C++ 的标准库,这样一来,上面的问题我们就不难理解了──编译 C++ 程序,需要链接 C++ 的函数库 libstdc++.a。
编译 C 的时候我们不需要指定 C 的函数库,为什么 C++ 要指定呢?这是由于早期 gcc 是指 GNU 的 C 语言编译器(GNU C Compiler),随着 C++,Fortran 等语言的加入,gcc的含义才变化成了 GNU 编译器集合(GNU Compiler Collection)。C作为 gcc 的原生语言,故编译时不需额外的选项。
不过幸运的是,GCC 包含专门为 C++ 、Fortran 等语言的编译器前端。于是,上面的例子,我们可以直接用如下命令编译:
$ g++ -Wall hello.cpp -o hello
GCC 的 C++ 前端是 g++,而 Fortran 的情况则有点复杂:在 gcc-4.0 版本之前,Fortran 前端是 g77,而gcc-4.0之后的版本对应的 Fortran 前端则改为 gfortran。下面我们先写一个简单的 Fortran 示例程序:
C Fortran 示例程序 PROGRAM HELLOWORLD WRITE(*,10) 10 FORMAT('hello, world') END PROGRAM HELLOWORLD
将文件保存‘hello.f’,用 GCC 的 Fortran 前端编译运行该文件
$ gfortran -Wall hello.f -o hello $ ./hello hello, world
我们已经知道,直接用 gcc 来编译 C++ 时,需要链接 C++ 标准库,那么用 gcc 编译 Fortran时,命令该怎么写呢?
$ gcc -Wall hello.f -o helloworld -lgfortran -lgfortranbegin
注意:上面这条命令与 gfortran 前端是等价的(g77 与此稍有不同)。其中库文件 libgfortranbegin.a (通过命令行选项 -lgfortranbegin 被调用) 包含运行和终止一个 Fortran 程序所必须的开始和退出代码。库文件 libgfortran.a 包含 Fortran 底层的输入输出等所需要的运行函数。
对于 g77 来说,下面两条命令是等价的(注意到 g77 对应的 gcc 是 4.0 之前的版本):
$ g77 -Wall hello.f -o hello $ gcc-3.4 -Wall hello.f -o hello -lfrtbegin -lg2c
命令行中的两个库文件分别包含 Fortran 的开始和退出代码以及 Fortran 底层的运行函数。