Skip to content

Commit 31afd0c

Browse files
authored
Vendor xerces (#12)
* build: bundle xerces-c as submodule and link statically Adds third_party/xerces-c (pinned to tag v3.2.5; the xercesc_3_2 ABI namespace is hard-coded across ORCA so the 3.3.x line cannot be used without a source migration) and a new PG_ORCA_BUNDLED_XERCES CMake option (default ON) that builds it as a static archive folded into pg_orca.so. The system-xerces pkg-config / manual search path is kept as a fallback when the option is set to OFF. CPack deb/rpm drop the libxerces-c runtime dependency in bundled mode, so the resulting package installs cleanly on hosts without an external xerces-c (e.g. self-hosted Supabase, distroless containers). * build: require bundled xerces for release deb/rpm packaging CPackConfig.cmake now hard-errors when PG_ORCA_BUNDLED_XERCES=OFF, so release packages can never accidentally ship with a runtime libxerces-c dependency that may be absent on the target host (Ubuntu 24.04's t64 rename, RHEL 9, Supabase / distroless images). The previously conditional deb/rpm Depends/Requires lines collapse to the bundled-only form. build-packages.sh passes -DPG_ORCA_BUNDLED_XERCES=ON explicitly so stale cache values cannot disable bundling.
1 parent bb94828 commit 31afd0c

7 files changed

Lines changed: 148 additions & 45 deletions

File tree

.github/workflows/build.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ jobs:
2323

2424
steps:
2525
- uses: actions/checkout@v5
26+
with:
27+
submodules: recursive
2628

2729
- name: Add PostgreSQL apt repository (pgdg)
2830
run: |
@@ -95,6 +97,8 @@ jobs:
9597
perl perl-IPC-Run
9698
9799
- uses: actions/checkout@v5
100+
with:
101+
submodules: recursive
98102

99103
- name: Show toolchain versions
100104
run: |
@@ -161,6 +165,8 @@ jobs:
161165
git
162166
163167
- uses: actions/checkout@v5
168+
with:
169+
submodules: recursive
164170

165171
- name: Show toolchain versions
166172
run: |
@@ -208,6 +214,8 @@ jobs:
208214
perl perl-IPC-Run
209215
210216
- uses: actions/checkout@v5
217+
with:
218+
submodules: recursive
211219

212220
- name: Show toolchain versions
213221
run: |
@@ -258,6 +266,8 @@ jobs:
258266

259267
steps:
260268
- uses: actions/checkout@v5
269+
with:
270+
submodules: recursive
261271

262272
- name: Add PostgreSQL apt repository (pgdg)
263273
run: |
@@ -303,6 +313,8 @@ jobs:
303313

304314
steps:
305315
- uses: actions/checkout@v5
316+
with:
317+
submodules: recursive
306318

307319
- name: Install build dependencies
308320
run: |

.github/workflows/package.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ jobs:
1414

1515
steps:
1616
- uses: actions/checkout@v5
17+
with:
18+
submodules: recursive
1719

1820
- name: Add PostgreSQL apt repository (pgdg)
1921
run: |

.gitmodules

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Submodule pin: the recorded gitlink SHA below freezes xerces-c to a
2+
# specific commit (currently tag v3.2.5). The ABI namespace `xercesc_3_2`
3+
# is hard-coded throughout ORCA, so we cannot bump to the 3.3.x line
4+
# without a coordinated source change. Run `git submodule update --init
5+
# --recursive` after cloning.
6+
[submodule "third_party/xerces-c"]
7+
path = third_party/xerces-c
8+
url = https://github.com/apache/xerces-c

CMakeLists.txt

Lines changed: 103 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -53,52 +53,106 @@ message(STATUS " server headers: ${PG_SERVER_INCLUDEDIR}")
5353
message(STATUS " pkglibdir: ${PG_PKGLIBDIR}")
5454

5555
# -------------------------------------------------------------------
56-
# xerces-c (needed by ORCA for DXL XML parsing)
57-
# Prefer pkg-config (works on Linux and Homebrew macOS); fall back to
58-
# manual find_library + find_path for installations without .pc files.
56+
# xerces-c (needed by ORCA for DXL XML parsing).
57+
#
58+
# Default on Linux: build the bundled submodule under third_party/xerces-c
59+
# as a static library folded into pg_orca.so. This makes the extension
60+
# self-contained — no runtime libxerces-c.so dependency — which matters
61+
# for the deb/rpm release packages (self-hosted Supabase, distroless
62+
# containers, hosts without a matching xerces-c package).
63+
#
64+
# Default on macOS: use Homebrew's xerces-c. Release packaging is
65+
# Linux-only; for macOS dev builds the system library is easier and
66+
# avoids quirks of the static build on the Apple toolchain.
67+
#
68+
# Override either way with -DPG_ORCA_BUNDLED_XERCES=ON/OFF.
5969
# -------------------------------------------------------------------
60-
find_package(PkgConfig QUIET)
61-
if(PKG_CONFIG_FOUND)
62-
pkg_check_modules(XERCES xerces-c)
70+
if(APPLE)
71+
set(_pg_orca_bundled_default OFF)
72+
else()
73+
set(_pg_orca_bundled_default ON)
6374
endif()
75+
option(PG_ORCA_BUNDLED_XERCES
76+
"Build xerces-c from third_party/ submodule and link statically"
77+
${_pg_orca_bundled_default})
6478

65-
if(XERCES_FOUND)
66-
# pkg-config succeeded — prefer absolute paths from XERCES_LINK_LIBRARIES so
67-
# the linker doesn't need to search for it. On macOS Homebrew, xerces-c
68-
# lives in /opt/homebrew/opt/xerces-c/lib which is not a default search
69-
# path, so passing only "-lxerces-c" fails with "library not found".
70-
if(XERCES_LINK_LIBRARIES)
71-
set(XERCES_LIB ${XERCES_LINK_LIBRARIES})
72-
else()
73-
set(XERCES_LIB ${XERCES_LIBRARIES})
79+
if(PG_ORCA_BUNDLED_XERCES)
80+
set(_xerces_src "${CMAKE_SOURCE_DIR}/third_party/xerces-c")
81+
if(NOT EXISTS "${_xerces_src}/CMakeLists.txt")
82+
message(FATAL_ERROR
83+
"PG_ORCA_BUNDLED_XERCES=ON but ${_xerces_src}/CMakeLists.txt is "
84+
"missing. Run: git submodule update --init --recursive")
7485
endif()
75-
set(XERCES_INCLUDE ${XERCES_INCLUDE_DIRS})
76-
message(STATUS "xerces-c (pkg-config): ${XERCES_LIB}")
86+
87+
# Force xerces options before adding its subdirectory. FORCE is required
88+
# because xerces-c declares these with CACHE; without FORCE our values
89+
# would be ignored on the second cmake run.
90+
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
91+
set(network OFF CACHE BOOL "" FORCE) # no socket-based entity resolver
92+
set(transcoder "gnuiconv" CACHE STRING "" FORCE) # use glibc iconv, not ICU
93+
set(message-loader "inmemory" CACHE STRING "" FORCE) # no external catalog files
94+
set(threads ON CACHE BOOL "" FORCE)
95+
# Suppress xerces install rules; we never install its headers/libs.
96+
set(CMAKE_SKIP_INSTALL_RULES_BACKUP "${CMAKE_SKIP_INSTALL_RULES}")
97+
set(CMAKE_SKIP_INSTALL_RULES TRUE)
98+
add_subdirectory(third_party/xerces-c EXCLUDE_FROM_ALL)
99+
set(CMAKE_SKIP_INSTALL_RULES "${CMAKE_SKIP_INSTALL_RULES_BACKUP}")
100+
101+
set_target_properties(xerces-c PROPERTIES
102+
POSITION_INDEPENDENT_CODE ON
103+
CXX_VISIBILITY_PRESET hidden
104+
VISIBILITY_INLINES_HIDDEN ON)
105+
106+
# The xerces-c target propagates its include dirs as PUBLIC, so consumers
107+
# only need to link to it. Keep XERCES_INCLUDE empty for the static path.
108+
set(XERCES_LIB xerces-c)
109+
set(XERCES_INCLUDE "")
110+
message(STATUS "xerces-c: bundled static build (third_party/xerces-c)")
77111
else()
78-
# Fall back to manual search
79-
find_library(XERCES_LIB xerces-c
80-
PATHS
81-
/opt/homebrew/opt/xerces-c/lib # Apple Silicon Homebrew
82-
/usr/local/opt/xerces-c/lib # Intel Homebrew
83-
/usr/local/lib # Linux generic
84-
/usr/lib
85-
/usr/lib/x86_64-linux-gnu # Debian/Ubuntu amd64
86-
/usr/lib/aarch64-linux-gnu # Debian/Ubuntu arm64
87-
)
88-
find_path(XERCES_INCLUDE xercesc/util/XercesDefs.hpp
89-
PATHS
90-
/opt/homebrew/opt/xerces-c/include
91-
/usr/local/opt/xerces-c/include
92-
/usr/local/include
93-
/usr/include
94-
)
95-
if(NOT XERCES_LIB OR NOT XERCES_INCLUDE)
96-
message(FATAL_ERROR
97-
"xerces-c not found. Install it (e.g. 'apt install libxerces-c-dev' "
98-
"or 'brew install xerces-c') or set -DXERCES_LIB= and "
99-
"-DXERCES_INCLUDE= manually.")
112+
# Legacy path: find a system-installed xerces-c.
113+
find_package(PkgConfig QUIET)
114+
if(PKG_CONFIG_FOUND)
115+
pkg_check_modules(XERCES xerces-c)
116+
endif()
117+
118+
if(XERCES_FOUND)
119+
# pkg-config succeeded — prefer absolute paths from XERCES_LINK_LIBRARIES
120+
# so the linker doesn't need to search for it. On macOS Homebrew,
121+
# xerces-c lives in /opt/homebrew/opt/xerces-c/lib which is not a
122+
# default search path, so passing only "-lxerces-c" fails.
123+
if(XERCES_LINK_LIBRARIES)
124+
set(XERCES_LIB ${XERCES_LINK_LIBRARIES})
125+
else()
126+
set(XERCES_LIB ${XERCES_LIBRARIES})
127+
endif()
128+
set(XERCES_INCLUDE ${XERCES_INCLUDE_DIRS})
129+
message(STATUS "xerces-c (pkg-config): ${XERCES_LIB}")
130+
else()
131+
find_library(XERCES_LIB xerces-c
132+
PATHS
133+
/opt/homebrew/opt/xerces-c/lib # Apple Silicon Homebrew
134+
/usr/local/opt/xerces-c/lib # Intel Homebrew
135+
/usr/local/lib # Linux generic
136+
/usr/lib
137+
/usr/lib/x86_64-linux-gnu # Debian/Ubuntu amd64
138+
/usr/lib/aarch64-linux-gnu # Debian/Ubuntu arm64
139+
)
140+
find_path(XERCES_INCLUDE xercesc/util/XercesDefs.hpp
141+
PATHS
142+
/opt/homebrew/opt/xerces-c/include
143+
/usr/local/opt/xerces-c/include
144+
/usr/local/include
145+
/usr/include
146+
)
147+
if(NOT XERCES_LIB OR NOT XERCES_INCLUDE)
148+
message(FATAL_ERROR
149+
"xerces-c not found. Install it (e.g. 'apt install libxerces-c-dev' "
150+
"or 'brew install xerces-c'), set -DXERCES_LIB= and "
151+
"-DXERCES_INCLUDE= manually, or use the default "
152+
"-DPG_ORCA_BUNDLED_XERCES=ON to build from third_party/.")
153+
endif()
154+
message(STATUS "xerces-c (manual): ${XERCES_LIB}, headers: ${XERCES_INCLUDE}")
100155
endif()
101-
message(STATUS "xerces-c (manual): ${XERCES_LIB}, headers: ${XERCES_INCLUDE}")
102156
endif()
103157

104158
# -------------------------------------------------------------------
@@ -132,6 +186,15 @@ file(GLOB_RECURSE ORCA_CORE_SRC CONFIGURE_DEPENDS
132186

133187
add_library(orca_core OBJECT ${ORCA_CORE_SRC})
134188

189+
# Pull in xerces-c headers via the target's PUBLIC interface. For the
190+
# bundled build XERCES_LIB is the "xerces-c" target which propagates its
191+
# header search path; for the system build XERCES_LIB is a library path
192+
# with no usage requirements (XERCES_INCLUDE supplies headers separately,
193+
# see target_include_directories below). OBJECT libs accept
194+
# target_link_libraries since CMake 3.12 — no symbol is actually linked,
195+
# but compile-time properties propagate.
196+
target_link_libraries(orca_core PUBLIC ${XERCES_LIB})
197+
135198
target_compile_definitions(orca_core PUBLIC
136199
$<$<CONFIG:Debug>:GPOS_DEBUG>
137200
USE_CMAKE

packaging/CPackConfig.cmake

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@
1010
#
1111
# Or use packaging/build-packages.sh as a thin wrapper.
1212

13+
# -------------------------------------------------------------------
14+
# Release packages must statically bundle xerces-c. Shipping a .deb/.rpm
15+
# that runtime-depends on the distro's libxerces-c is fragile (Ubuntu
16+
# 24.04 renamed the package to libxerces-c3.2t64, RHEL 9 has no current
17+
# build, Supabase / distroless images often lack it entirely). Refuse to
18+
# package if someone has overridden PG_ORCA_BUNDLED_XERCES=OFF.
19+
# -------------------------------------------------------------------
20+
if(NOT PG_ORCA_BUNDLED_XERCES)
21+
message(FATAL_ERROR
22+
"Release packaging requires PG_ORCA_BUNDLED_XERCES=ON so xerces-c "
23+
"is linked statically into pg_orca.so. Reconfigure without "
24+
"-DPG_ORCA_BUNDLED_XERCES=OFF.")
25+
endif()
26+
1327
# -------------------------------------------------------------------
1428
# Version: parse from pg_orca.control's default_version (single source).
1529
# -------------------------------------------------------------------
@@ -69,9 +83,9 @@ set(CPACK_DEBIAN_PACKAGE_SECTION "database")
6983
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
7084
# Match dpkg arch (amd64/arm64) rather than CMAKE_SYSTEM_PROCESSOR (x86_64/aarch64).
7185
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
72-
# postgresql-NN supplies pkglibdir/sharedir; libxerces-c is the runtime XML lib.
73-
set(CPACK_DEBIAN_PACKAGE_DEPENDS
74-
"postgresql-${PG_MAJOR}, libxerces-c3.2 | libxerces-c3.2t64")
86+
# postgresql-NN supplies pkglibdir/sharedir. xerces-c is statically linked
87+
# into pg_orca.so (enforced above), so no runtime libxerces-c is required.
88+
set(CPACK_DEBIAN_PACKAGE_DEPENDS "postgresql-${PG_MAJOR}")
7589
# Override default file name to use dpkg arch.
7690
execute_process(COMMAND dpkg --print-architecture
7791
OUTPUT_VARIABLE _deb_arch OUTPUT_STRIP_TRAILING_WHITESPACE
@@ -92,8 +106,8 @@ set(CPACK_RPM_PACKAGE_URL "${CPACK_PACKAGE_HOMEPAGE_URL}")
92106
set(CPACK_RPM_PACKAGE_VENDOR "${CPACK_PACKAGE_VENDOR}")
93107
set(CPACK_RPM_PACKAGE_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
94108
set(CPACK_RPM_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}")
95-
# PGDG postgresqlNN-server, distro xerces-c. autoreq picks up the rest.
96-
set(CPACK_RPM_PACKAGE_REQUIRES "postgresql${PG_MAJOR}-server, xerces-c")
109+
# PGDG postgresqlNN-server only; xerces-c is bundled into pg_orca.so.
110+
set(CPACK_RPM_PACKAGE_REQUIRES "postgresql${PG_MAJOR}-server")
97111
set(CPACK_RPM_PACKAGE_AUTOREQ ON)
98112
# Don't claim ownership of system dirs we install into.
99113
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION

packaging/build-packages.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,12 @@ repo_root="$(cd "$(dirname "$0")/.." && pwd)"
5858
cd "$repo_root"
5959

6060
echo "==> Configuring ($build_type) with PG_CONFIG=$pg_config"
61+
# PG_ORCA_BUNDLED_XERCES=ON is required for release packages so xerces-c
62+
# is statically linked into pg_orca.so (no runtime libxerces-c dep).
6163
cmake -S . -B "$build_dir" \
6264
-DCMAKE_BUILD_TYPE="$build_type" \
6365
-DPG_CONFIG="$pg_config" \
66+
-DPG_ORCA_BUNDLED_XERCES=ON \
6467
-GNinja
6568

6669
echo "==> Building"

third_party/xerces-c

Submodule xerces-c added at 53c1641

0 commit comments

Comments
 (0)