Re: Build issue with postgresql 17 undefined reference to `pg_encoding_to_char' and `pg_char_to_encoding'

From: Mikael Sand <msand(at)seaber(dot)io>
To: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: Build issue with postgresql 17 undefined reference to `pg_encoding_to_char' and `pg_char_to_encoding'
Date: 2024-10-09 09:51:21
Message-ID: CAAwAxZfWmmYqEDTGowaA3HS215=6bUPBCrC6e2SY0udqBayCpg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

This seems to work:

# syntax=docker/dockerfile:1
FROM alpine:3.20 AS builder

# Fails with 17.0 succeeds with 16.4
ARG PG=17.0

USER root
RUN apk update && apk add --no-cache --update-cache \
ca-certificates-bundle \
util-linux-dev \
execline-dev \
libedit-dev \
libxml2-dev \
clang17-dev \
llvm18-dev \
build-base \
net-tools \
zlib-dev \
autoconf \
automake \
busybox \
icu-dev \
clang17 \
llvm18 \
cmake \
bison \
meson \
ninja \
flex \
perl \
curl \
bash
WORKDIR /app

RUN curl -L https://github.com/openssl/openssl/releases/download/openssl-3.3.2/openssl-3.3.2.tar.gz
> openssl.tar.gz
RUN mkdir openssl && tar --extract --file=openssl.tar.gz
--strip-components=1 --directory=openssl && rm openssl.tar.gz
RUN cd openssl && CC=clang CXX=clang++ perl ./Configure \
linux-$(uname -m) \
--prefix=/usr \
--libdir=lib \
--openssldir=/etc/ssl \
enable-ktls \
shared \
no-zlib \
no-async \
no-comp \
no-idea \
no-mdc2 \
no-rc5 \
no-ec2m \
no-sm2 \
no-sm4 \
no-ssl3 \
no-seed \
no-weak-ssl-ciphers \
-Wa,--noexecstack && \
perl configdata.pm --dump && \
make -j$(nproc) && make install

RUN curl -L https://ftp.postgresql.org/pub/source/v$PG/postgresql-$PG.tar.bz2
> postgresql.tar.bz2
RUN mkdir postgresql && tar --extract --bzip2
--file=postgresql.tar.bz2 --strip-components=1 --directory=postgresql
&& rm postgresql.tar.bz2
COPY <<EOF ./pg.patch
Subject: [PATCH] Fix static build
---
Index: src/bin/initdb/Makefile
<+>UTF-8
===================================================================
diff --git a/src/bin/initdb/Makefile b/src/bin/initdb/Makefile
--- a/src/bin/initdb/Makefile (revision
c4b8a916f8a53379621825028532b038e004f891)
+++ b/src/bin/initdb/Makefile (date 1728466911177)
@@ -20,7 +20,8 @@
# from libpq, else we have risks of version skew if we run with a libpq
# shared library from a different PG version. Define
# USE_PRIVATE_ENCODING_FUNCS to ensure that that happens.
-override CPPFLAGS := -DUSE_PRIVATE_ENCODING_FUNCS -I$(libpq_srcdir)
-I$(top_srcdir)/src/timezone $(ICU_CFLAGS) $(CPPFLAGS)
+#override CPPFLAGS := -DUSE_PRIVATE_ENCODING_FUNCS -I$(libpq_srcdir)
-I$(top_srcdir)/src/timezone $(ICU_CFLAGS) $(CPPFLAGS)
+override CPPFLAGS := -I$(libpq_srcdir) -I$(top_srcdir)/src/timezone
$(ICU_CFLAGS) $(CPPFLAGS)

# We need libpq only because fe_utils does.
LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils
$(libpq_pgport) $(ICU_LIBS)
Index: src/common/Makefile
<+>UTF-8
===================================================================
diff --git a/src/common/Makefile b/src/common/Makefile
--- a/src/common/Makefile (revision c4b8a916f8a53379621825028532b038e004f891)
+++ b/src/common/Makefile (date 1728466354406)
@@ -143,7 +143,7 @@
# Files in libpgcommon.a should use/export the "xxx_private" versions
# of pg_char_to_encoding() and friends.
#
-$(OBJS_FRONTEND): CPPFLAGS += -DUSE_PRIVATE_ENCODING_FUNCS
+#$(OBJS_FRONTEND): CPPFLAGS += -DUSE_PRIVATE_ENCODING_FUNCS

#
EOF

RUN apk update && apk add --no-cache --update-cache git
RUN cd postgresql && git apply ../pg.patch
RUN cd postgresql && export CC=clang && export CXX=clang++ && \
./configure --with-openssl --with-libedit-preferred
--with-uuid=e2fs --with-libxml --prefix=/usr/local && \
cd src/include && make && make install && \
cd ../common && make && make install && \
cd ../port && make && make install && \
cd ../interfaces/libpq && make && make install

COPY <<EOF ./main.cpp
#include <algorithm>
#include <iostream>
#include <chrono>
#include <thread>
#include <cstring>
#include <csignal>
#include <vector>

