Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: linker issue when using clang with cgo on linux #11002

Closed
bodokaiser opened this issue May 30, 2015 · 20 comments
Closed

cmd/go: linker issue when using clang with cgo on linux #11002

bodokaiser opened this issue May 30, 2015 · 20 comments

Comments

@bodokaiser
Copy link

Hello,

1. What go version do I use?

go version go1.4.2 linux/amd64.

2. What operating system do I use?

alpine linux as official docker image build steps can be taken from this Dockerfile.

3. What did I do?

I want to compile a go project which uses cgo to do some work in opencv.
You can see the file which imports C.

4. What did I expect to happen?

That cgo works platform independent across unix* and between gcc and clang.

5. What happened instead?

/usr/bin/ld: -r and -shared may not be used together
clang-3.6: error: linker command failed with exit code 1 (use -v to see invocation)

6. What did I do as workaround?

I prefixed the go command with CC="" CXX="" so that go uses gcc instead of clang.

Possible related issues:

Best Bodo

@ianlancetaylor
Copy link
Contributor

What is the output of "pkg-config opencv"?

I assume you are getting this error when you run "go build". Can you add the output of "go build -x"?

Go is probably passing the -r option (as -Wl,-r), but I doubt it is passing the -shared option. Go 1.4 never passes a -shared option. We need to find out where -shared is coming from, and why.

I have no idea why GCC and clang would be behaving differently here. The error message is from the linker, and normally on GNU/Linux both GCC and clang use the same linker.

@ianlancetaylor ianlancetaylor changed the title linker issue when using clang with cgo on linux cmd/go: linker issue when using clang with cgo on linux May 30, 2015
@bodokaiser
Copy link
Author

pkg-config opencv returns nothing but

  • pkg-config --cflags opencv: -I/usr/local/include/opencv -I/usr/local/include
  • pkg-config --libs opencv: -L/usr/local/lib -lopencv_shape -lopencv_stitching -lopencv_objdetect -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_core -lopencv_hal

The output of go get -x github.com/bodokaiser/retina can be found here.

I don't think this relates directly as it is about the -shared flag but here was some flag difference between OS X and linux mentioned.

Also interesting a pastebin from someone else who had the same problem.

@ianlancetaylor
Copy link
Contributor

There is nothing in the way that the Go tool is invoking clang++ that should cause it to pass -shared to the linker.

Run go build -work. That will print out a value for WORK and leave files in that directory. Set the environment variable WORK to the value it prints out and run the failing command:

/usr/bin/clang++ -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -o $WORK/github.com/bodokaiser/retina/image/_obj/_all.o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_export.o $WORK/github.com/bodokaiser/retina/image/_obj/image.cgo2.o $WORK/github.com/bodokaiser/retina/image/_obj/image.cc.o -g -O2 -L/usr/local/lib -Wl,-r -nostdlib /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2/libgcc.a -Wl,--build-id=none

and add a -v option as well. It should fail the same way, but should show how clang++ invoked the linker. Show us the complete compiler output.

@bodokaiser
Copy link
Author

