...

设置并使用gccgo

This document explains how to use gccgo, a compiler for the Go language. The gccgo compiler is a new frontend for GCC, the widely used GNU compiler. Although the frontend itself is under a BSD-style license, gccgo is normally used as part of GCC and is then covered by the GNU General Public License (the license covers gccgo itself as part of GCC; it does not cover code generated by gccgo).

本文档说明了如何使用Go语言的编译器gccgo。gccgo编译器是GCC的一个新前端, 它一个使用广泛的GNU编译器。尽管该前端本身使用BSD风格的授权,但gccgo一般作为GCC的一部分使用, 因此它会被GNU通用公共许可所覆盖 (该许可只会将gccgo本身作为GCC的一部分来覆盖,它不会覆盖由gccgo生成的代码)。

Note that gccgo is not the gc compiler; see the Installing Go instructions for that compiler.

请注意gccgo并非 gc 编译器,有关该编译器的说明, 见安装Go

Releases

发行版

The simplest way to install gccgo is to install a GCC binary release built to include Go support. GCC binary releases are available from various websites and are typically included as part of GNU/Linux distributions. We expect that most people who build these binaries will include Go support.

安装gccgo最简单的方式就是安装包含Go支持的GCC二进制发行版。GCC二进制发行版在 各种网站上均有提供, 它一般会作为GNU/Linux发行版的一部分包含在其中。 我们希望构建这些二进制包的大部分人会加入Go的支持。

The GCC 4.7.1 release and all later 4.7 releases include a complete Go 1 compiler and libraries.

GCC 4.7.1和所有比4.7更新的发行版都包含有完整的Go 1编译器和库。

Due to timing, the GCC 4.8.0 and 4.8.1 releases are close to but not identical to Go 1.1. The GCC 4.8.2 release includes a complete Go 1.1.2 implementation.

由于时间关系,虽然GCC 4.8.0和4.8.1发行版都与Go 1.1很接近,但并不完全相同。 GCC 4.8.2发行版预计会包含完整的Go 1.1.1实现。

The GCC 4.9 releases include a complete Go 1.2 implementation.

The GCC 4.9 releases include a complete Go 1.2 implementation. GCC 4.9 发行版包含了完整的 Go 1.2 实现。

Source code

源码

If you cannot use a release, or prefer to build gccgo for yourself, the gccgo source code is accessible via Subversion. The GCC web site has instructions for getting the GCC source code. The gccgo source code is included. As a convenience, a stable version of the Go support is available in a branch of the main GCC code repository: svn://gcc.gnu.org/svn/gcc/branches/gccgo. This branch is periodically updated with stable Go compiler sources.

若你无法使用发行版,或更想自己去编译gccgo,那么gccgo的源码可通过Subversion访问。 GCC网站上有如何获取GCC源码的说明。 gccgo的源码已含于其中。为方便起见,Go支持的稳定版在主GCC代码仓库的分支 svn://gcc.gnu.org/svn/gcc/branches/gccgo 中亦有提供。 该分支跟随Go编译器的稳定版源码定期更新。

Note that although gcc.gnu.org is the most convenient way to get the source code for the Go frontend, it is not where the master sources live. If you want to contribute changes to the Go frontend compiler, see Contributing to gccgo.

Note that although gcc.gnu.org is the most convenient way to get the source code for the Go frontend, it is not where the master sources live. If you want to contribute changes to the Go frontend compiler, see Contributing to gccgo. 请注意,尽管 gcc.gnu.org 是获取Go前端源码最简便的方式, 但它并不是主源所在的地方。如果你想为Go前端编译器贡献更改, 请参阅为gccgo做贡献

Building

构建

Building gccgo is just like building GCC with one or two additional options. See the instructions on the gcc web site. When you run configure, add the option --enable-languages=c,c++,go (along with other languages you may want to build). If you are targeting a 32-bit x86, then you will want to build gccgo to default to supporting locked compare and exchange instructions; do this by also using the configure option --with-arch=i586 (or a newer architecture, depending on where you need your programs to run). If you are targeting a 64-bit x86, but sometimes want to use the -m32 option, then use the configure option --with-arch-32=i586.

