-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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/ld: relative #cgo LDFLAGS -L does not work #5428
Comments
Comment 2 by manoj.dayaram@moovweb.com: Sorry about that, I've gone ahead and made gosass public. |
Comment 3 by manoj.dayaram@moovweb.com: And yes, -L has a relative path. |
Comment 5 by manoj.dayaram@moovweb.com: Yeah, that made sense, but I guess what threw me off is that the packages compile fine when using go version 1.0.3 and below given the same scenario. I've made a few build scripts which have stopped working because of this. It wouldn't be the end of the world to add fixes to them, but this bug did strike me as a regression, so I figured I'd post an issue about it. |
Comment 6 by manoj.dayaram@moovweb.com: It looks like it has to do with the fact that my paths for LDFLAGS are relative. So prior in go1.0.3, it looks like relative paths were resolved relative to the directory the go file with the flags was in. In go1.1 it looks like relative paths are resolved relative to the location where 'go build' is being run. |
Comment 7 by manoj.dayaram@moovweb.com: This problem still exists using go1.1 |
Comment 8 by fritz@flux.io: I am experiencing the same problem. Of note: - rolling back to go1.0.3 fixes the issue - I do not run into the problem on the darwin_amd64 platform; only on the linux_amd64 platform. Having the LDFLAGS within cgo comments in a go src file in a package be interpreted differently depending on where the client build was started seems pretty problematic for creating packages that bundle and use external dso's via cgo. How should a developer arrange the files for such a package so that it can be reliably incorporated into a client go application using go's internal build system? In particular, the relative lib search paths needed to find the external dso when the package is built in its own directory vs. as part of a client build must necessarily be different? |
Owner changed to @ianlancetaylor. |
@r: yes, it definitely is. IIUC, internal linking: - records the path to required shared libraries in shared packages, - permits unresolved symbols in the program linked, and sets DT_NEEDED to include the recorded shared library name. External linking simply records the LDFLAGS and passes those along to the host linker. |
Comment 13 by manoj.dayaram@moovweb.com: Yep, problem still exists in linux go1.1.1 |
To clarify, what I get from the test case in the original issue is: > git clone git@github.com:hcatlin/libsass.git Cloning into 'libsass'... Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. |
Comment 19 by manoj.dayaram@moovweb.com: That's odd, the repo is public in github: https://github.com/hcatlin/libsass However, if the ssh method for git cloning doesn't work, you could try using https: replace each clone with the equivalent https url, so for libsass: git clone https://github.com/hcatlin/libsass Since the repo is public, it should not ask for any credentials. |
This is the problem: https://github.com/moovweb/gosass/blob/master/gosass.go #cgo LDFLAGS: -L../../clibs/lib -lsass -lstdc++ #cgo CFLAGS: -I../../clibs/include In the old world we used those to build the .o file that we eventually handed to the internal linker. We ran the external linker with those flags in the directory for the package. In the new world, we just remember them and hand them to the eventual final link command, which runs in a different directory. The only fix I see is to start parsing those strings in order to recognize and rewrite relative paths. I think that's too big a change for Go 1.2 at this point. Labels changed: added go1.3, removed go1.2. |
Would it be possible to temporarily change the working directly before and after the external linker is used? Because it works if you cd into the directory before running go install/build. It just fails when you are outside, like in ~/. Another alternative is support $VAR's. If there was a var for the package path, I could do something like: -L$PKGPATH/path/to/lib |
The old way invoked the system linker once for each package in the final binary. It could do each invocation in a different directory. The new way only has a single link, which can only have a single current directory. If we could magically figure out which directory to use for one package, we'd still have a problem if two different packages wanted magical treatment. |
Comment 24 by manoj.dayaram@moovweb.com: Sounds like the only way to do it would be to absolutize the LDFLAGS path upon entering each package before storing it for later use, which you're right, it would require parsing it at that time. Perhaps a simple option that might not require parsing it though, maybe store both the value of LDFLAGS as well as the current working directory associated with the package it came from, then join those together at link time? |
Issue #5319 has been merged into this issue. |
Comment 29 by camilo@buglabs.net: the problem with absolute paths is that it is not portable as you already know. On the other side, trying to use environment variables in CGO directives, inside the Go source, doesn't work either. So, we are not left with good workarounds at this moment. |
Comment 33 by camilo@buglabs.net: The problem with using $GOPATH is that it could contain multiple paths. |
Comment 34 by manoj.dayaram@moovweb.com: If relative paths can't be used, using shell variables could be a good compromise. It doesn't have to be $GOPATH specifically since, as mentioned, that could contain multiple paths, but allowing shell variable expansion for those flags would solve the problem, and arguable, be better than supporting relative paths. |
You can already do 'shell variable'-like things with the CGO_LDFLAGS environment variable, but it still requires people to set environment variables to install your package. Are we strongly opposed to copying all .a files from the source dir to build dir when compiling so we can just use same-directory paths (#cgo LDFLAGS: mylib.a)? |
Comment 36 by camilo@buglabs.net: In my use case, I don't really want to statically compile the library into my result binary. So, ideally for me, this should work exactly like it used to work in Go 1.0.3. Keeping backwards compatibility should be a priority in Go. |
Comment 37 by manoj.dayaram@moovweb.com: I have a very similar usecase as Camilo. We're dynamically linking libraries. Several of these individual libraries are used all over the Go code in different locations, however, we dump all the libraries into one "lib" folder that we provide relative paths to during the compile process with LDFLAGS. I would also like to mention that this affects "go test" as well. Perhaps obvious, I feel like a lot of the alternative solutions provided in this thread ignore the fact that the workflow for go test (specially for the "go test ..." command) would not work since it would require the command to be ran from within the directory using the cgo flags. If you're using two projects that use different cgo flags, then the alternatives fail. As mentioned, using relative paths worked fine in Go1.0.3. This issue has now been bumped for nearly three versions of Go since it's been filed because of its difficult to implement I presume. I work in software as well, I understand that sometimes things will take longer than expected, so this does not bother me that much. However, if we're going to talk about discarding this as an issue all together, please provide a more powerful alternative. As mentioned by others, using absolute paths is not a viable alternative as it forces the code to be non-portable. Please don't take features away without at least providing a new more powerful alternative. |
Comment 39 by christopher@climatemonkeys.com: Confirmed here as well that copying the static libraries from another directory into the build directory works with a simple "#cgo LDFLAGS". Is there a recommended elegant way to do this? Makefile? Shell script wrapper that executes either "go build" or "go install"? |
One possible approach in issue #7891. Labels changed: removed priority-later, toolbug. |
CL https://golang.org/cl/114640044 mentions this issue. |
by manoj.dayaram@moovweb.com:
The text was updated successfully, but these errors were encountered: