On AIX, shared objects must be wrapped under an archive file.
For testso, creating libcgosotest with an extern symbol isn't
AIX-friendly. By default, ld will block such behavior. Rather than
forcing ld to work as on Linux and using the run-time linking,
goCallback became a function pointer which is set by setCallback().
Updates #30565
Change-Id: I455ab32faddd41f1b0c84cc9e503788044ad49b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/169020
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
if runtime.GOOS == "linux" {
t.Skip("External linking not implemented on aix/ppc64 (issue #8912).")
}
- if runtime.GOOS == "aix" {
- t.Skip("Using shared object isn't yet available on aix/ppc64 (issue #30565)")
- }
case "mips64le", "mips64":
t.Skip("External linking not implemented on mips64.")
}
case "windows":
ext = "dll"
args = append(args, "-DEXPORT_DLL")
+ case "aix":
+ ext = "so.1"
}
sofname := "libcgosotest." + ext
args = append(args, "-o", sofname, "cgoso_c.c")
}
t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
+ if runtime.GOOS == "aix" {
+ // Shared object must be wrapped by an archive
+ cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1")
+ cmd.Dir = modRoot
+ out, err = cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
+ }
+ }
+
cmd = exec.Command("go", "build", "-o", "main.exe", "main.go")
cmd.Dir = modRoot
cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
#include "_cgo_export.h"
-#ifdef WIN32
+#if defined(WIN32) || defined(_AIX)
extern void setCallback(void *);
void init() {
setCallback(goCallback);
#cgo netbsd LDFLAGS: -L. libcgosotest.so
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
#cgo windows LDFLAGS: -L. libcgosotest.dll
+#cgo aix LDFLAGS: -L. -l cgosotest
void init(void);
void sofunc(void);
goCallback = (void (*)())f;
}
__declspec(dllexport) void sofunc(void);
+#elif defined(_AIX)
+// AIX doesn't allow the creation of a shared object with an
+// undefined symbol. It's possible to bypass this problem by
+// using -Wl,-G and -Wl,-brtl option which allows run-time linking.
+// However, that's not how most of AIX shared object works.
+// Therefore, it's better to consider goCallback as a pointer and
+// to set up during an init function.
+void (*goCallback)(void);
+void setCallback(void *f) { goCallback = f; }
#else
extern void goCallback(void);
void setCallback(void *f) { (void)f; }
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build dragonfly freebsd linux netbsd solaris
+// +build aix dragonfly freebsd linux netbsd solaris
package cgosotest
if runtime.GOOS == "linux" {
t.Skip("External linking not implemented on aix/ppc64 (issue #8912).")
}
- if runtime.GOOS == "aix" {
- t.Skip("Using shared object isn't yet available on aix/ppc64 (issue #30565)")
- }
case "mips64le", "mips64":
t.Skip("External linking not implemented on mips64.")
}
case "windows":
ext = "dll"
args = append(args, "-DEXPORT_DLL")
+ case "aix":
+ ext = "so.1"
}
sofname := "libcgosotest." + ext
args = append(args, "-o", sofname, "cgoso_c.c")
}
t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
+ if runtime.GOOS == "aix" {
+ // Shared object must be wrapped by an archive
+ cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1")
+ cmd.Dir = modRoot
+ out, err = cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
+ }
+ }
+
cmd = exec.Command("go", "build", "-o", "main.exe", "main.go")
cmd.Dir = modRoot
cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
#cgo netbsd LDFLAGS: -L. libcgosotest.so
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
#cgo windows LDFLAGS: -L. libcgosotest.dll
+#cgo aix LDFLAGS: -L. -l cgosotest
#include "cgoso_c.h"