Linux下steampipe-postgres-fdw编译失败问题排查
问题背景
steampipe-postgres-fdw是基于Golang开发的PostgreSQL外部数据包装器(FDW),通过go build -buildmode=c-archive编译生成约393MB的静态库steampipe_postgres_fdw.a,再通过PostgreSQL的PGXS构建系统编译为扩展。在Linux(amd64/aarch64)下执行make时出现两类错误:
- 重定位错误:提示需用
-fPIC重新编译 - DWARF调试信息段溢出错误
Darwin(M1/Intel)环境下构建正常,且当静态库体积约100MB时Linux下也能正常编译。
相关配置与错误日志
Makefile配置
MODULE_big = steampipe_postgres_fdw OBJS = [list of object files] SHLIB_LINK = steampipe_postgres_fdw.a EXTENSION = steampipe_postgres_fdw DATA = steampipe_postgres_fdw--1.0.sql REGRESS = steampipe_postgres-fdw EXTRA_CLEAN = steampipe_postgres_fdw.a fdw.h PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) SERVER_LIB = $(shell $(PG_CONFIG) --includedir-server) INTERNAL_LIB = $(shell $(PG_CONFIG) --includedir)/internal PG_CFLAGS = -I${SERVER_LIB} -I${INTERNAL_LIB} -g include $(PGXS)
错误日志示例(aarch64架构)
/usr/bin/ld: steampipe_postgres_fdw.a(go.o): relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol `type:string' which may bind externally can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: DWARF error: line info data is bigger (0x65f0639) than the space remaining in the section (0xe86ef9) /usr/bin/ld: DWARF error: line info data is bigger (0x66400c8) than the space remaining in the section (0xe86cbd) ... /usr/bin/ld: steampipe_postgres_fdw.a(go.o): relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol `encoding/json.stateError·f' which may bind externally can not be used when making a shared object; recompile with -fPIC go.go:(.text+0x13ade0): dangerous relocation: unsupported relocation
原因分析
重定位错误根源:
Linux下构建共享库(PostgreSQL扩展以共享库形式加载)要求所有链接的目标文件必须生成位置无关代码(PIC)。Go编译c-archive时默认未强制生成PIC代码,当静态库体积较大时,链接器会触发外部符号重定位检查;而Darwin的链接器对PIC的约束更宽松,小体积静态库则因符号分布未触发该检查。DWARF错误根源:
Go编译时默认生成详细的DWARF调试信息,当静态库体积达到393MB时,调试信息的大小超过了链接器默认分配的.debug_line段空间上限,导致段溢出错误。
解决方法
1. 强制Go生成PIC代码编译静态库
Go 1.17及以上版本支持通过CGO_CFLAGS环境变量传递-fPIC参数,确保生成的静态库符合Linux共享库链接要求:
CGO_CFLAGS="-fPIC" go build -buildmode=c-archive -o steampipe_postgres_fdw.a
2. 优化DWARF调试信息
方案A:剥离调试信息(推荐,大幅减小体积)
编译Go静态库时添加-s -w参数,剥离符号表和调试信息,既解决DWARF段溢出问题,又缩小静态库体积:
CGO_CFLAGS="-fPIC" go build -buildmode=c-archive -s -w -o steampipe_postgres_fdw.a
方案B:调整链接器段大小(保留调试信息时使用)
在Makefile中添加链接器参数,扩大.debug_line段的起始地址和大小:
PG_LDFLAGS += -Wl,--relax -Wl,--section-start=.debug_line=0x10000000
注:不同架构可能需要调整段起始地址的数值。
3. 调整Makefile的链接配置
确保链接器完整包含静态库中的所有符号,避免因符号缺失导致的隐式错误:
修改Makefile中的SHLIB_LINK为:
SHLIB_LINK += -Wl,--whole-archive steampipe_postgres_fdw.a -Wl,--no-whole-archive
内容的提问来源于stack exchange,提问作者Binaek Sarkar

