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/link: external linking does not link dynamic libraries without cgo #42459

Open
FiloSottile opened this issue Nov 9, 2020 · 4 comments
Open

cmd/link: external linking does not link dynamic libraries without cgo #42459

FiloSottile opened this issue Nov 9, 2020 · 4 comments
Labels
Milestone

Comments

@FiloSottile
Copy link
Member

@FiloSottile FiloSottile commented Nov 9, 2020

https://golang.org/cl/232397 removes the cgo implementation from crypto/x509, which was preserved just for test purposes.

In doing so it seems to have broken external linking.

$ godev test crypto/x509 -ldflags=-linkmode=external
# crypto/x509.test
/Users/valsorda/go/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
Undefined symbols for architecture x86_64:
  "_CFArrayGetCount", referenced from:
      _crypto/x509/internal/macos.x509_CFArrayGetCount_trampoline in go.o
  "_CFArrayGetValueAtIndex", referenced from:
      _crypto/x509/internal/macos.x509_CFArrayGetValueAtIndex_trampoline in go.o
  "_CFDataGetBytePtr", referenced from:
      _crypto/x509/internal/macos.x509_CFDataGetBytePtr_trampoline in go.o
  "_CFDataGetLength", referenced from:
      _crypto/x509/internal/macos.x509_CFDataGetLength_trampoline in go.o
  "_CFDictionaryGetValueIfPresent", referenced from:
      _crypto/x509/internal/macos.x509_CFDictionaryGetValueIfPresent_trampoline in go.o
  "_CFEqual", referenced from:
      _crypto/x509/internal/macos.x509_CFEqual_trampoline in go.o
  "_CFNumberGetValue", referenced from:
      _crypto/x509/internal/macos.x509_CFNumberGetValue_trampoline in go.o
  "_CFRelease", referenced from:
      _crypto/x509/internal/macos.x509_CFRelease_trampoline in go.o
  "_CFStringCreateWithBytes", referenced from:
      _crypto/x509/internal/macos.x509_CFStringCreateWithBytes_trampoline in go.o
  "_SecItemExport", referenced from:
      _crypto/x509/internal/macos.x509_SecItemExport_trampoline in go.o
  "_SecPolicyCopyProperties", referenced from:
      _crypto/x509/internal/macos.x509_SecPolicyCopyProperties_trampoline in go.o
  "_SecTrustSettingsCopyCertificates", referenced from:
      _crypto/x509/internal/macos.x509_SecTrustSettingsCopyCertificates_trampoline in go.o
  "_SecTrustSettingsCopyTrustSettings", referenced from:
      _crypto/x509/internal/macos.x509_SecTrustSettingsCopyTrustSettings_trampoline in go.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

https://storage.googleapis.com/go-build-log/14984eec/darwin-amd64-10_14_b0e9ceb1.log

I suppose the build was relying on the #cgo LDFLAGS: -framework CoreFoundation -framework Security line from the cgo file to bring in the dynamic libraries, even if it was not cgo to use them, as they were used via go:cgo_import_dynamic.

See also https://golang.org/cl/248333. /cc @cherrymui @thanm @randall77

@cherrymui
Copy link
Contributor

@cherrymui cherrymui commented Nov 9, 2020

Thanks for reporting. I can reproduce on the current tip with $ CGO_ENABLED=0 go test -c -ldflags=-linkmode=external crypto/x509.

I agree it is related to the LDFLAGS. One way is that you could add

//go:cgo_ldflag "-framework"
//go:cgo_ldflag "CoreFoundation"
//go:cgo_ldflag "-framework"
//go:cgo_ldflag "Security"

to one of the non-cgo files (e.g. crypto/x509/internal/macos/corefoundation.go). (You have to do one flag a line, sorry.)

cc @ianlancetaylor about using cgo_ldflag in non-cgo-generated files. (It is still limited to the standard library by the compiler.)

@cagedmantis cagedmantis added the NeedsFix label Nov 9, 2020
@cagedmantis cagedmantis added this to the Backlog milestone Nov 9, 2020
@FiloSottile
Copy link
Member Author

@FiloSottile FiloSottile commented Nov 9, 2020

@cherrymui
Copy link
Contributor

@cherrymui cherrymui commented Nov 9, 2020

I don't know there is anyway for the linker to add those flags automatically in general. (Another possibility is to pass them in the command line, as -extldflags, but I assume this is not what you wanted.)

From cgo_import_dynamic pragmas the linker knows the libraries' paths, but it doesn't know the framework. In internal linking mode we just emit LC_LOAD_DYLIB with the libraries directly. Maybe we could hardcode a list of frameworks in the linker. But I'm not sure this is any better than adding pragmas in the source code.

Ideas welcome :)

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Nov 9, 2020

If we're going to use //go:cgo_ldflag in crypto/x509, we should update the comment in cmd/compile/internal/gc, which only mentions the runtime and syscall packages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.