go build -x -v -work ./...
WORK=/tmp/go-build288906313
github.com/bodokaiser/retina/image
mkdir -p $WORK/github.com/bodokaiser/retina/image/_obj/
mkdir -p $WORK/github.com/bodokaiser/retina/
cd /srv/src/github.com/bodokaiser/retina/image
pkg-config --cflags opencv
pkg-config --libs opencv
CGO_LDFLAGS="-g" "-O2" "-L/usr/local/lib" "-lopencv_shape" "-lopencv_stitching" "-lopencv_objdetect" "-lopencv_superres" "-lopencv_videostab" "-lopencv_calib3d" "-lopencv_features2d" "-lopencv_highgui" "-lopencv_videoio" "-lopencv_imgcodecs" "-lopencv_video" "-lopencv_photo" "-lopencv_ml" "-lopencv_imgproc" "-lopencv_flann" "-lopencv_core" "-lopencv_hal" /usr/lib/go/pkg/tool/linux_amd64/cgo -objdir $WORK/github.com/bodokaiser/retina/image/_obj/ -- -I/usr/local/include/opencv -I/usr/local/include -I $WORK/github.com/bodokaiser/retina/image/_obj/ image.go
/usr/lib/go/pkg/tool/linux_amd64/6c -F -V -w -trimpath $WORK -I $WORK/github.com/bodokaiser/retina/image/_obj/ -I /usr/lib/go/pkg/linux_amd64 -o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_defun.6 -D GOOS_linux -D GOARCH_amd64 $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_defun.c
/usr/bin/clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -print-libgcc-file-name
/usr/bin/clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -I/usr/local/include/opencv -I/usr/local/include -I $WORK/github.com/bodokaiser/retina/image/_obj/ -g -O2 -o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_main.o -c $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_main.c
/usr/bin/clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -I/usr/local/include/opencv -I/usr/local/include -I $WORK/github.com/bodokaiser/retina/image/_obj/ -g -O2 -o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_export.o -c $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_export.c
/usr/bin/clang -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -I/usr/local/include/opencv -I/usr/local/include -I $WORK/github.com/bodokaiser/retina/image/_obj/ -g -O2 -o $WORK/github.com/bodokaiser/retina/image/_obj/image.cgo2.o -c $WORK/github.com/bodokaiser/retina/image/_obj/image.cgo2.c
/usr/bin/clang++ -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -I/usr/local/include/opencv -I/usr/local/include -I $WORK/github.com/bodokaiser/retina/image/_obj/ -g -O2 -std=c++11 -o $WORK/github.com/bodokaiser/retina/image/_obj/image.cc.o -c ./image.cc
/usr/bin/clang++ -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_.o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_main.o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_export.o $WORK/github.com/bodokaiser/retina/image/_obj/image.cgo2.o $WORK/github.com/bodokaiser/retina/image/_obj/image.cc.o -g -O2 -L/usr/local/lib -lopencv_shape -lopencv_stitching -lopencv_objdetect -lopencv_superres -lopencv_videostab -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_core -lopencv_hal
/usr/lib/go/pkg/tool/linux_amd64/cgo -objdir $WORK/github.com/bodokaiser/retina/image/_obj/ -dynimport $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_.o -dynout $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_import.c
/usr/lib/go/pkg/tool/linux_amd64/6c -F -V -w -trimpath $WORK -I $WORK/github.com/bodokaiser/retina/image/_obj/ -I /usr/lib/go/pkg/linux_amd64 -o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_import.6 -D GOOS_linux -D GOARCH_amd64 $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_import.c
/usr/bin/clang++ -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -o $WORK/github.com/bodokaiser/retina/image/_obj/_all.o $WORK/github.com/bodokaiser/retina/image/_obj/_cgo_export.o $WORK/github.com/bodokaiser/retina/image/_obj/image.cgo2.o $WORK/github.com/bodokaiser/retina/image/_obj/image.cc.o -g -O2 -L/usr/local/lib -Wl,-r -nostdlib /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2/libgcc.a -Wl,--build-id=none
# github.com/bodokaiser/retina/image
/usr/bin/ld: -r and -shared may not be used together
clang-3.6: error: linker command failed with exit code 1 (use -v to see invocation)

Still no -shared or -Bshareable there do you think this is a cgo issue or more a ld, clang one?

@ianlancetaylor
Copy link
Contributor

Thanks for that output, but what I need to see is the output of the final /usr/bin/clang++ line when you add the -v option to that line. That is, please do exactly what I asked for above. I don't need -v added to go build. I need it added to clang++. Thanks.

@bodokaiser
Copy link
Author

clang version 3.6.1 (tags/RELEASE_361/final)
Target: x86_64-alpine-linux-musl
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2
Found candidate GCC installation: /usr/lib/gcc/x86_64-alpine-linux-musl/4.9.2
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2
Candidate multilib: .;@m64
Selected multilib: .;@m64
clang-3.6: error: no such file or directory: '/tmp/go-build30000/github.com/bodokaiser/retina/image/_obj/_cgo_export.o'
clang-3.6: error: no such file or directory: '/tmp/go-build30000/github.com/bodokaiser/retina/image/_obj/image.cgo2.o'

@ianlancetaylor
Copy link
Contributor

Ah, right. Sorry. The Go linker will create a temporary file, but it won't save it. Bother.

OK, try creating a foo.o file from C, and run

/usr/bin/clang++ -v -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -o foo foo.o -g -O2 -L/usr/local/lib -Wl,-r -nostdlib /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2/libgcc.a -Wl,--build-id=none

@minux
Copy link
Member

minux commented May 31, 2015 via email

@bodokaiser
Copy link
Author

foo.c (if it matters)

#include <stdlib.h>

