Re: Build issue with postgresql 17 undefined reference to `pg_encoding_to_char' and `pg_char_to_encoding' - Mailing list pgsql-hackers

From Mikael Sand
Subject Re: Build issue with postgresql 17 undefined reference to `pg_encoding_to_char' and `pg_char_to_encoding'
Date
Msg-id CAAwAxZfWmmYqEDTGowaA3HS215=6bUPBCrC6e2SY0udqBayCpg@mail.gmail.com
Whole thread Raw
Responses Re: Build issue with postgresql 17 undefined reference to `pg_encoding_to_char' and `pg_char_to_encoding'
List 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@seaber.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

pgsql-hackers by date:

Previous
From: Erik Wienhold
Date:
Subject: Re: pgindent fails with perl 5.40
Next
From: Tomas Vondra
Date:
Subject: Re: Changing the state of data checksums in a running cluster