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 
<https://github.com/golang/go/issues/31578>), 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 (
"testing"
"github.com/stretchr/testify/assert"
cgomultiversion1 "github.com/vitalyisaev2/cgo_multiversion_go_lib/v1"
cgomultiversion2 "github.com/vitalyisaev2/cgo_multiversion_go_lib/v2"
)

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



Full example is available at: 
https://github.com/vitalyisaev2/cgo_multiversion_go_lib

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

-- 
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+unsubscr...@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.

Reply via email to