8

I'm trying in Linux to statically link some code created in Nim into a Go application. I've followed the Nim Backend Integration docs and some articles for linking C in Go but haven't gotten it working.

Here's where I'm at so far...


Nim code target.nim:

proc testnim* {.exportc.} =
  echo "In Nim!"

I compile it with:

nim c --app:staticLib --noMain --header target.nim

Go code app.go:

package main

/*
#cgo CFLAGS: -I/my/path/to/target/nimcache
#cgo CFLAGS: -I/my/path/to/Nim/lib
#cgo LDFLAGS: /my/path/to/target/libtarget.a
#include "/my/path/to/target/nimcache/target.h"
*/
import "C"
import "fmt"

func main() {
  fmt.Println("In Go!")
  C.NimMain()
  C.testnim()
}

I tried building it both of these:

go build

go build --ldflags '-extldflags "-static"' app.go

Here's what I get:

# command-line-arguments
/my/path/to/target/libtarget.a(stdlib_system.o): In function `nimUnloadLibrary':
stdlib_system.c:(.text+0xe6f0): undefined reference to `dlclose'
/my/path/to/target/libtarget.a(stdlib_system.o): In function `nimLoadLibrary':
stdlib_system.c:(.text+0xe71b): undefined reference to `dlopen'
/my/path/to/target/libtarget.a(stdlib_system.o): In function `nimGetProcAddr':
stdlib_system.c:(.text+0xe750): undefined reference to `dlsym'
collect2: error: ld returned 1 exit status

So I'm missing something(s). I'm using Go 1.5 and Nim 0.11.3 (devel branch). Any advice or hints would be much appreciated.

Lye Fish
  • 2,538
  • 15
  • 25
  • 1
    `/my/path/to/target/libtarget.a` on it's own isn't a valid LDFLAG. You also need to specifically link *all* needed libraries, i.e. you need `-ldl` to link to libdl for `dlclose`, `dlopen`, etc. – JimB Sep 10 '15 at 21:56
  • 2
    and directly from the page you linked to: > "for instance, on Linux systems you will likely need to use -ldl too to link in required dlopen functionality." – JimB Sep 10 '15 at 21:58
  • @JimB: Thank you. So much of this is Greek to me. I'll give those suggestions a try. – Lye Fish Sep 10 '15 at 22:10
  • @JimB: Thanks again. It's working by adding `#cgo LDFLAGS: -ldl` to the `app.go` file, but only works if I keep the invalid `#cgo LDFLAGS: /my/path/to/target/libtarget.a`. Any idea why that would be or how/where it should be included to be properly done? – Lye Fish Sep 10 '15 at 22:25
  • Forgot you can pass files directly to gcc like that. I'm not sure if it's any better to use `-L /path/to/target -ltarget`. Go with whichever works – JimB Sep 10 '15 at 22:38
  • @JimB: Excellent, thanks. If you wish to post an answer about my `-ldl` omission, I'll accept it. Thanks again. – Lye Fish Sep 10 '15 at 22:40

1 Answers1

5

You're missing the libdl library. Add -ldl to your LDFLAGS

JimB
  • 104,193
  • 13
  • 262
  • 255