简体   繁体   English

“编译”go 项目作为 C 在 AIX 7.2 上共享 object 库导致无法运行的可执行文件

[英]"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.编辑:对于任何发现这个的可怜的灵魂,从 go 难题中寻找共享库的解决方案:我无法找到使用 go 的解决方案,我建议,直到谷歌 go 为 AIX 提供本机 c 共享支持你应该为你的项目找到一个替代方案。

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.我没有使用 gccgo go 转发,因为这感觉就像一个完全不同的蠕虫罐头,我不愿意进一步深入研究。 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. FWIW 我自己将转向纯粹的 C 实现,因为我至少对这一切有一个(有点)坚定(呃)的理解。

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环境: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.我想从 AIX 7.2 上的 golang 项目创建一个 C 共享 object 库(在通常的 unix 白话 a.so 文件中),以便它可以被 C 应用程序使用。 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.在我的示例中,我可以将它编译成最终的 a.out 二进制文件,但它无法执行,因为共享的 object 显然是以错误的方式编译的。

So far I have achieved the following:到目前为止,我已经取得了以下成就:

Suppose my example go "library" sharedLibTest.go:假设我的示例 go“库”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:还有一些 C 应用程序在 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 . m 现在,因为 AIX 觉得需要以不同的方式做事,所以当前的 golang 工具链不支持使用-buildmode=c-shared直接创建 c-shared object。 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".相反,我试图通过首先使用-buildmode=c-archive创建一个 static 库,使用 gcc-8 将其编译成一个共享的 object 并在我的“目标 C 应用程序”中使用它来尝试迂回的方式。

I can compile sharedLibTest.go this with我可以用 sharedLibTest.go 编译它

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因为在 AIX 中默认情况下不导出符号MyPackage_InitMyPackage_Create ,所以我需要手动创建一个额外的符号文件

$ 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)来源(如果有任何想法我可以省略这个 file.exp 步骤我真的很感激)

Now with that I can compile a shared object out of that by running现在我可以通过运行从中编译一个共享的 object

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现在因为 AIX 不查找 .so 文件而只查找 .a 文件,即使它们是共享库,我将生成的 libsharedLibTest.so 重命名为 libsharedLibTest.a

mv libsharedLibTest.so libsharedLibTest.a

Lastly I want to compile my C applications with最后我想编译我的 C 应用程序

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.这成功了,结果我得到了我的 a.out 文件。 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.到目前为止,几个小时的谷歌搜索显示我可能缺少编译选项 -fPIC 来创建“发出与位置无关的代码”,但是以各种组合将该标志添加到上述任何步骤都会导致相同的错误。

Clearly I need to add some compile option to tell the shared object not to be thread-local, however I am unclear how.显然我需要添加一些编译选项来告诉共享 object 不是线程本地的,但我不清楚如何。 Any ideas?有任何想法吗?

Few points... mv will not make an archieve, ar will.几点... mv不会存档, ar会。 You need to use ar command to create .a file.您需要使用ar命令来创建.a文件。 Second, use LIBPATH environment variable in place of LD_LIBRARY_PATH.其次,使用 LIBPATH 环境变量代替 LD_LIBRARY_PATH。 Use of -fPIC option is irrelevant on AIX. -fPIC 选项的使用与 AIX 无关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM