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/link: link failure caused by duplicated LDFLAGS passed to external linker #25930

Open
albertjin opened this Issue Jun 17, 2018 · 6 comments

Comments

Projects
None yet
3 participants
@albertjin

albertjin commented Jun 17, 2018

What version of Go are you using (go version)?

go1.10.3

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

macOS/amd64, doing cross compile for android/arm64

What did you do?

export GOOS=android
export GOARCH=arm64
export CC=/path/to/androd/gcc
export CXX=/path/to/androd/g++
export CGO_ENABLED=1
export CGO_LDFLAGS="-Wl,--version-script=/the/version-script/export.txt"
go build -buildmode=c-shared -ldflags="-s -w -v" -v -o libxxx.so foo/bar

What did you expect to see?

The shared library is generated without any error.

What did you see instead?

In the output line

0.19 host link: ...

"-Wl,--version-script=/the/version-script/export.txt" is repeated 4 time and there are 3 errors,

anonymous version tag cannot be combined with other version tags

Note that if the version script contains a version name, the error message is 'duplicate version tag xxx'.

@albertjin

This comment has been minimized.

albertjin commented Jun 17, 2018

For a quick fix, change the line in src/cmd/link/internal/ld/lib.go

	argv = append(argv, ldflag...)

as the following,

	{
		added := map[string]bool{}
		for _, s := range ldflag {
			if added[s] {
				continue
			}
			added[s] = true
			argv = append(argv, s)
		}
	}

@albertjin albertjin changed the title from Link failure caused by duplicated LDFLAGS passed to cgo linker to cmd/go: Link failure caused by duplicated LDFLAGS passed to cgo linker Jun 17, 2018

@albertjin albertjin changed the title from cmd/go: Link failure caused by duplicated LDFLAGS passed to cgo linker to cmd/link: Link failure caused by duplicated LDFLAGS passed to cgo linker Jun 17, 2018

@tklauser

This comment has been minimized.

Member

tklauser commented Jun 18, 2018

@ianlancetaylor ianlancetaylor changed the title from cmd/link: Link failure caused by duplicated LDFLAGS passed to cgo linker to cmd/link: link failure caused by duplicated LDFLAGS passed to cgo linker Jun 18, 2018

@ianlancetaylor ianlancetaylor changed the title from cmd/link: link failure caused by duplicated LDFLAGS passed to cgo linker to cmd/link: link failure caused by duplicated LDFLAGS passed to external linker Jun 18, 2018

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Jun 18, 2018

The suggested fix above is unfortunately too simple, as some options like -Bstatic may appear multiple times, and eliminating them would change the meaning of the link command. I don't know how to fix this without understanding the external linker options.

@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Jun 18, 2018

@albertjin

This comment has been minimized.

albertjin commented Jun 19, 2018

While analyzing the code for a safe fix, I realized that using #cgo directive in one .go file also solves the problem. This directive will not be replicated for each imported package, so there is just one after all auto generated //go:cgo_ldflag ... directives are merged back from each package.

It looks like this,

/*
#cgo LDFLAGS: "-Wl,--version-script=${SRCDIR}/export.txt"
//...
*/
#import "C"
// ...

Note that this flag is not in the white list and requires the following environment variable,

CGO_LDFLAGS_ALLOW="-Wl,--version-script=[a-zA-Z0-9+-_/.]+"

It seems that CGO_LDFLAGS is about a global configuration option of the Go toolchain. It should better not be used for each project.

@albertjin

This comment has been minimized.

albertjin commented Sep 24, 2018

@ianlancetaylor, I got a new idea for a general fix.

  1. Add a mark tag at the moment getting CGO_LDFLAGS array from env
  2. Remove the tag and clean up all duplicated arrays at linking

Note that the tag format is (a const uuid + length of the whole CGO_LDFLAGS array with the tag prefix).

patch_cgo_ldflags.diff.txt

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Sep 24, 2018

@albertjin For copyright reasons I prefer to look at patches submitted using as a PR or via Gerrit, to ensure that the CLA is signed.

It sounds like you are suggesting handling LDFLAGS that come from an environment variable differently than LDFLAGS listed in the file, and removing duplicates from the environment variable. That seems reasonable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment