Reputation: 41
I am trying to create a golang program which will use an external C library. Before doing complex stuff, I wanted to test the use of SWIG in a small foo example. I also want to be able to use the "go get" syntax without having to manually run swig. And to take into account that the external C library shall have been built before and can be located anywhere on the machine.
I am using golang 1.12.5 and swig 3.0.12
I have created the following structure:
.
|-- libfoo
| |-- foo.c
| |-- foo.h
| `-- libfoo.so
`-- src
|-- example_test.go
|-- lib.go
`-- libfoo.swig
In the libfoo folder I have a simple shared library. The files contain: foo.c:
#include "foo.h"
int foo(int c){
return c+1;
};
foo.h
int foo(int c);
That I've compiled it with:
gcc -o ./libfoo.so -fPIC -shared ./foo.c
Then the golang files: libfoo.swig
%module libfoo
%{
extern int foo(int a);
%}
extern int foo(int a);
lib.go
package libfoo
/*
#cgo LDFLAGS: -L../libfoo -lfoo
*/
import "C"
And finally example_test.go
package libfoo
import (
"testing"
"fmt"
)
func TestFoo(*testing.T) {
i := Foo(1)
fmt.Printf("%v\n",i)
}
When I try to build with "go build -x" It seems that the cgo directives located in the "lib.go" file are not taken into account as I do not see the flag appears in the output. Here is the output
06aa7e308d6:/mnt/data/src# go build -x
WORK=/tmp/go-build551116655
mkdir -p $WORK/b001/
swig -version
cd $WORK
/opt/go/pkg/tool/linux_amd64/compile -o ./b001/_go_.o -trimpath ./b001 -p main -complete -goversion go1.12.5 -D _$WORK -c=4 ./swig_intsize.go
cd /mnt/data/src
swig -go -cgo -intgosize 64 -module libfoo -o $WORK/b001/libfoo_wrap.c -outdir $WORK/b001/ libfoo.swig
CGO_LDFLAGS='"-g" "-O2"' /opt/go/pkg/tool/linux_amd64/cgo -objdir $WORK/b001/ -importpath _/mnt/data/src -- -I $WORK/b001/ -g -O2 ./lib.go $WORK/b001/_libfoo_swig.go
cd $WORK
gcc -fno-caret-diagnostics -c -x c - || true
gcc -Qunused-arguments -c -x c - || true
gcc -fdebug-prefix-map=a=b -c -x c - || true
gcc -gno-record-gcc-switches -c -x c - || true
cd $WORK/b001
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x001.o -c _cgo_export.c
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x002.o -c lib.cgo2.c
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x003.o -c _libfoo_swig.cgo2.c
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_x004.o -c libfoo_wrap.c
TERM='dumb' gcc -I /mnt/data/src -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -I ./ -g -O2 -o ./_cgo_main.o -c _cgo_main.c
cd /mnt/data/src
TERM='dumb' gcc -I . -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=$WORK/b001=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_cgo_.o $WORK/b001/_cgo_main.o $WORK/b001/_x001.o $WORK/b001/_x002.o $WORK/b001/_x003.o $WORK/b001/_x004.o -g -O2
# _/mnt/data/src
/tmp/go-build551116655/b001/_x004.o: In function `_wrap_foo_libfoo_0f106433f15c8754':
/tmp/go-build/libfoo_wrap.c:255: undefined reference to `foo'
collect2: error: ld returned 1 exit status
If I set the CGO_LDFLAGS using an environment variable, it works. However I want to be able to just use "go get" without having those variables before.
I don't understand why go does not take my #cgo directive into account. Did I miss something ?
Upvotes: 3
Views: 946
Reputation: 41
Someone on the golang github repository has solved my issue.
The solution was to remove the newline between the import "C" directive and the comments containing the #cgo directives.
Upvotes: 1