Search code examples
gccgoldnettle

How do I fix an undefined reference to `nettle_sha256_digest`?


TL;DR

I'm attempting to build a go project that uses this dependency: https://github.com/mqu/openldap, which in turn externally links lldap and llber libraries, which in turn uses lgnutls, which uses lnettle, which is where I'm stuck.

The go build produces a long list of undefined references and the build fails. Here's a sample:

/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o): In function `_ctx_init':
(.text+0x468): undefined reference to `nettle_sha256_digest'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o): In function `_ctx_init':
(.text+0x476): undefined reference to `nettle_sha224_init'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o): In function `_ctx_init':
(.text+0x494): undefined reference to `nettle_sha256_init'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o): In function `_ctx_init':
(.text+0x4b8): undefined reference to `nettle_sha256_digest'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o): In function `_ctx_init':
(.text+0x4c6): undefined reference to `nettle_sha256_init'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o):(.data.rel.ro+0x18): undefined reference to `nettle_sha256_init'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o):(.data.rel.ro+0x28): undefined reference to `nettle_sha256_digest'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o):(.data.rel.ro+0x58): undefined reference to `nettle_sha224_init'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o):(.data.rel.ro+0x68): undefined reference to `nettle_sha224_digest'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o):(.data.rel.ro+0x98): undefined reference to `nettle_sha1_init'
/usr/lib/x86_64-linux-gnu/libgnutls.a(sha-x86-ssse3.o):(.data.rel.ro+0xa8): undefined reference to `nettle_sha1_digest'

And my go build command:

CC=/usr/local/musl/bin/musl-gcc \
    GOOS=linux go build \
    -o /bin/activedirectory \
    -ldflags '-linkmode external -extldflags "-static -L/usr/lib/x86_64-linux-gnu -lnettle -lp11 -lsasl2 -lgnutls -ltasn1"'

I have tried resolving this by installing libnettle4, nettle-dev, libghc-nettle-dev, nettle-bin. I have made sure to include -lnettle in the ldflags. No luck.

More context

The openldap library is linking the ldap and lber libs in the code:

package openldap

/*

#define LDAP_DEPRECATED 1
#include <stdlib.h>
#include <ldap.h>

static inline char* to_charptr(const void* s) { return (char*)s; }
static inline LDAPControl** to_ldapctrlptr(const void* s) {
    return (LDAPControl**) s;
}
*/
// #cgo CFLAGS: -DLDAP_DEPRECATED=1
// #cgo linux CFLAGS: -DLINUX=1
// #cgo LDFLAGS: -lldap -llber

This has required me to install and include in the ldflags all the libraries you see in my build command.

So the dependency chain, in short, goes like this:

lldap -> lgnutls -> lnettle.

I added lgnutls and that resolved my gnutls dependency issues, but I'm unable to resolve my nettle depencency issues.

My question

What am I doing wrong in my attempts to fix these nettle dependency issues?

Bonus question

Is there a best practice for resolving these ld linker dependencies? Right now my flow looks like this:

  1. Run the build
  2. Watch for "undefined reference" errors
  3. Figure out which package is missing by googling the error or looking at the name referenced (e.g. nettle_sha1_digest = nettle package)
  4. Install that package
  5. Repeat

I guess I'm wondering if there's a magic bullet that can install all dependencies for me? :)


Solution

  • From the looks of it you're linking your dependent libraries in the wrong order (see Why does the order in which libraries are linked sometimes cause errors in GCC? for more context).

    With statically linked libraries the linker attempts to resolve symbols in the order that the libraries were specified in. If a relied-upon symbol comes up as undefined then the linker looks to see if it's defined in the subsequent libraries specified. Since in your build invocation -lnettle is specified before -lgnutls the gnutls library can't resolve the symbols it needs from nettle.

    What this means is that (at minimum) you'll have to move your reference to -lnettle to after -lgnutls. Not sure this will solve all of your problems since I'm not familiar with all of the linking dependencies you have listed, but it should at least solve your current errors running go build.