Relative paths for cgo shared objects

108 views
Skip to first unread message

Risto Saarelma

unread,
Jan 21, 2010, 1:24:09 PM1/21/10
to golang-nuts
I want to deploy a program linked to SDL with cgo on machines without
Go installed. This means that the binary and the shared objects
produced by cgo should just be droppable in a random directory, and
the binary should run when called in that directory.

The current cgo seems to force the linked shared objects to have
absolute paths. The path can be controlled with the env variable
CGOPKGPATH, but it looks like it must be either an absolute path or
end up within $GOROOT. Also, it seems that the cgo binaries always
expect to find libcgo.so within $GOROOT. If the user is going to drop
my binary in an arbitrary directory and expect it to run from there,
hardcoded paths are a problem.

One way to indicate you want a path to be relative is to prefix it
with "./". So I modified cgo to no longer force "./"-prefix
CGOPKGPATHs to be rooted and furthermore to expect libcgo.so from the
relative CGOPKGPATH instead of within $GOROOT when CGOPKGPATH has "./"-
prefix. My patch is here: http://codereview.appspot.com/186261

This is probably not the cleanest way to go about this, but works for
me. Are there better options or a chance of getting the patch
included?

Devon H. O'Dell

unread,
Jan 21, 2010, 1:31:21 PM1/21/10
to Risto Saarelma, golang-nuts
2010/1/21 Risto Saarelma <rsaa...@gmail.com>:

I think this is a valid concern. I'll review the patch in a bit.

To extend this point a bit, the generated go binary will require to
find any other imports inside GOROOT as well. I would suggest having a
wrapper script to run the application (this seems to be commonplace
for a lot of things these days).

--dho

nsf

unread,
Jan 25, 2010, 6:32:20 AM1/25/10
to golan...@googlegroups.com

There is also an another trick. 'cgo' creates file called _cgo_defun.c.
And this is a file where basically all dynamic linking information
hides. There are strings like:

#pragma dynld initcgo initcgo "/usr/lib/go/pkg/linux_386/libcgo.so"

Well, both

"$(GOROOT)/pkg/$(GOOS)_$(GOARCH)/$(CGOPKGPATH)/libcgo.so"
and
"$(GOROOT)/pkg/$(GOOS)_$(GOARCH)/$(CGOPKGPATH)/<yourlib>.so"

was composed here already.

But before compiling these file to an .8 you can simply search &
replace them to relative paths, like that:

"libcgo.so"
and
"<yourlib>.so"

And then when you'll link that package to your binary, the binary
contains the following LD entries:

[nsf @ golang]$ ldd 8.out
linux-gate.so.1 => (0xb7761000)
libcgo.so => not found
<yourlib>.so => not found

The last thing you need to do is just copy libcgo.so and <yourlib>.so
somewhere and tell LD linker where they are.

(I use current directory as an example):

[nsf @ golang]$ LD_LIBRARY_PATH=. ldd 8.out
linux-gate.so.1 => (0xb7777000)
libcgo.so => ./libcgo.so (0xb7774000)
<yourlib>.so => ./<yourlib>.so (0xb776f000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb772d000)
libm.so.6 => /lib/libm.so.6 (0xb7707000)
libc.so.6 => /lib/libc.so.6 (0xb75bf000)
/lib/ld-linux.so.2 (0xb7778000)

And it works! Well.. at least on linux.

Reply all
Reply to author
Forward
0 new messages