'"Compiling" go project as C shared object library on AIX 7.2 results in Executable that doesn't run
EDIT: For any poor soul that finds this, in search of a solution for the shared library from go conundrum: I was unable to find a solution that uses go and I would suggest, that until google go provides native c-shared support for AIX you should find an alternative for your project.
I did not go forward with gccgo because that felt like an entirely different can of worms that I was unwilling to delve further into. FWIW I myself am going forward switching to pure C implementation, because there I at least have a (somewhat) firm(er) understanding of it all.
Should anyone find a solution I'd love to hear from you and see how you got around this limitation.
Environment: AIX 7.2 go1.16.12 aix/ppc64 gcc-8
I want to create a C shared object library (in usual unix vernacular a .so file) out of a golang project on AIX 7.2 so that it can be used by a C application. I can compile it down to a final a.out binary in my example, but it can then not be executed because the shared object is apparently compiled the wrong way.
So far I have achieved the following:
Suppose my example go "library" sharedLibTest.go:
package main
import (
m "fmt"
)
import "C"
func main() {
fmt.Printf("%s\n", "Golang: main was called")
MyPackage_Init()
MyPackage_Create()
}
//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")
}
And some C application that calls these functions in main.c:
#include <stdio.h>
#include "sharedLibTest.h"
int main() {
printf("%s\n", "C: main() called");
MyPackage_Init();
MyPackage_Create();
}
m
Now, because AIX feels the need to do things differently the current golang toolchain does not support directly creating a c-shared object with -buildmode=c-shared. Instead I am trying to do the roundabout way by first creating a static lib with -buildmode=c-archive, compiling that into a shared object using gcc-8 and use that in my "target C application".
I can compile sharedLibTest.go this 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
Because the symbols MyPackage_Init and MyPackage_Create are not exported by default in AIX, I need to manually create an extra symbol file 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
Now because AIX does not look for .so files but only .a files even if they are shared libraries, I rename the resulting libsharedLibTest.so into libsharedLibTest.a with
mv libsharedLibTest.so libsharedLibTest.a
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 revealed that I might be missing the compile option -fPIC to create "emit position-independent code" however adding that flag to any of the above steps in various combinations has all resulted in the same error.
Clearly I need to add some compile option to tell the shared object not to be thread-local, however I am unclear how. Any ideas?
Solution 1:[1]
Few points... mv will not make an archieve, ar will. You need to use ar command to create .a file. Second, use LIBPATH environment variable in place of LD_LIBRARY_PATH. Use of -fPIC option is irrelevant on AIX.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Sunil |