构建gccgo就像构建GCC加上一两个选项一样, 具体见gcc网站上的说明。 当你运行 configure 时,请加上 --enable-languages=c,c++,go 选项(也许你想连同其它语言一起构建)。若你的目标平台为32位的x86架构, 那么你会想构建gccgo默认支持锁定的比较与交换指令;也可以使用 configure--with-arch=i586(或更新的架构,这取决于你的程序想要在哪运行)选项来达到目的。 若你的目标平台为64位的x86架构,但有时想使用 -m32 选项,那么请使用 configure--with-arch-32=i586 选项。

Gold

On x86 GNU/Linux systems the gccgo compiler is able to use a small discontiguous stack for goroutines. This permits programs to run many more goroutines, since each goroutine can use a relatively small stack. Doing this requires using the gold linker version 2.22 or later. You can either install GNU binutils 2.22 or later, or you can build gold yourself.

在x86 GNU/Linux系统上,gccgo编译器可为Go程使用小型的不连续栈。这允许程序运行更多的Go程, 直到每个Go程都可使用相对较小的栈。要这样需使用2.22或更高版本的gold连接器。你也可以安装GNU binutils 2.22或更新的版本,或者自己构建gold。

To build gold yourself, build the GNU binutils, using --enable-gold=default when you run the configure script. Before building, you must install the flex and bison packages. A typical sequence would look like this (you can replace /opt/gold with any directory to which you have write access):

要自己构建gold,需构建GNU binutils,当你运行 configure 脚本时,请使用 --enable-gold=default 选项。在构建之前, 你必须安装flex与bison包。典型的顺序看起来像这样(你可以将 /opt/gold 替换为你想写入访问的任何目录):

cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src login
[password is "anoncvs"]
[The next command will create a directory named src, not binutils]
cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co binutils
mkdir binutils-objdir
cd binutils-objdir
../src/configure --enable-gold=default --prefix=/opt/gold
make
make install

However you install gold, when you configure gccgo, use the option --with-ld=GOLD_BINARY.

无论你是否安装gold,在配置gccgo时,都需要使用 --with-ld=GOLD_BINARY选项。

Prerequisites

先决条件

A number of prerequisites are required to build GCC, as described on the gcc web site. It is important to install all the prerequisites before running the gcc configure script. The prerequisite libraries can be conveniently downloaded using the script contrib/download_prerequisites in the GCC sources.

构建GCC需满足一些前提,其描述在gcc网站上。 在运行GCC的 configure 脚本前,安装好所有的依赖库是很重要的,你可以用GCC源码中的 contrib/download_prerequisites 脚本来方便地下载它们。

Build commands

构建命令

Once all the prerequisites are installed, then a typical build and install sequence would look like this (only use the --with-ld option if you are using the gold linker as described above):

Once all the prerequisites are installed, then a typical build and install sequence would look like this (only use the --with-ld option if you are using the gold linker as described above): 所有的先决条件一旦设置好后,典型的构建安装顺序看起来就像这样(若你使用上面叙述的gold连接器, 只需使用 --with-ld 选项):

svn checkout svn://gcc.gnu.org/svn/gcc/branches/gccgo gccgo
mkdir objdir
cd objdir
../gccgo/configure --prefix=/opt/gccgo --enable-languages=c,c++,go --with-ld=/opt/gold/bin/ld
make
make install

A note on Ubuntu

Ubuntu上的注意事项

Current versions of Ubuntu and versions of GCC before 4.8 disagree on where system libraries and header files are found. This is not a gccgo issue. When building older versions of GCC, setting these environment variables while configuring and building gccgo may fix the problem.

Ubuntu与gcc的当前版本在寻找系统库与头文件方面不一致。这并不是gccgo的问题, 而我们希望它尽快解决。在此之前,当配置并构建gccgo时,设置以下环境变量即可修复此问题。

LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
CPLUS_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
export LIBRARY_PATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH

使用gccgo

The gccgo compiler works like other gcc frontends. The gccgo installation does not currently include a version of the go command. However if you have the go command from an installation of the gc compiler, you can use it with gccgo by passing the option -compiler gccgo to go build or go install or go test.

gccgo编译器像其它GCC前端一样工作。gccgo的安装当前并不包含 go 命令的版本。 然而,若你从 gc 编译器的安装中获得了 go 命令,便可通过向 go buildgo installgo test 传递 -compiler gccgo 选项来使用gccgo。

To compile a file without using the go command:

不使用 go 命令来编译文件:

