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 <ms...@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
>

Reply via email to