"架构x86_64的未定义符号:"在macOS Sierra上使用cgo的库

时间:2017-07-18 22:11:15

标签: c macos gcc go cgo

我正在尝试使用一个库https://github.com/go-steem/rpc,它使用了一些引用库的C代码。

可以在此处找到C库,https://github.com/bitcoin-core/secp256k1

我按照步骤安装了

$ ./autogen.sh
$ ./configure
$ make
$ ./tests
$ sudo make install  # optional

有这个输出;

$ sudo make install
Password:
  CC       src/libsecp256k1_la-secp256k1.lo
  CCLD     libsecp256k1.la
  CC       src/tests-tests.o
  CCLD     tests
  CC       src/exhaustive_tests-tests_exhaustive.o
  CCLD     exhaustive_tests
 build-aux/install-sh -c -d '/usr/local/lib'
 /bin/sh ./libtool   --mode=install /usr/bin/install -c   libsecp256k1.la '/usr/local/lib'
libtool: install: /usr/bin/install -c .libs/libsecp256k1.0.dylib /usr/local/lib/libsecp256k1.0.dylib
libtool: install: (cd /usr/local/lib && { ln -s -f libsecp256k1.0.dylib libsecp256k1.dylib || { rm -f libsecp256k1.dylib && ln -s libsecp256k1.0.dylib libsecp256k1.dylib; }; })
libtool: install: /usr/bin/install -c .libs/libsecp256k1.lai /usr/local/lib/libsecp256k1.la
libtool: install: /usr/bin/install -c .libs/libsecp256k1.a /usr/local/lib/libsecp256k1.a
libtool: install: chmod 644 /usr/local/lib/libsecp256k1.a
libtool: install: /usr/bin/ranlib /usr/local/lib/libsecp256k1.a
 build-aux/install-sh -c -d '/usr/local/include'
 /usr/bin/install -c -m 644 include/secp256k1.h '/usr/local/include'
 build-aux/install-sh -c -d '/usr/local/lib/pkgconfig'
 /usr/bin/install -c -m 644 libsecp256k1.pc '/usr/local/lib/pkgconfig'

我尝试从Go库运行upvote示例,go-steem / rpc / examples / upvote /并获得以下输出;

$ go run main.go 
# github.com/go-steem/rpc/transactions
../../transactions/signing.c:5:10: fatal error: 'secp256k1.h' file not found

感觉车轮已经脱落......

请耐心等待我,因为我没有用C语言发展,所以我得到了一些黑客攻击。

经过大量阅读和谷歌搜索后,我决定复制“包含”中的文件。我将libsecp256k1编译到与错误源自的目录相同的目录。

您可以看到文件不存在;

$ ls -la ../../transactions/
total 48
drwxr-xr-x   8 shaunmorrow  staff   272 May  8 18:09 .
drwxr-xr-x  15 shaunmorrow  staff   510 May  8 18:09 ..
-rw-r--r--   1 shaunmorrow  staff   256 Apr 27 17:53 chains.go
-rw-r--r--   1 shaunmorrow  staff  3731 May  8 18:09 signed_transaction.go
-rw-r--r--   1 shaunmorrow  staff  1849 May  8 18:09 signed_transaction_test.go
-rw-r--r--   1 shaunmorrow  staff  3075 Apr 27 17:53 signing.c
-rw-r--r--   1 shaunmorrow  staff   408 Apr 27 17:53 signing.h
-rw-r--r--   1 shaunmorrow  staff  1049 May  8 18:09 transactions.go

并在复制之后;

$ ls -la ../../transactions/
total 128
drwxr-xr-x  11 shaunmorrow  staff    374 Jul 18 19:08 .
drwxr-xr-x  15 shaunmorrow  staff    510 May  8 18:09 ..
-rw-r--r--   1 shaunmorrow  staff    256 Apr 27 17:53 chains.go
-rw-r--r--   1 shaunmorrow  staff  27071 Jul 18 19:08 secp256k1.h
-rw-r--r--   1 shaunmorrow  staff   1014 Jul 18 19:08 secp256k1_ecdh.h
-rw-r--r--   1 shaunmorrow  staff   4700 Jul 18 19:08 secp256k1_recovery.h
-rw-r--r--   1 shaunmorrow  staff   3731 Jul 18 19:05 signed_transaction.go
-rw-r--r--   1 shaunmorrow  staff   1849 May  8 18:09 signed_transaction_test.go
-rw-r--r--   1 shaunmorrow  staff   3075 Apr 27 17:53 signing.c
-rw-r--r--   1 shaunmorrow  staff    408 Apr 27 17:53 signing.h
-rw-r--r--   1 shaunmorrow  staff   1049 May  8 18:09 transactions.go

现在我收到一个新错误;

$ go run main.go 
# github.com/go-steem/rpc/transactions
ld: library not found for -lsecp256k1
clang: error: linker command failed with exit code 1 (use -v to see invocation)

这让我阅读和谷歌搜索更多,

最后,我得到更多hack-y并更改transactions.go;

// #cgo LDFLAGS: -lsecp256k1
// #include <stdlib.h>
// #include "signing.h"
import "C"

变为

// #cgo LDFLAGS: -L/usr/local/lib
// #include <stdlib.h>
// #include "signing.h"
import "C"

失败,稍后输出

我也试试;

// #cgo LDFLAGS: -L/usr/local/lib -I/usr/local/include
// #include <stdlib.h>
// #include "signing.h"
import "C"

并将.h文件复制到/ usr / local / include目录。