#include <libpq-fe.h>

void sig_handler(int /*_signo*/, siginfo_t * info, void * /*_ctx*/) {
raise(info->si_signo);
_exit(EXIT_FAILURE);
}

void registerSignalHandlers() {
std::vector<int> signals = {
// Signals for which the default action is "Core".
SIGABRT, // Abort signal from abort(3)
SIGBUS, // Bus error (bad memory access)
SIGFPE, // Floating point exception
SIGILL, // Illegal Instruction
SIGIOT, // IOT trap. A synonym for SIGABRT
SIGQUIT, // Quit from keyboard
SIGSEGV, // Invalid memory reference
SIGSYS, // Bad argument to routine (SVr4)
SIGTRAP, // Trace/breakpoint trap
SIGXCPU, // CPU time limit exceeded (4.2BSD)
SIGXFSZ, // File size limit exceeded (4.2BSD)
SIGTERM
};

for (size_t i = 0; i < signals.size(); ++i) {
struct sigaction action;
memset(&action, 0, sizeof action);
action.sa_flags = static_cast<int>(SA_SIGINFO | SA_ONSTACK |
SA_NODEFER | SA_RESETHAND);
sigfillset(&action.sa_mask);
sigdelset(&action.sa_mask, signals[i]);
action.sa_sigaction = &sig_handler;
sigaction(signals[i], &action, nullptr);
}
}

int main() {
registerSignalHandlers();
std::cout << "start" << std::endl;
PGconn *conn = PQconnectdb("");
if (conn == NULL) {
std::cout << "fail" << std::endl;
} else {
if (PQstatus(conn) == CONNECTION_OK) {
std::cout << "success" << std::endl;
} else {
fprintf(stderr, "fail: %s", PQerrorMessage(conn));
}
PQfinish(conn);
}
while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
return 0;
}
EOF

# Fails with "-static" succeeds without
RUN CC=clang CXX=clang++ clang++ \
-std=c++20 \
-static \
-flto \
-O3 \
-march=native \
-Wpedantic \
-Wall \
-Wextra \
-Wsign-conversion \
-Wconversion \
-o main main.cpp \
-lpq \
-lpgcommon \
-lpgport \
-lssl \
-lcrypto \
-lpthread \
-ldl
ENTRYPOINT ["./main"]
CMD []

On Wed, Oct 9, 2024 at 10:10 AM Mikael Sand <msand(at)seaber(dot)io> wrote:

