Distributing binaries and linking to C libraries

1,026 views
Skip to first unread message

OmarShariffDontLikeIt

unread,
Apr 12, 2011, 5:35:23 AM4/12/11
to golang-nuts
Hi Everybody,

This might sound like a simple question and please bear with me as I'm
not particulary familiar with the details of how programs are compiled
with Go, and some of my usage of terminoligy may be incorrect, I'm
still learning :)

Basically, I understand that there are two ways to link libraries to
an executable; dynamically and statically linked. It is my
understanding that Go uses static linking. Is this true of Go packages
that interface with C libraries?

I ask because I would like to distribute the binary of my Go program,
which uses a Go package that uses a C library (via cgo). It is my
understanding that because Go doesn't suppoer dynamic linking that the
C Go package will contain the C library staticly linked, and that
users of my compiled Go program will not need to install this C
library themselves. e.g. Say I use the SQLite Go package; my users
will not have to install the SQLite library in order to use my
program.

Is this correct, or am I confusing the way Go compiled regular Go
packages with how Go links to C libraries via cgo? I've not been able
to find any documentation that clearly separates the two ways of
linking when compiling Go programs.

Can someone enlighten me?

Cheers!

Ben

William Waites

unread,
Apr 12, 2011, 9:46:03 AM4/12/11
to OmarShariffDontLikeIt, golang-nuts
* [2011-04-12 02:35:23 -0700] OmarShariffDontLikeIt <omarsharif...@gmail.com> �crit:

] I ask because I would like to distribute the binary of my Go program,


] which uses a Go package that uses a C library (via cgo).

It will depend on the linker flags you tell it to use. Doing
the usual way -lsomelib will result in a dependency on a shared
library. If you pass the library as libsomelib.a it should get
linked in statically.

Cheers,
-w
--
William Waites <mailto:w...@styx.org>
http://river.styx.org/ww/ <sip:w...@styx.org>
F4B3 39BF E775 CF42 0BAB 3DF0 BE40 A6DF B06F FD45

OmarShariffDontLikeIt

unread,
Apr 12, 2011, 11:44:57 AM4/12/11
to golang-nuts
ooh! wow, thats great, so it actually can do both? Thats awesome :)

I take it that you mean when I compile using cgo, I can use this flag?

On Apr 12, 2:46 pm, William Waites <w...@styx.org> wrote:
> * [2011-04-12 02:35:23 -0700] OmarShariffDontLikeIt <omarshariffdontlik...@gmail.com> crit:

Russ Cox

unread,
Apr 12, 2011, 2:46:23 PM4/12/11
to OmarShariffDontLikeIt, golang-nuts
This answer is only about the gc tools (6g, 6l, 8g, 8l, 5g, 5l).
The situation in gccgo is different.

William Waites's reply is wrong for gc.
It may be true of gccgo in certain modes, but it may not.

> Basically, I understand that there are two ways to link libraries to
> an executable; dynamically and statically linked. It is my
> understanding that Go uses static linking. Is this true of Go packages
> that interface with C libraries?

By default, the gc tools generate dynamically linked binaries
that refer to no dynamic libraries. That's not quite the same
thing as a statically linked binary, but it is close enough for
most purposes. Both have the property that you can distribute
the binary without any other files, and it will be able to run and
find all the code it needs (because it is all in that one file).

If you use cgo, the references to the C libraries turn into references
to the dynamic libraries that implement those functions, so
now the dynamically linked Go binary does have library references.
For example, if you use cgo with sqlite, the binary that uses it
will end up referring to /usr/lib/libsqlite.so.3 or whatever the file is.
To use the 6.out, a user will need the sqlite library installed too.
You can run "ldd 6.out" to get a list of the libraries that 6.out is
referring to and how the dynamic linker would resolve them if you
invoked 6.out on the current system with the current environment.

The way cgo runs now, it will only generate references to these
system libraries. An earlier version of cgo generated references
to other dynamic libraries that were tiny stubs generated during
the build process. Distributing binaries along with all the tiny stubs
was unwieldy, so we dropped that requirement.

Russ

William Waites

unread,
Apr 12, 2011, 3:00:20 PM4/12/11
to Russ Cox, OmarShariffDontLikeIt, golang-nuts
* [2011-04-12 14:46:23 -0400] Russ Cox <r...@golang.org> �crit:

] This answer is only about the gc tools (6g, 6l, 8g, 8l, 5g, 5l).


] The situation in gccgo is different.
]
] William Waites's reply is wrong for gc.
] It may be true of gccgo in certain modes, but it may not.

Apologies for the misinformation. If you pass libfoo.a with #cgo
LDFLAGS it will appear to work - I tested this - but when you try to
link an executable it will find that the archive hasn't actually been
included... However if you really want to you could ar -x the .a file
and add the resulting objects to CGO_OFILES. It still won't be a
static binary bit won't have dependencies on the extra shared
libraries that the original poster was worried about being present...

Russ Cox

unread,
Apr 12, 2011, 3:08:13 PM4/12/11
to William Waites, OmarShariffDontLikeIt, golang-nuts
> Apologies for the misinformation. If you pass libfoo.a with #cgo
> LDFLAGS it will appear to work - I tested this - but when you try to
> link an executable it will find that the archive hasn't actually been
> included... However if you really want to you could ar -x the .a file
> and add the resulting objects to CGO_OFILES. It still won't be a
> static binary bit won't have dependencies on the extra shared
> libraries that the original poster was worried about being present...

This may or may not work. CGO_OFILES is only guaranteed
to work for the gcc inputs that cgo itself generates. For anything
else it is a toss-up as to whether or not 6l/8l will be able to
link the object file into the program. It might work, but it might not,
or it might not tomorrow.

Russ

OmarShariffDontLikeIt

unread,
Apr 13, 2011, 8:41:16 AM4/13/11
to golang-nuts
Okay, so just to tie this off in a bow...

If I use the standard Go tools (I use make files and gomake and
goinstall for packages) this will create a a binary that contains
everything required by the user?

If I use cgo directly or gccgo I may have to specify that I want
libraries statically linked (with gccgo) and that that may be
alternatives that may or may not work if I use cgo on its own?

Is this correct?

Thanks for your helpful answers so far.

Cheers,
Ben

Russ Cox

unread,
Apr 13, 2011, 9:22:25 AM4/13/11
to OmarShariffDontLikeIt, golang-nuts
> If I use the standard Go tools (I use make files and gomake and
> goinstall for packages) this will create a a binary that contains
> everything required by the user?

Yes.

> If I use cgo directly or gccgo I may have to specify that I want
> libraries statically linked (with gccgo) and that that may be
> alternatives that may or may not work if I use cgo on its own?

Mostly yes.

Ultimately the answer is run ldd on your 6.out.
It will tell you what other files it depends on to run.

Russ

OmarShariffDontLikeIt

unread,
Apr 13, 2011, 9:33:00 AM4/13/11
to golang-nuts
Magic. Thanks very much!
Reply all
Reply to author
Forward
0 new messages