'"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