> Hello dear Hackers
>
> I'm trying to upgrade to v17 and encountering a strange issue.
>
> I've made a minimal reproduction that works with 16.4 but fails with 17.0,
> it also works without the "-static" compile flag:
>
>
> # syntax=docker/dockerfile:1
>> FROM alpine:3.20 AS builder
>>
>> # Fails with 17.0 succeeds with 16.4
>> ARG PG=17.0
>>
>> USER root
>> RUN apk update && apk add --no-cache --update-cache \
>> ca-certificates-bundle \
>> util-linux-dev \
>> clang17-dev \
>> execline-dev \
>> llvm18-dev \
>> libedit-dev \
>> libxml2-dev \
>> build-base \
>> net-tools \
>> clang17 \
>> zlib-dev \
>> autoconf \
>> automake \
>> busybox \
>> llvm18 \
>> icu-dev \
>> cmake \
>> bison \
>> flex \
>> perl \
>> curl \
>> bash \
>> flex
>> WORKDIR /app
>>
>> RUN curl -L https://github.com/openssl/openssl/releases/download/openssl-3.3.2/openssl-3.3.2.tar.gz > openssl.tar.gz
>> RUN mkdir openssl && tar --extract --file=openssl.tar.gz --strip-components=1 --directory=openssl && rm openssl.tar.gz
>> RUN cd openssl && CC=clang CXX=clang++ perl ./Configure \
>> linux-$(uname -m) \
>> --prefix=/usr \
>> --libdir=lib \
>> --openssldir=/etc/ssl \
>> enable-ktls \
>> shared \
>> no-zlib \
>> no-async \
>> no-comp \
>> no-idea \
>> no-mdc2 \
>> no-rc5 \
>> no-ec2m \
>> no-sm2 \
>> no-sm4 \
>> no-ssl3 \
>> no-seed \
>> no-weak-ssl-ciphers \
>> -Wa,--noexecstack && \
>> perl configdata.pm --dump && \
>> make -j$(nproc) && make install
>>
>> RUN curl -L https://ftp.postgresql.org/pub/source/v$PG/postgresql-$PG.tar.bz2 > postgresql.tar.bz2
>> RUN mkdir postgresql && tar --extract --bzip2 --file=postgresql.tar.bz2 --strip-components=1 --directory=postgresql && rm postgresql.tar.bz2
>> RUN cd postgresql && CC=clang CXX=clang++ ./configure --with-openssl --with-libedit-preferred --with-uuid=e2fs --with-libxml --prefix=/usr/local
>> RUN cd postgresql/src/include && CC=clang CXX=clang++ make && make install
>> RUN cd postgresql/src/common && CC=clang CXX=clang++ make && make install
>> RUN cd postgresql/src/port && CC=clang CXX=clang++ make && make install
>> RUN cd postgresql/src/interfaces/libpq && CC=clang CXX=clang++ make && make install
>>
>> COPY <<EOF ./main.cpp
>> #include <algorithm>
>> #include <iostream>
>> #include <chrono>
>> #include <thread>
>> #include <cstring>
>> #include <csignal>
>> #include <vector>
>>
>> #include <libpq-fe.h>
>>
>> void sig_handler(int /*_signo*/, siginfo_t * info, void * /*_ctx*/) {
>> raise(info->si_signo);
>> _exit(EXIT_FAILURE);
>> }
>>
>> void registerSignalHandlers() {
>> std::vector<int> signals = {
>> // Signals for which the default action is "Core".
>> SIGABRT, // Abort signal from abort(3)
>> SIGBUS, // Bus error (bad memory access)
>> SIGFPE, // Floating point exception
>> SIGILL, // Illegal Instruction
>> SIGIOT, // IOT trap. A synonym for SIGABRT
>> SIGQUIT, // Quit from keyboard
>> SIGSEGV, // Invalid memory reference
>> SIGSYS, // Bad argument to routine (SVr4)
>> SIGTRAP, // Trace/breakpoint trap
>> SIGXCPU, // CPU time limit exceeded (4.2BSD)
>> SIGXFSZ, // File size limit exceeded (4.2BSD)
>> SIGTERM
>> };
>>
>> for (size_t i = 0; i < signals.size(); ++i) {
>> struct sigaction action;
>> memset(&action, 0, sizeof action);
>> action.sa_flags = static_cast<int>(SA_SIGINFO | SA_ONSTACK | SA_NODEFER | SA_RESETHAND);
>> sigfillset(&action.sa_mask);
>> sigdelset(&action.sa_mask, signals[i]);
>> action.sa_sigaction = &sig_handler;
>> sigaction(signals[i], &action, nullptr);
>> }
>> }
>>
>> int main() {
>> registerSignalHandlers();
>> std::cout << "start" << std::endl;
>> PGconn *conn = PQconnectdb("");
>> if (conn == NULL) {
>> std::cout << "fail" << std::endl;
>> } else {
>> if (PQstatus(conn) == CONNECTION_OK) {
>> std::cout << "success" << std::endl;
>> } else {
>> fprintf(stderr, "fail: %s", PQerrorMessage(conn));
>> }
>> PQfinish(conn);
>> }
>> while (true) {
>> std::this_thread::sleep_for(std::chrono::milliseconds(1000));
>> }
>> return 0;
>> }
>> EOF
>>
>> # Fails with "-static" succeeds without
>> RUN CC=clang CXX=clang++ clang++ \
>> -std=c++20 \
>> -static \
>> -flto \
>> -O3 \
>> -march=native \
>> -Wpedantic \
>> -Wall \
>> -Wextra \
>> -Wsign-conversion \
>> -Wconversion \
>> -o main main.cpp \
>> -lpq \
>> -lpgcommon \
>> -lpgport \
>> -lssl \
>> -lcrypto \
>> -lpthread \
>> -ldl
>> ENTRYPOINT ["./main"]
>> CMD []
>>
>>
> And here is the output:
>
> 15/15
> RUN CC=clang CXX=clang++ clang++ -std=c++20 -static -flto -O3
> -march=native -Wpedantic -Wall -Wextra -Wsign-conversion -Wconversion -o
> main main.cpp -lpq -lpgcommon -lpgport -lssl -lcrypto -lpthread -ldl
> ERROR
> 1.0s
> 1
> /usr/bin/ld: /usr/local/lib/libpq.a(fe-connect.o): in function
> `pqConnectOptions2':
> 2
> fe-connect.c:(.text+0x1cb4): undefined reference to `pg_encoding_to_char'
> 3
> /usr/bin/ld: /usr/local/lib/libpq.a(fe-connect.o): in function
> `PQsetClientEncoding':
> 4
> fe-connect.c:(.text+0x64a8): undefined reference to `pg_encoding_to_char'
> 5
> /usr/bin/ld: /usr/local/lib/libpq.a(fe-exec.o): in function
> `pqSaveParameterStatus':
> 6
> fe-exec.c:(.text+0x1168): undefined reference to `pg_char_to_encoding'
> 7
> /usr/bin/ld: /usr/local/lib/libpq.a(fe-misc.o): in function
> `PQenv2encoding':
> 8
> fe-misc.c:(.text+0x1394): undefined reference to `pg_char_to_encoding'
> 9
> clang++: error: linker command failed with exit code 1 (use -v to see
> invocation)
>
> Any ideas?
>
> Best regard
> Mikael Sand
>

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Michael Paquier 2024-10-09 09:54:18 Re: GUC names in messages
Previous Message Erik Wienhold 2024-10-09 09:34:39 Re: pgindent fails with perl 5.40