Golang静态编译自定义库的方法与实践

Golang静态编译自定义库的方法与实践 大家好,

我正在尝试使用SAP NetWeaver库静态编译一个Go程序。

如果我像这样直接构建:

$ go build hello_gorfc.go

它会创建一个可执行文件,这个文件可以正常工作(它能连接到SAP系统并获取相关数据),但它是动态链接的:

$ file hello_gorfc
hello_gorfc: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter 
/lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0e44420f833955509aa381f3d18dd3d447d398ca, for 
GNU/Linux 3.2.0, not stripped

$ ldd hello_gorfc
linux-vdso.so.1 (0x00007ffdf0191000)
libsapnwrfc.so => /usr/local/sap/nwrfcsdk/lib/libsapnwrfc.so (0x00007f5b5d765000)
libsapucum.so => /usr/local/sap/nwrfcsdk/lib/libsapucum.so (0x00007f5b5d42b000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f5b5d408000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5b5d216000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5b5d210000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f5b5d205000)
libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f5b5d1fa000)

如果我尝试静态编译,则会失败。我已经尝试了各种参数组合:

$ go build -ldflags '-linkmode external -extldflags "-static"'  -a hello_gorfc.go
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: cannot find -lsapnwrfc
/usr/bin/ld: cannot find -lsapucum
collect2: error: ld returned 1 exit status

$ CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags '-linkmode external -extldflags "-static"'  -a hello_gorfc.go
package command-line-arguments: build constraints exclude all Go files in /home/appuser

$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-linkmode external -extldflags "-static"'  -a hello_gorfc.go
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: cannot find -lsapnwrfc
/usr/bin/ld: cannot find -lsapucum
collect2: error: ld returned 1 exit status

非常感谢您能提供的任何帮助。如果您需要更多细节来进行评估,请告诉我。

提前感谢。


更多关于Golang静态编译自定义库的方法与实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

顶一下

更多关于Golang静态编译自定义库的方法与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


对于静态编译包含SAP NetWeaver库的Go程序,需要使用CGO并正确配置链接器参数。以下是解决方案:

// 首先确保CGO_ENABLED=1,因为SAP库需要CGO
// 创建构建脚本 build_static.sh:
#!/bin/bash
export CGO_ENABLED=1
export GOOS=linux
export GOARCH=amd64

# 设置SAP库路径
export SAPNWRFC_HOME=/usr/local/sap/nwrfcsdk
export CGO_CFLAGS="-I$SAPNWRFC_HOME/include"
export CGO_LDFLAGS="-L$SAPNWRFC_HOME/lib -lsapnwrfc -lsapucum -Wl,-rpath,$SAPNWRFC_HOME/lib"

# 使用外部链接模式进行静态编译
go build -ldflags '-linkmode=external -extldflags "-static -L$SAPNWRFC_HOME/lib"' -o hello_gorfc_static hello_gorfc.go

如果上述方法仍然失败,可以尝试使用完全静态链接的方法:

// 创建自定义链接器配置
// 在项目根目录创建 static_build.go:
//go:build static
// +build static

package main

/*
#cgo linux LDFLAGS: -Wl,-Bstatic -lsapnwrfc -lsapucum -Wl,-Bdynamic -lpthread -ldl -lrt -luuid -lc
*/
import "C"

// 然后使用以下命令构建:
CGO_ENABLED=1 go build -tags=static -o hello_gorfc_static hello_gorfc.go

另一种方法是使用pkg-config配置:

// 创建sapnwrfc.pc文件:
/*
prefix=/usr/local/sap/nwrfcsdk
libdir=${prefix}/lib
includedir=${prefix}/include

Name: sapnwrfc
Description: SAP NetWeaver RFC SDK
Version: 7.50
Libs: -L${libdir} -lsapnwrfc -lsapucum -lpthread -ldl -lrt -luuid
Cflags: -I${includedir}
*/

// 设置环境变量:
export PKG_CONFIG_PATH=/usr/local/sap/nwrfcsdk/lib/pkgconfig:$PKG_CONFIG_PATH

// 构建命令:
CGO_ENABLED=1 go build -ldflags '-extldflags "-static"' -o hello_gorfc_static hello_gorfc.go

如果SAP库本身依赖其他动态库,可能需要将所有依赖库都静态链接。创建链接器包装脚本:

// 创建wrapper.sh:
#!/bin/bash
SAP_LIB="/usr/local/sap/nwrfcsdk/lib"
STATIC_LIBS="$SAP_LIB/libsapnwrfc.a $SAP_LIB/libsapucum.a"

# 收集系统静态库
SYS_LIBS="-lpthread -ldl -lrt -luuid -lc"

gcc -o hello_gorfc_static \
    -static \
    $STATIC_LIBS \
    $SYS_LIBS \
    hello_gorfc.o

// 然后分步构建Go程序:
CGO_ENABLED=1 go build -buildmode=c-archive -o hello_gorfc.a hello_gorfc.go
# 使用上面的wrapper.sh进行最终链接

验证静态编译结果:

$ file hello_gorfc_static
hello_gorfc_static: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0

$ ldd hello_gorfc_static
不是动态可执行文件

关键点:

  1. SAP NetWeaver库需要CGO支持
  2. 必须正确设置库路径和包含路径
  3. 使用-linkmode=external-extldflags "-static"组合
  4. 确保所有依赖库都有静态版本可用
回到顶部