int main() {
    return 0;
}
/usr/bin/clang++ -v -I . -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -o foo foo.o 
-g -O2 -L/usr/local/lib -Wl,-r -nostdlib /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2/libgcc.a -Wl,--build-id=none
clang version 3.6.1 (tags/RELEASE_361/final)
Target: x86_64-alpine-linux-musl
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2
Found candidate GCC installation: /usr/lib/gcc/x86_64-alpine-linux-musl/4.9.2
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/bin/ld" -pie -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib/ld-musl-x86_64.so.1 -o foo -L/usr/local/lib -L/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2 -L/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2/../../../../x86_64-alpine-linux-musl/lib -L/usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2/../../.. -L/usr/bin/../lib -L/lib -L/usr/lib foo.o -r /usr/bin/../lib/gcc/x86_64-alpine-linux-musl/4.9.2/libgcc.a --build-id=none
/usr/bin/ld: -r and -shared may not be used together
clang-3.6: error: linker command failed with exit code 1 (use -v to see invocation)

@ianlancetaylor
Copy link
Contributor

Thanks. It's a very misleading message from the GNU linker. The actual problem is the -pie option. The GNU linker rejects using -pie -r.

Unfortunately the GNU linker has no way to turn off a -pie option. So we need to arrange for clang++ to not pass -pie to the linker. That means we need to find out why it is doing it and how to disable it.

The version of clang++ installed on my system (3.4) does not pass a -pie option. I can't find any evidence that LLVM likes to pass -pie on systems other than Android.

Does your system have a file /usr/lib/gcc/x86_64-alpine-linux-musl/4.9.2/specs ? If so, please add it here.

Otherwise I think we need to pass this to the LLVM developers. Why it LLVM passing -pie? How can we get it to stop?

@bodokaiser
Copy link
Author

vanila.spec

%include <hardenednossp.specs>
%include <hardenednopie.specs>
*esp_link_now:


*esp_link_relro:


*esp_cc1_strict_overflow:

hardenednopie.spec

*esp_cc1_pie:


*esp_options_pie:


*esp_link_pie_check:


*esp_link_pie:

hardenednopiessp.specs

%include <hardenednossp.specs>
%include <hardenednopie.specs>

hardenednossp.specs

*esp_cc1_ssp:


*esp_options_ssp:

Seems you are right that one of the specs are setting the pie option.

Am I right that the distributor of the gcc package adds the *.spec files?

@ianlancetaylor
Copy link
Contributor

I can't see the actual contents of the spec files--I think that github markdown syntax is hiding them. Is there some way to disable markdown?

Yes, in this case, it is the distributor of GCC who is added the spec files. GCC does not distribute spec files like this.

@bodokaiser
Copy link
Author

This is strange? Are you answering per email?

However thank you for your support! I will show this the distributor maybe this will save a good portion of time for further docker deploys :D

**vanila.spec**
%include <hardenednossp.specs>
%include <hardenednopie.specs>
*esp_link_now:


*esp_link_relro:


*esp_cc1_strict_overflow:


**hardenednopie.spec**
*esp_cc1_pie:


*esp_options_pie:


*esp_link_pie_check:


*esp_link_pie:

**hardenednopiessp.specs**
%include <hardenednossp.specs>
%include <hardenednopie.specs>


**hardenednossp.specs**
*esp_cc1_ssp:


*esp_options_ssp:

@ianlancetaylor
Copy link
Contributor

I'm not answering by e-mail, I'm looking at http://golang.org/issue/11002 and failing to see the contents of the spec files. I just see lines like "*esp_cc1_ssp:" but nothing else. Is that what the spec files look like?

@bodokaiser
Copy link
Author

Yes, they are just some lines of code. In the worst case you could still look it up on github

@ianlancetaylor
Copy link
Contributor

I would find it helpful to see those lines. Where would I look on github to find them? Thanks.

@bodokaiser
Copy link
Author

You do not use GitHub very often?

#11002 (comment)

@ianlancetaylor
Copy link
Contributor

I am not at all an expert user of github. When I go to that link, which is exactly what I have been doing, I see just '*' lines and %include lines. I do not see anything else. I would expect to see more text, along the lines of %{!-r:-pie} or something.

@bodokaiser
Copy link
Author

If you do not see more you are expecting too much. Each of the files only had about one to five lines.

One contains some option where "pie" is a part of so I guess this is the "bad one".

Am 01.06.2015 um 22:11 schrieb Ian Lance Taylor notifications@github.com:

I am not at all an expert user of github. When I go to that link, which is exactly what I have been doing, I see just '*' lines and %include lines. I do not see anything else. I would expect to see more text, along the lines of %{!-r:-pie} or something.


Reply to this email directly or view it on GitHub.

@ianlancetaylor
Copy link
Contributor

Ah, in that case, these files are not the problem.

I still don't know where the -pie option is coming from. I agree that it must be some distro-specific patch, though.

@golang golang locked and limited conversation to collaborators Jun 25, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants