0

这是一个好奇的问题:为什么?

为什么完全相同的代码会有不同的行为?

我经常遇到这样的问题,即我可以在一个发行版中编译某些东西,但不能在另一个发行版中编译。所以今天我又遇到了一个问题,当我以与 ArchLinux 相同的方式构建 PostgreSQL 的 pg_dump 时,它可以工作,但是当我在 Alpine 上这样做时,它会失败并出现以下错误:

gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -static -fPIC -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -fPIC -shared -Wl,-soname,libpq.so.5 -Wl,--version-script=exports.list -o libpq.so.5.11 fe-auth.o fe-auth-scram.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o fe-protocol2.o fe-protocol3.o pqexpbuffer.o fe-secure.o libpq-events.o chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o thread.o getpeereid.o pg_strong_random.o encnames.o wchar.o base64.o ip.o md5.o scram-common.o saslprep.o unicode_norm.o sha2.o -L../../../src/port -L../../../src/common    -Wl,--as-needed -Wl,-rpath,'/usr/local/pgsql/lib',--enable-new-dtags    
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: /lib/gcc/x86_64-linux-musl/8.2.0/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: /lib/gcc/x86_64-linux-musl/8.2.0/crtend.o: relocation R_X86_64_32 against `.ctors' can not be used when making a shared object; recompile with -fPIC
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
make[1]: Leaving directory '/src/src/interfaces/libpq'
make[1]: *** [../../../src/Makefile.shlib:309: libpq.so.5.11] Error 1
make: *** [../../../src/Makefile.global:580: submake-libpq] Error 2

这是 Alpine 的 Dockerfile:

FROM muslcc/x86_64:x86_64-linux-musl

RUN apk update && apk add make

ENV DOWNLOAD_URL https://ftp.postgresql.org/pub/source/v11.2/postgresql-11.2.tar.bz2

WORKDIR /src
RUN wget "$DOWNLOAD_URL" && \
    tar xvjf "${DOWNLOAD_URL##*/}" --strip-components=1 && \
    rm -fv "${DOWNLOAD_URL##*/}"

# NOTE: I left the -fPIC here for clarity sake but it fails with
#       the same error with or without it
RUN ./configure --without-readline --without-zlib CFLAGS="-static -fPIC"
RUN cd src/bin/pg_dump && make pg_dump

这是 ArchLinux 的 Dockerfile:

FROM archlinux/base

RUN pacman -Syu --noconfirm --needed base-devel musl

ENV DOWNLOAD_URL https://ftp.postgresql.org/pub/source/v11.2/postgresql-11.2.tar.bz2

WORKDIR /src
RUN curl -o "${DOWNLOAD_URL##*/}" "$DOWNLOAD_URL" && \
    tar xvjf "${DOWNLOAD_URL##*/}" --strip-components=1 && \
    rm -fv "${DOWNLOAD_URL##*/}"

RUN ./configure --without-readline --without-zlib CC="musl-gcc" CFLAGS="-static"
RUN cd src/bin/pg_dump && make pg_dump

我什至不知道在哪里看。这可能是musl版本的不同吗?另一个编译工具?我真的不想要解决方案,我想了解原因。

4

1 回答 1

1

我对 Alpine Linux 没有太多经验,我需要自己玩它,但似乎一些非常基本的标准 C 库是作为非平台无关代码 (PIC) 构建的,这意味着你不是允许与它链接一个动态库。

我会开始追逐 Alpine Linux 开发人员,因为 PostgreSQL 可能有配置标志,可以让你构建你想要的东西。

现在,我注意到一件事。您传递CFLAGS=-static给编译,但它./configure已经设置为共享是没有意义的 - 仔细查看您引用的编译器调用。如果要静态构建,则需要找到适当的配置标志并将其与./configure. 我你的情况--disable-shared应该有效。

CFLAGS="-static" CXXFLAGS="-static" LDFLAGS="-Wl,-Bstatic" ./configure --without-readline --without-zlib

似乎启用-static而不离开-shared

于 2019-04-15T08:22:12.267 回答