Compile Go application with multiple versions of C library

118 views
Skip to first unread message

Vitaly Isaev

unread,
Oct 8, 2019, 8:56:45 AM10/8/19
to golang-nuts
Suggest we're implementing a very specific Go application like data migrator (for example, the one that transfers data from old database to new database with different data types). Therefore, this application must be compiled with two different versions of one library (e.g. v1 and v2). It seems to be impossible in terms of Go modules (see this ticket), but can we do this trick with C shared libraries?

Minimal example:

v1/lib.h
#ifndef LIBCGO_MULTIVERSION_V1
#define LIBCGO_MULTIVERSION_V1

int add(int a, int b);

#endif

v1/lib.c
#include "lib.h"

int add(int a, int b) {
    return a + b;
}

v1/lib.go
package cgomultiversion

// #cgo LDFLAGS: -l:libcgomultiversion.so.1
// #include <cgomultiversion_v1/lib.h>
import "C"

func Add(a, b int) int {
return int(C.add(C.int(a), C.int(b)))
}

v2/lib.h
#ifndef LIBCGO_MULTIVERSION_V2
#define LIBCGO_MULTIVERSION_V2

int add(int a, int b);

#endif

v2/lib.c
#include "lib.h"

int add(int a, int b) {
    // for tests purposes addition is replaced with multiplication in v2
    return a * b;
}

v2/lib.go
package cgomultiversion

// #cgo LDFLAGS: -l:libcgomultiversion.so.2
// #include <cgomultiversion_v2/lib.h>
import "C"

func Add(a, b int) int {
return int(C.add(C.int(a), C.int(b)))
}

Finally we have a test that tries to utilize both versions of C library:
package cgomultiversion

import (
)

func TestAdd(t *testing.T) {
assert.Equal(t, 10, cgomultiversion1.Add(5, 5))
assert.Equal(t, 25, cgomultiversion2.Add(5, 5))
}

This won't compile because of naming conflict on the C side:
go test -count=1 -v        
# github.com/vitalyisaev2/cgo_multiversion_go_lib.test
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-218143790/000005.o: in function `add':
/home/isaev/go/src/github.com/vitalyisaev2/cgo_multiversion_go_lib/v2/lib.c:6: multiple definition of `add'; /tmp/go-link-218143790/000002.o:/home/isaev/go/src/github.com/vitalyisaev2/cgo_multiversion_go_lib/v1/lib.c:5: first defined here
collect2: error: ld returned 1 exit status



Is it possible to achieve this with some other methods? Thanks a lot.

Robert Engels

unread,
Oct 8, 2019, 11:00:58 AM10/8/19
to Vitaly Isaev, golang-nuts
You can create Go plugins too. 

On Oct 8, 2019, at 7:57 AM, Vitaly Isaev <vitaly...@gmail.com> wrote:


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/1778392c-d0d6-4ff9-9385-380483078626%40googlegroups.com.

Igor Maznitsa

unread,
Oct 15, 2019, 3:34:16 PM10/15/19
to golang-nuts
thats possible use preprocessing with golang too, but through some extra-tools, like maven-golang, example
Reply all
Reply to author
Forward
0 new messages