gccgo -c file.go

That produces file.o. To link files together to form an executable:

它将产生 file.o 文件。将文件链接到一起形成可执行文件:

gccgo -o file file.o

To run the resulting file, you will need to tell the program where to find the compiled Go packages. There are a few ways to do this:

要运行产生的文件,你需要告诉该程序从哪找到已编译的Go包。这有几种方式:

  • Set the LD_LIBRARY_PATH environment variable:

    LD_LIBRARY_PATH=${prefix}/lib/gcc/MACHINE/VERSION
    [or]
    LD_LIBRARY_PATH=${prefix}/lib64/gcc/MACHINE/VERSION
    export LD_LIBRARY_PATH
    

    Here ${prefix} is the --prefix option used when building gccgo. For a binary install this is normally /usr. Whether to use lib or lib64 depends on the target. Typically lib64 is correct for x86_64 systems, and lib is correct for other systems. The idea is to name the directory where libgo.so is found.

  • Passing a -Wl,-R option when you link:

    gccgo -o file file.o -Wl,-R,${prefix}/lib/gcc/MACHINE/VERSION
    [or]
    gccgo -o file file.o -Wl,-R,${prefix}/lib64/gcc/MACHINE/VERSION
    
  • Use the -static-libgo option to link statically against the compiled packages.

  • Use the -static option to do a fully static link (the default for the gc compiler).

Options

选项

The gccgo compiler supports all GCC options that are language independent, notably the -O and -g options.

gccgo编译器支持所有语言独立的GCC选项。如 -O-g 选项。

The -fgo-prefix=PREFIX option may be used to set a unique prefix for the package being compiled. This option is intended for use with large programs that contain many packages, in order to allow multiple packages to use the same identifier as the package name. The PREFIX may be any string; a good choice for the string is the directory where the package will be installed.

-fgo-prefix=PREFIX 选项可为已编译的包设置唯一的前缀 该选项用于包含许多包的大型程序,以允许多个包使用相同的标识符作为包名。 PREFIX 可为任何字符串,将包会被安装到的目录作为该字符串是个不错的选择。

The -I and -L options, which are synonyms for the compiler, may be used to set the search path for finding imports.

-I-L 选项对编译器来说是一样的,它可用于设置寻找导入的搜索路径。

Imports

导入

When you compile a file that exports something, the export information will be stored directly in the object file. When you import a package, you must tell gccgo how to find the file.

当你在编译导入了一些东西的文件时,导入信息将被直接存储在对象文件中。当你导入一个包时, 你必须告诉gccgo如何找到该文件。

When you import the package FILE with gccgo, it will look for the import data in the following files, and use the first one that it finds.

当你使用gccgo导入 FILE 包时,它将在以下文件中寻找导入数据,并使用找到的第一个文件。

FILE.gox, when used, will typically contain nothing but export data. This can be generated from FILE.o via

FILE.gox 被使用时,除导入数据外,一般不包含任何其它数据。 该文件可通过以下命令从 FILE.o 中生成。

objcopy -j .go_export FILE.o FILE.gox

The gccgo compiler will look in the current directory for import files. In more complex scenarios you may pass the -I or -L option to gccgo. Both options take directories to search. The -L option is also passed to the linker.

gccgo编译器会在当前目录中寻找导入文件。在更复杂的情况下, 你可以向gccgo传递 -I-L 选项。二者都会获取搜索目录。-L 选项也可传递至连接器。

The gccgo compiler does not currently (2013-06-20) record the file name of imported packages in the object file. You must arrange for the imported data to be linked into the program.

gccgo编译器当前(2013-06-20)还不能记录对象文件中已导入包的文件名。 你必须为链接到程序的导入数据进行安排。

gccgo -c mypackage.go              # Exports mypackage
gccgo -c main.go                   # Imports mypackage
gccgo -o main main.o mypackage.o   # Explicitly links with mypackage.o

调试

If you use the -g option when you compile, you can run gdb on your executable. The debugger has only limited knowledge about Go. You can set breakpoints, single-step, etc. You can print variables, but they will be printed as though they had C/C++ types. For numeric types this doesn't matter. Go strings and interfaces will show up as two-element structures. Go maps and channels are always represented as C pointers to run-time structures.

若你在编译时使用了 -g 选项,亦可以在你的可执行文件上运行 gdb。 该调试器对Go只有有限的支持。你可以设置断点,单步执行等等。你可以打印变量, 但它们将被当作C/C++的类型打印。对于数值类型,这当然没问题。但对于Go的字符串和接口, 它门将作为双元素结构显示。Go的映射与信道总会被表示为指向运行时结构的指针。

C Interoperability

与C的互操作性

When using gccgo there is limited interoperability with C, or with C++ code compiled using extern "C".

对于C或使用 extern "C" 编译的C++代码,在使用gccgo时只有有限的互操作性,

Types

类型

Basic types map directly: an int in Go is an int in C, an int32 is an int32_t, etc. Go byte is equivalent to C unsigned char. Pointers in Go are pointers in C. A Go struct is the same as C struct with the same fields and types.

基本类型将直接地进行映射,如Go的 int 即为C的 intint32 即为 int32_t 等等。Go的 byte 等价于C的unsigned char。Go中的指针即为C中的指针。Go的struct 与带相同字段和类型的C的 struct 相同。

The Go string type is currently defined as a two-element structure (this is subject to change):

Go的 string 类型当前被定义为双元素结构(本条目需要修改):

struct __go_string {
  const unsigned char *__data;
  int __length;
};

You can't pass arrays between C and Go. However, a pointer to an array in Go is equivalent to a C pointer to the equivalent of the element type. For example, Go *[10]int is equivalent to C int*, assuming that the C pointer does point to 10 elements.

你不能在C与Go之间传递数组。然而在Go中,指向数组的指针等价于在C中,指向等价元素类型的指针。 例如,Go的 *[10]int 等价于C的 int*,假定该C指针指向10个元素。

A slice in Go is a structure. The current definition is (this is subject to change):

Go中的切片为结构。当前定义为(本条目需要修改):

struct __go_slice {
  void *__values;
  int __count;
  int __capacity;
};

The type of a Go function is a pointer to a struct (this is subject to change). The first field in the struct points to the code of the function, which will be equivalent to a pointer to a C function whose parameter types are equivalent, with an additional trailing parameter. The trailing parameter is the closure, and the argument to pass is a pointer to the Go function struct. When a Go function returns more than one value, the C function returns a struct. For example, these functions are roughly equivalent:

Go不带接收器的函数类型等价于在C中形参类型等价的函数。当Go函数的返回值大于1个时, C函数返回一个结构。例如,以下函数拥有等价的类型:

func GoFunction(int) (int, float64)
struct { int i; float64 f; } CFunction(int, void*)

Go interface, channel, and map types have no corresponding C type (interface is a two-element struct and channel and map are pointers to structs in C, but the structs are deliberately undocumented). C enum types correspond to some integer type, but precisely which one is difficult to predict in general; use a cast. C union types have no corresponding Go type. C struct types containing bitfields have no corresponding Go type. C++ class types have no corresponding Go type.

Go的 interfacechannelmap 类型在C中并没有对应的类型(interface 为双元素结构, channelmap 在C中为指向结构的指针,但该结构有意不公开)。 C的 enum 类型对应于一些整数类型,但严格来说,要预测出是哪个通常很困难, 除非通过计算的方法。C的 union 类型在Go中并没有对应的类型。 在C中包含位字段的 struct 类型在Go中并没有对应的类型。C++的 class 类型在Go中并没有对应的类型。

Memory allocation is completely different between C and Go, as Go uses garbage collection. The exact guidelines in this area are undetermined, but it is likely that it will be permitted to pass a pointer to allocated memory from C to Go. The responsibility of eventually freeing the pointer will remain with C side, and of course if the C side frees the pointer while the Go side still has a copy the program will fail. When passing a pointer from Go to C, the Go function must retain a visible copy of it in some Go variable. Otherwise the Go garbage collector may delete the pointer while the C function is still using it.

在C与Go之间,内存的分配完全不同,因为Go使用垃圾收集机制。在此范围内, 准确的指导方针仍未定义,但将来很可能会允许C通过向Go传递指针来分配内存。 最终释放指针的责任将保留在C那边,当然,在Go这边仍有一份副本时,如果C那边释放该指针, 该程序就会失败。当从Go向C传递指针时,Go函数必须在一些的Go变量中,保留一份其可见的副本。 否则,在C函数仍在使用它时,Go垃圾回收会删除该指针。

