Search code examples
gccgocgo

Golang c-shared on linux - ld cannot find -ltest


I'm trying to follow the instructions in http://snowsyn.net/2016/09/11/creating-shared-libraries-in-go/

My project is somewhat simpler. The library has one test function with println. As the title says, I'm getting 'cannot find'.

I'm running Ubuntu zesty and go 1.7.4

ls -l

roy@roy-desktop:~/go/src/c$ ls -l total 2016 -rw-rw-r-- 1 roy roy 43 Dec 10 06:55 test.c -rw-rw-r-- 1 roy roy 1274 Dec 10 06:54 test.h -rw-rw-r-- 1 roy roy 2053664 Dec 10 06:54 test.so

test.c

#include "test.h"

int main() {
    test();
}

lib.go

package main

import "fmt"
import "C"


//export test
func test() {
    fmt.Println("test")
}

func main() {}

test.h and test.so were generated with: go build -o test.so -buildmode=c-shared test.go

invocation of gcc fails as follows:

roy@roy-desktop:~/go/src/c$ gcc -o test test.c -L. -ltest
/usr/bin/ld: cannot find -ltest
collect2: error: ld returned 1 exit status

The original example uses clang but googling indicates the invocation should work for gcc as well.

Post Solution

A couple of extra comments:

  1. A function name in go func test() {} will appear in nm as _test but should be declared in C as extern void test();

  2. For some reason, the invocation go build -buildmode=c-shared does not generate a header file on OSX but does on Linux.


Solution

  • Note the difference between the go build commandline in the instructions you say you are following:

    go build -o libimgutil.so -buildmode=c-shared imgutil.go
                +++^^^^^^^^^^                     ^^^^^^^^^^ 
    

    and your own go build command:

    go build -o test.so -buildmode=c-shared test.go
                ^^^^^^^                     ^^^^^^^
    

    Consider this difference in the light of the documentation of the linker option -l | --library

    -l namespec
    --library=namespec
    
    Add the archive or object file specified by namespec to the list of files to link.
                                                ^^^^^^^^
    This option may be used any number of times. If namespec is of the form :filename,
                                                    ^^^^^^^^                +^^^^^^^^
    ld will search the library path for a file called filename, otherwise it will
                                                      ^^^^^^^^
    search the library path for a file called libnamespec.a.
                                              +++^^^^^^^^++
    On ... ELF and SunOS systems, ld will search a directory for a library called
    libnamespec.so before searching for one called libnamespec.a. (By convention,
    +++^^^^^^^^+++                                 +++^^^^^^^^++
    a .so extension indicates a shared library.) ...
    

    This will show you that your go build command needs to be:

    go build -o libtest.so -buildmode=c-shared test.go