Hello everyone, I recently started working with AIX so please bear with me.
Environment:
AIX 7.2 64bit, powerpc7
go1.16.12 aix/ppc64
gcc-8
In our team we are trying to develop more applications with Golang for our AIX 7.2 platform and in one scenario we plan to create a shared object (.so-file) that can be called by a Perl application. So far I have gotten as far as being apparently able to compile it all down into some example C application, but that refuses to run. To showcase this issue I created a simple example described below.
For testing purposes I created the following simple golang project I want to compile out:
sharedLibTest.go
package main
import (
m "fmt"
)
import "C"
func main() {
}
//export MyPackage_Init
func MyPackage_Init() {
fmt.Printf("%s\n", "Golang: MyPackage_Init was called")
}
//export MyPackage_Create
func MyPackage_Create() {
fmt.Printf("%s\n", "Golang: MyPackage_Create was called")
}
The functions MyPackage_init() and MyPackage_Create should be callable by a simple C app that currently just consists of this main.c
#include <stdio.h>
#include "sharedLibTest.h"
int main() {
printf("%s\n", "C: main() called");
MyPackage_Init();
MyPackage_Create();
}
Now, while on other platforms the golang toolchain supports the direct creation of a shared object with the build flag -buildmode=c-shared, this is entirely unsupported on AIX at the time of writing. However we can create a static library out of it with -buildmode=c-archive and have that linked with gcc into a shared object.
I can compile that with
go build -v -buildmode=c-archive -mod vendor -o /home/myuser/workspace/go_proj/sharedLibTest/sharedLibTest.a /home/myuser/workspace/go_proj/sharedLibTest/sharedLibTest.go
This successfully creates the sharedLibTest.a file.
Because the symbols MyPackage_Init and MyPackage_Create are not exported by default in AIX, I need to manually create an extra symbol file to pass to my gcc compiler to incorporate the exportable symbols with:
$ cat > file.exp << EOF
> MyPackage_Init
> MyPackage_Create
> EOF
Source (If there are any ideas how i can omit this file.exp step I'd really appreciate it)
Now with that I can compile a shared object out of that by running
gcc -g -O2 -mcpu=power7 -maix64 -shared -lpthread -Wl,-bE:file.exp -o libsharedLibTest.so -Wl,-bnoobjreorder ./sharedLibTest.a
Because AIX supposedly does not look for .so files but only .a files even if they are shared libraries, I tried appending that .so file to an archive file.
ar -X64 r libsharedLibTest.a libsharedLibTest.so
Lastly I want to compile my C applications with
gcc -L/home/myuser/workspace/go_proj/sharedLibTest -g -O2 -mcpu=power7 -maix64 -Wl,-bnoobjreorder -lsharedLibTest -lpthreads main.c
This succeeds and I get my a.out file as a result. However, when I try to run this with the following, I only get the error below:
LD_LIBRARY_PATH=/home/myuser/workspace/go_proj/sharedLibTest ./a.out
$ ./a.out
exec(): 0509-036 Cannot load program ./a.out because of the following errors:
0509-150 Dependent module /home/myuser/workspace/go_proj/sharedLibTest/libsharedLibTest.a(libsharedLibTest.so) could not be loaded.
0509-187 The local-exec model was used for thread-local
storage, but the module is not the main program.
0509-193 Examine the .loader section header with the
'dump -Hv' command.
Some hours of googling so far have lead me to believe that the .so file created by golang is in fact position dependent code that fails to be usable as a dynamically loaded object because it is expected to be statically linked into some final binary. Using the -fPIC compile option should apparently fix this, however adding the flag to any of the above compilation steps has made no difference whatsoever, all leading to the same error message.
Clearly I need to add some compile option to tell the shared object not to use thread-local storage, however I am unclear how or what I am missing or whether I am invoking especially go build correctly or not.
Any help would be appreciated.
Cheers,
Chris