cgo and gotest and rpath

2,289 views
Skip to first unread message

Albert Strasheim

unread,
Jan 13, 2011, 12:40:02 AM1/13/11
to golang-nuts
Hello all

I have some library foo installed in a system location (e.g., /usr/
lib64) and in /opt/foo/lib (maybe a newer version).

I have a package that uses cgo and I would like to link my test binary
against foo in /opt/foo/lib and run with this library.

include $(GOROOT)/src/Make.inc
TARG=foo
CGOFILES=foo.go
CGO_CFLAGS=-I/opt/foo/include
CGO_LDFLAGS=-L/opt/foo/lib -lfoo
include $(GOROOT)/src/Make.pkg

What should I be setting in the package Makefile to pass "-r /opt/foo/
lib" to 6l when gotest builds 6.out?

(I think the linker ignores rpaths on darwin, so there I would still
have to set DYLD_LIBRARY_PATH in the environment before running the
test.)

Regards

Albert

Camilo Aguilar

unread,
Apr 25, 2014, 10:17:25 AM4/25/14
to golan...@googlegroups.com
I have exactly the same need. Any help is very much appreciated.

Ian Lance Taylor

unread,
Apr 25, 2014, 10:35:12 AM4/25/14
to Camilo Aguilar, golang-nuts
On Fri, Apr 25, 2014 at 7:17 AM, Camilo Aguilar
<camilo....@gmail.com> wrote:
> I have exactly the same need. Any help is very much appreciated.

The message to which you are replying is quite old and predates the go
tool. Please send a separate message in a new thread describing your
problem today. Thanks.

Ian
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Justin Israel

unread,
Apr 27, 2014, 6:20:40 AM4/27/14
to golan...@googlegroups.com, Camilo Aguilar
Just to expand on this, I am just now facing the same issue. Trying to CGO link against a library that depends on boost. 

$ export CGO_CPPFLAGS="-I/usr/local/Cellar/boost/1.53.0/include"
$ export CGO_LDFLAGS="-L/usr/local/Cellar/boost/1.53.0/lib"

# Fine
$ go build

# Fail
$ go test
dyld: Library not loaded: /usr/local/lib/libboost_thread-mt.dylib

# Fine
$ go test -c
$ DYLD_LIBRARY_PATH=/usr/local/Cellar/boost/1.53.0/lib ./foo.test
PASS

# Fail
$ export CGO_CPPFLAGS="-I/usr/local/Cellar/boost/1.53.0/include"
$ export CGO_LDFLAGS="-L/usr/local/Cellar/boost/1.53.0/lib -Wl,-rpath,/usr/local/Cellar/boost/1.53.0/lib"
$ go build
ld: -rpath can only be used when creating a dynamic final linked image
clang: error: linker command failed with exit code 1 (use -v to see invocation)


So I think the question (for me at least) is how to go about using rpath in the build so that DYLD_LIBRARY_PATH does not have to be set at runtime? 

Aram Hăvărneanu

unread,
Apr 27, 2014, 6:27:36 AM4/27/14
to Justin Israel, golang-nuts, Camilo Aguilar
Perhaps you can use something like

    -ldflags="-L/usr/local/Cellar/boost/1.53.0/lib -extldflags '--Wl,-rpath,/usr/local/Cellar/boost/1.53.0/lib'"

Untested.

--
Aram Hăvărneanu

Justin Israel

unread,
Apr 27, 2014, 7:24:09 AM4/27/14
to golan...@googlegroups.com, Justin Israel, Camilo Aguilar
Hmm. That at least finishes without error and looks like it is using a reasonable linker parameter, but it doesn't seem to take effect:

$ go test -c -ldflags="-extldflags '--Wl,-rpath,/usr/local/Cellar/boost/1.53.0/lib'"
$ $ otool -L *.test | grep boost
/usr/local/lib/libboost_thread-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/lib/libboost_system-mt.dylib (compatibility version 0.0.0, current version 0.0.0)

I will have to keep tinkering with it.

I can change the paths after the fact, on the test binary:

$ install_name_tool -change /usr/local/lib/libboost_thread-mt.dylib /usr/local/Cellar/boost/1.53.0/lib/libboost_thread-mt.dylib foo.test 
$ install_name_tool -change /usr/local/lib/libboost_system-mt.dylib /usr/local/Cellar/boost/1.53.0/lib/libboost_system-mt.dylib foo.test 
$ otool -L *.test | grep boost
/usr/local/Cellar/boost/1.53.0/lib/libboost_thread-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/local/Cellar/boost/1.53.0/lib/libboost_system-mt.dylib (compatibility version 0.0.0, current version 0.0.0)

$ ./foo.test
PASS

But I must be missing something in my build command/flags to get boost to properly link to this other location.

Carlos Castillo

unread,
Apr 27, 2014, 1:37:02 PM4/27/14
to golan...@googlegroups.com, Justin Israel, Camilo Aguilar
Do you have example code so the rest of us can follow along?

BTW, rpath on darwin is a little different than on other systems. By default it stores the absolute path to the library *in the library*, and copies that to the binary when linking. This is why when linking to the library in /usr/local/Cellar/boost/... your binary is still looking for a library in /usr/local/lib. For example: run "otool -L /usr/local/Cellar/boost/1.53.0/lib/libboost_thread-mt.dylib" and you will see: "/usr/local/lib/libboost_thread-mt.dylib", because that is what was "burned-in" to the library when it was built, and what is put into the resulting binaries when you build against it.

Homebrew by default builds boost with static libraries as well, why don't you use those instead? Then you won't have this problem, and upgrading/removing boost won't break your built binaries either.

Justin Israel

unread,
Apr 27, 2014, 4:21:06 PM4/27/14
to Carlos Castillo, golang-nuts, Camilo Aguilar
Ah good point. I suppose the workflow would be different on linux where rpath is handled differently. I should try the static linking of boost. 

I don't really have example code to share since it's just empty files that contain CGO directives linking to a library that has a boost dependency (it is for the imagebufalgo package in my OpenImageIO bindings: https://github.com/justinfx/openimageigo). I've just now started to wrap the imagebufalgo and realized it required boost. If it helps, I can post those mostly empty files (imagebufalgo.go, imagebufalgo_test.go, algo.h, algo.cpp).

The question would be the same for other libraries that use CGO to link against external libraries, such as https://github.com/gographics/imagick/ which links against libMagickWand/libMagickCore

Carlos Castillo

unread,
Apr 27, 2014, 5:19:30 PM4/27/14
to golan...@googlegroups.com, Carlos Castillo, Camilo Aguilar
I was able to build the following with no problems on my OSX machine (10.9), using go at tip, and the most recent version of boost from homebrew (1.55.0_1): http://play.golang.org/p/sXrGzDS7Rb

The output from otool shows generated binaries point the the /usr/local/lib/libboost*.dylib versions of the libraries, and the program built and ran without error.

I didn't need to specify any DYLD_LIBRARY_PATH, or rpath, or even pass "-L" flags since by default the libraries installed by homebrew are symlinked to /usr/local/lib, and the internal (absolute) paths point there. That should also survive upgrades since the symlinks would be updated to point to the new locations. The only thing I needed to specify was the library to link in (-lboost_thread-mt)

Justin Israel

unread,
Apr 27, 2014, 5:45:43 PM4/27/14
to Carlos Castillo, golang-nuts, Camilo Aguilar
No you are totally right in that respect. That should work just fine because your libraries are in a standard location. But I am talking about the situation where libraries are located elsewhere and I have to provide the paths. In that case, I was having trouble getting it to work without needing DYLD_LIBRARY_PATH

I just tried the previously mentioned rpath flags on my linux box, now that I am at work, and I don't seem to be getting an rpath set either. 



Justin Israel

unread,
Apr 27, 2014, 5:55:04 PM4/27/14
to Carlos Castillo, golang-nuts, Camilo Aguilar
So using the similar example you gave, but on linux:

$ export CGO_LDFLAGS="-L/path/to/other/boost-1.46.1/lib" 
$ go build -o boosty -x -v -ldflags="-extldflags '--Wl,-rpath,/path/to/other/boost-1.46.1/lib'"

In a clean shell:

$ ldd boosty | grep boost
libboost_thread.so.1.46.1 => /usr/lib/libboost_thread.so.1.46.1 (0x00007fd564650000)

So it doesn't seem to be using the rpath. I would have to make sure my env uses LD_LIBRARY_PATH

$ export LD_LIBRARY_PATH=/path/to/other/boost-1.46.1/lib
$ ldd boosty | grep boost
libboost_thread.so.1.46.1 => /path/to/other/boost-1.46.1/lib/libboost_thread.so.1.46.1 (0x00007f1a39208000)



Jeff Mickey

unread,
Oct 8, 2015, 11:59:53 PM10/8/15
to Justin Israel, Carlos Castillo, golang-nuts, Camilo Aguilar
I know this is a long shot.. but: did you ever find an answer to this bug? Compiling go for a distro with very unique library paths and need to override rpaths.

  //  mickey

Michael Hudson-Doyle

unread,
Oct 9, 2015, 10:55:39 PM10/9/15
to Jeff Mickey, Justin Israel, Carlos Castillo, golang-nuts, Camilo Aguilar
I haven't read the old thread, but you should be able to override
rpath with -ldflags "-r $whatever".

Cheers,
mwh

Jeff Mickey

unread,
Oct 11, 2015, 6:02:17 PM10/11/15
to Michael Hudson-Doyle, Justin Israel, Carlos Castillo, golang-nuts, Camilo Aguilar
Yes, I'm using an -r $whatever setting, but this doesn't work for
cgo. All the other tools have the correct paths. cgo just has an empty
reference to libgcc_s.so, whereas all the other paths are correct.

I'm packaging go for guix, a nix-like linux os where all the libs are in
extremely non-standand locations. It seems like CGO_LDFLAGS doesn't
stick during make.bash.

// mickey

* Michael Hudson-Doyle <michael...@canonical.com> [2015-10-09 19:55]:

Michael Hudson-Doyle

unread,
Oct 11, 2015, 6:21:36 PM10/11/15
to Jeff Mickey, golang-nuts
Can you post the command you're executing, what happens and what you
expect to happen?

Are you saying that the cgo binary itself has a broken rpath? On my
system cgo is statically linked.

Or is it something about setting rpath while invoking cgo? AIUI rpath
as a concept applies to executables and shared libraries, which cgo
doesn't produce. So I don't understand that side either.

(As an aside, a distribution that puts libs in non-standard locations
but doesn't change the dynamic linker default search path sounds ...
unfriendly?)

Cheers,
mwh
Reply all
Reply to author
Forward
0 new messages