这些都不起作用,现在我遇到了像这样的错误

$ go run main.go 
# github.com/go-steem/rpc/transactions
ld: library not found for -lsecp256k1
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ShaunsSePc-2:upvote shaunmorrow$ go run main.go 
# github.com/go-steem/rpc/transactions
Undefined symbols for architecture x86_64:
  "_secp256k1_context_create", referenced from:
      _sign_transaction in signing.o
      _verify_recoverable_signature in signing.o
  "_secp256k1_context_destroy", referenced from:
      _sign_transaction in signing.o
      _verify_recoverable_signature in signing.o
  "_secp256k1_ec_pubkey_serialize", referenced from:
      _verify_recoverable_signature in signing.o
  "_secp256k1_ecdsa_recover", referenced from:
      _verify_recoverable_signature in signing.o
  "_secp256k1_ecdsa_recoverable_signature_convert", referenced from:
      _verify_recoverable_signature in signing.o
  "_secp256k1_ecdsa_recoverable_signature_parse_compact", referenced from:
      _verify_recoverable_signature in signing.o
  "_secp256k1_ecdsa_recoverable_signature_serialize_compact", referenced from:
      _sign_transaction in signing.o
  "_secp256k1_ecdsa_sign_recoverable", referenced from:
      _sign_transaction in signing.o
  "_secp256k1_ecdsa_verify", referenced from:
      _verify_recoverable_signature in signing.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

此时我真的不知道如何继续。

正如您所看到的,我根本没有C经验,也不知道如何测试库libsecp256k1是否安装得正确!

这是我结束的地方,但我很有可能在旅程的早期出现了错误的转弯,我很感激任何给予的帮助,因为我已经在这几个晚上一直在努力:( < / p>

不确定需要什么,所以这里有一些env变量

$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/shaunmorrow/Work/go/"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/86/hlqptn5101z5bcydjz05qy8m0000gn/T/go-build689438019=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

版本 go版本go1.8.3 darwin / amd64 ,没有旧版本。

谢谢!

1 个答案:

答案 0 :(得分:1)

你的问题有两个:

  1. 配置不正确的libsecp256k1
  2. 您的C编译器没有在/usr/local目录中搜索已安装的headers / libs
  3. 修复了libsecp256k1配置不正确的软件包

    关于链接C库的“未定义符号”问题有时会指向一个配置不正确的包(在Autotools包或CMake包的意义上,而不是Go包)。运行./configure --help,我看到有一个名为--enable-module-recovery的选项。根据{{​​1}}和_secp256k1_ecdsa_sign_recoverable之类的名称判断,您需要在配置时添加该选项,这意味着您应该执行此操作,而不是执行更简单的_secp256k1_ecdsa_recover

    ./configure

    C编译器坏了吗?

    由于在./configure --enable-module-recovery 中找不到secp256k1.h头文件,尽管在/usr/local/include完成后头文件肯定存在,但这意味着your compiler doesn't search /usr/local

    除了链接问题中的任何修补程序,您可以根据需要更改Go包的源代码来解决此问题,以添加/修改处理{{1时使用的sudo make installCFLAGS像这样的语句:

    LDFLAGS

    如果您安装了import "C",则可以使用它而不是手动设置// #cgo CFLAGS: -I/usr/local/include // #cgo LDFLAGS: -L/usr/local/lib -lsecp256k1 // #include <secp256k1.h> import "C" pkg-config

    1. 使用自定义路径集导出CFLAGS环境变量。由于未指定前缀(即用作安装根目录的目录),因此假定LDFLAGS,意味着PKG_CONFIG_PATH将包含标头,/usr/local将包含库。这意味着您需要在命令行中导出/usr/local/include,如/usr/local/lib中所示。取消设置时,默认设置PKG_CONFIG_PATH在Linux上按此顺序包含export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfigPKG_CONFIG_PATH,并指定为可能使用的其他软件包的后备,但在此可能不需要案件。 OS X上的默认路径集可能有所不同,因此请查阅您的/usr/lib/pkgconfig手册页以供参考。
    2. 使用/usr/share/pkgconfigpkg-config// #cgo pkg-config: libsecp256k1将根据需要进行设置,而无需对其进行任何操作。由于并非所有系统都安装了CFLAGS,因此如果您希望程序包保持可移植性,那么依赖于此可能是一个坏主意。再说一遍,我认为你所处理的混乱更为可取,因为LDFLAGS根本找不到。
    3. 更改为upvote目录并输入pkg-config以构建正常工作的upvote二进制文件。
    4. 其他自定义

      自定义前缀

      如果您使用pkg-config之外的其他内容作为前缀(例如make),那么您需要相应地调整一些内容:

      /usr/local

      您还需要修改upvote目录中提供的Makefile以设置构建的二进制文件的运行时路径,否则将找不到./configure --enable-module-recovery --prefix=/opt/libsecp256k1

      // #cgo CFLAGS: -I/opt/libsecp256k1/include
      // #cgo LDFLAGS: -L/opt/libsecp256k1/lib -lsecp256k1
      // #include "secp256k1.h"
      import "C"
      
      // or just use pkg-config and export the PKG_CONFIG_PATH environment
      // variable containing the following paths:
      //   /opt/libsecp256k1/lib/pkgconfig
      //   /opt/libsecp256k1/share/pkgconfig
      //   /usr/lib/pkgconfig
      //   /usr/share/pkgconfig
      

      有关使用cgo的更多信息,请查看以下资源: