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.
Note that gccgo
is not the 6g
compiler; see
the Installing Go instructions for that
compiler.
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 a branch of the main gcc
code
repository: svn://gcc.gnu.org/svn/gcc/branches/gccgo
.
Building gccgo
is just like building gcc
with one additional option. 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).
A number of prerequisites are required to build gcc
, as
described on the gcc
web site. If those are all
available, then a typical build and install sequence would look like
this:
svn checkout svn://gcc.gnu.org/svn/gcc/branches/gccgo gccgo mkdir objdir cd objdir ../gccgo/configure --enable-languages=c,c++,go make make install
The gccgo
compiler works like other gcc frontends.
To compile a file:
gccgo -c file.go
That produces file.o
. To link files together to form an
executable:
gccgo -o file file.o
To run the resulting file, you will need to tell the program where to
find the Go runtime library. This can be done either by setting
LD_LIBRARY_PATH
in your environment:
LD_LIBRARY_PATH=/usr/lib/gcc/MACHINE/VERSION
or by passing a -Wl,-R
option when you link:
gccgo -o file file.o -Wl,-R,/usr/lib/gcc/MACHINE/VERSION
or you can use the -static-libgo
link-time option to link
statically against libgo, or you can do a fully static link (static
linking is the default for the 6l
Go linker). On most
systems, a static link will look something like:
gccgo -o file file.o -static -L /usr/lib/nptl -lgobegin -lgo -lpthread
You may get a warning about not creating an .eh_frame_hdr
section; this has nothing to do with Go, and may be ignored. In the
future the requirement of explicitly specifying
-L /usr/lib/nptl -lgobegin -lgo -lpthread
may be removed.
When you compile a file which 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.
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.
FILE.gox
FILE.o
libFILE.so
libFILE.a
FILE.gox
, when used, will typically contain
nothing but export data. This can be generated from
FILE.o
via
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.
The gccgo
compiler does not currently (2009-11-06) 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 -c mypackage.go # Exports mypackage gccgo -c main.go # Imports mypackage gccgo -o main main.o mypackage.o # Explicitly links with mypackage.o
Some Go features are not yet implemented in gccgo
. As of
2009-11-06, the following are not implemented:
If you use the -g
option when you compile, you can run
gdb
on your executable. The debugger doesn't (yet)
know anything about Go. However, 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
will show up as pointers to structures; to see the value
print *stringvar
. In general Go strings, maps, channels
and interfaces are always represented as C pointers.
When using gccgo
there is limited interoperability with C,
or with C++ code compiled using extern "C"
.
Basic types map directly: an int
in Go is an int
in C, 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.
The Go string
type is a pointer to a structure.
The current definition is
(this is expected to change):
struct __go_string { size_t __length; unsigned char __data[]; };
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.
A slice in Go is a structure. The current definition is (this is subject to change):
struct __go_slice { void *__values; int __count; int __capacity; };
The type of a Go function with no receiver is equivalent to a C function whose parameter types are equivalent. When a Go function returns more than one value, the C function returns a struct. For example, these functions have equivalent types:
func GoFunction(int) (int, float) struct { int i; float f; } CFunction(int)
A pointer to a Go function is equivalent to a pointer to a C function when the functions have equivalent types.
Go interface
, channel
, and map
types have no corresponding C type (they roughly correspond to pointers
to structs in C, but the structs are deliberately undocumented). C
enum
types correspond to some Go 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.
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.
Go code can call C functions directly using a Go extension implemented
in gccgo
: a function declaration may be followed by
__asm__("NAME")
. For example, here is how the C function
open
can be declared in Go:
func c_open(name *byte, mode int, perm int) int __asm__ ("open");
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 os
package):
var name = [4]byte{'f', 'o', 'o', 0}; i := c_open(&name[0], os.O_RDONLY, 0);
(this serves as an example only, to open a file in Go please use Go's
os.Open
function instead).
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
package.Functionname
. To call it from C you must set the
name using a gcc
extension similar to the gccgo
extension.
extern int go_function(int) __asm__ ("mypackage.Function");
The Go version of gcc
supports automatically generating
Go declarations from C code. The facility is rather awkward at present,
and a better mechanism is under development.
Compile your C code as usual, but replace -c
with
-S -ggo
. The result will be an assembler file
with a .s
extension. This assembler file will contain
comments beginning with #GO. Those comments are declarations in the Go
language for the C types, variables and functions declared in the C code.
C types which can not be represented in Go will contain the string INVALID.
Unsupported macro definitions will be recorded as unknowndefine
,
and uses of #undef
will be recorded as undef
.
So it is very approximately possible to get Go code by running
gcc -S -ggo foo.c grep '#GO' foo.s | grep -v INVALID | grep -v unknowndefine | grep -v undef > foo.go
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.