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?
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
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.