Function names

函数名

Go code can call C functions directly using a Go extension implemented in gccgo: a function declaration may be preceded by //extern NAME. For example, here is how the C function open can be declared in Go:

Go代码可直接使用gccgo中Go的扩展实现来调用C函数:函数声明可前导 //extern NAME。例如,以下为如何在Go中声明C函数 open

//extern open
func c_open(name *byte, mode int, perm int) int

The C function naturally expects a NUL-terminated string, which in Go is equivalent to a pointer to an array (not a slice!) of byte with a terminating zero byte. So a sample call from Go would look like (after importing the syscall package):

C函数自然期望NUL终止字符串,它在Go中等价于终止零字节的指向 byte 数组(不是切片!)的指针。因此从Go的一个简单调用看起来像这样(在导入 syscall 包之后):

var name = [4]byte{'f', 'o', 'o', 0};
i := c_open(&name[0], syscall.O_RDONLY, 0);

(this serves as an example only, to open a file in Go please use Go's os.Open function instead).

(本服务只作为一个例子,要在Go中打开文件,请使用Go的 os.Open 函数代替。)

Note that if the C function can block, such as in a call to read, calling the C function may block the Go program. Unless you have a clear understanding of what you are doing, all calls between C and Go should be implemented through cgo or SWIG, as for the gc compiler.

注意,若该C函数可被阻塞(例如对 read 的调用),那么调用它可能会阻塞Go程序。 除非你很清楚自己在做什么,否则所有在C和Go之间的调用都应当用 gc 编译器 通过 cgo 或 SWIG 来实现。

The name of Go functions accessed from C is subject to change. At present the name of a Go function that does not have a receiver is prefix.package.Functionname. The prefix is set by the -fgo-prefix option used when the package is compiled; if the option is not used, the default is go. To call the function from C you must set the name using a GCC extension.

从C访问Go函数名的条目需要修改。目前无接收器的Go的函数名为 prefix.package.Functionname。在该包被编译后,该前缀通过 -fgo-prefix 选项设置;若该选项未被使用,则默认为 go。 要从C调用该函数,你必须使用一个GCC扩展来设置名字。

extern int go_function(int) __asm__ ("myprefix.mypackage.Function");

Automatic generation of Go declarations from C source code

C源码中Go声明的自动生成

The Go version of GCC supports automatically generating Go declarations from C code. The facility is rather awkward, and most users should use the cgo program with the -gccgo option instead.

Go的GCC版本支持从C代码自动生成Go声明。这个功能比较尴尬,大部分用户应当通过 -gccgo 选项使用cgo来代替。

Compile your C code as usual, and add the option -fdump-go-spec=FILENAME. This will create the file FILENAME as a side effect of the compilation. This file will contain Go declarations for the types, variables and functions declared in the C code. C types that can not be represented in Go will be recorded as comments in the Go code. The generated file will not have a package declaration, but can otherwise be compiled directly by gccgo.

像往常一样编译你的C代码,并添加 -fdump-go-spec=FILENAME 选项。 编译的副作用会创建文件 FILENAME。该文件将在C代码中包含Go的类型声明、 变量以及函数声明。不能在Go中表示的C类型将作为注释记录在Go代码中。所生成的文件将不会有 package 声明,但可另外通过gccgo直接编译。

This procedure is full of unstated caveats and restrictions and we make no guarantee that it will not change in the future. It is more useful as a starting point for real Go code than as a regular procedure.

该过程将充满未声明警告和限制,我们不保证它在将来不会更改。 将真实Go代码作为出发点比规则的生成步骤更有用。

RTEMS Port

RTEMS移植

The gccgo compiler has been ported to RTEMS. RTEMS is a real-time executive that provides a high performance environment for embedded applications on a range of processors and embedded hardware. The current gccgo port is for x86. The goal is to extend the port to most of the architectures supported by RTEMS. For more information on the port, as well as instructions on how to install it, please see this RTEMS Wiki page.

gccgo编译器已被移植到 RTEMSRTEMS 是在一定范围的处理器与嵌入式硬件上,为嵌入式应用提供高性能环境的实时执行系统。 当前gccgo有x86的移植。其目的是为大部分 RTEMS 所支持架构的移植进行扩展。关于此移植的更多信息及如何安装的说明,请访问 RTEMS维基页面