Skip to content

Commit e35389f

Browse files
mrdrivingduckclaude
andcommitted
feat(build): support macOS builds with platform-aware CMake
Update paimon-cpp submodule to a version that includes macOS support for both the core library and JindoSDK. Adapt CMakeLists.txt for cross-platform builds: use CMAKE_SHARED_LIBRARY_SUFFIX for dylib naming, handle macOS rpath with @loader_path, read JindoSDK version from versions.txt for the versioned dylib filename, and use generator expressions for GNU-ld-specific linker flags. Add a patch to define NDEBUG on macOS plugin dylibs so that Arrow's checked_cast uses static_cast instead of dynamic_cast, avoiding RTTI mismatches across dylib boundaries from duplicated static Arrow archives. Propagate paimon-cpp library rpath to consumers (unittest, duckdb shell) and create the JindoSDK compatibility symlink required by its install_name. Enable osx_arm64 in CI and release bundle workflows with platform-aware packaging. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 4e51e4c commit e35389f

6 files changed

Lines changed: 107 additions & 42 deletions

File tree

.github/workflows/MainDistributionPipeline.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
duckdb_version: v1.5.2
2020
ci_tools_version: v1.5.2
2121
extension_name: paimon
22-
exclude_archs: 'linux_amd64_musl;osx_amd64;osx_arm64;windows_amd64;windows_amd64_mingw;wasm_mvp;wasm_eh;wasm_threads'
22+
exclude_archs: 'linux_amd64_musl;osx_amd64;windows_amd64;windows_amd64_mingw;wasm_mvp;wasm_eh;wasm_threads'
2323

2424
code-quality-check:
2525
name: Code Quality Check

.github/workflows/release-bundle.yml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ jobs:
2929
runner: ubuntu-22.04
3030
- bundle_arch: linux-arm64
3131
runner: ubuntu-22.04-arm
32+
- bundle_arch: osx-arm64
33+
runner: macos-14
3234
steps:
3335
- name: Checkout source
3436
uses: actions/checkout@v6
@@ -56,7 +58,11 @@ jobs:
5658
- name: Build extension (release)
5759
shell: bash
5860
run: |
59-
GEN=ninja make
61+
if command -v ninja &>/dev/null; then
62+
GEN=ninja make
63+
else
64+
make
65+
fi
6066
6167
- name: Package release bundle
6268
id: package
@@ -73,14 +79,22 @@ jobs:
7379
mkdir -p "${STAGE_DIR}"
7480
7581
cp "${EXT_DIR}/paimon.duckdb_extension" "${STAGE_DIR}/"
76-
cp "${EXT_DIR}"/libpaimon*.so* "${STAGE_DIR}/"
77-
cp "${EXT_DIR}"/libjindosdk_c.so* "${STAGE_DIR}/"
82+
case "${{ matrix.bundle_arch }}" in
83+
linux-*) LIB_EXT="so" ;;
84+
osx-*) LIB_EXT="dylib" ;;
85+
esac
86+
cp "${EXT_DIR}"/libpaimon*."${LIB_EXT}"* "${STAGE_DIR}/"
87+
cp "${EXT_DIR}"/libjindosdk_c*."${LIB_EXT}"* "${STAGE_DIR}/"
7888
7989
cp LICENSE "${STAGE_DIR}/LICENSE"
8090
cp README.md "${STAGE_DIR}/README.md"
8191
8292
tar -C dist -czf "dist/${PKG_NAME}.tar.gz" "${PKG_NAME}"
83-
sha256sum "dist/${PKG_NAME}.tar.gz" > "dist/${PKG_NAME}.tar.gz.sha256"
93+
if command -v sha256sum &>/dev/null; then
94+
sha256sum "dist/${PKG_NAME}.tar.gz" > "dist/${PKG_NAME}.tar.gz.sha256"
95+
else
96+
shasum -a 256 "dist/${PKG_NAME}.tar.gz" > "dist/${PKG_NAME}.tar.gz.sha256"
97+
fi
8498
8599
echo "archive=dist/${PKG_NAME}.tar.gz" >> "${GITHUB_OUTPUT}"
86100
echo "checksum=dist/${PKG_NAME}.tar.gz.sha256" >> "${GITHUB_OUTPUT}"

CMakeLists.txt

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.5)
1+
cmake_minimum_required(VERSION 3.17)
22

33
# Set extension name here
44
set(TARGET_NAME paimon)
@@ -15,6 +15,20 @@ include_directories(src/include)
1515
# Import paimon-cpp as a subproject
1616
include(ExternalProject)
1717

18+
# JindoSDK: the installed filename differs by platform, but we always bundle
19+
# using the short name that matches the dylib's install_name.
20+
file(STRINGS third_party/paimon-cpp/third_party/versions.txt
21+
_jindosdk_ver REGEX "^PAIMON_JINDOSDK_C_BUILD_VERSION=")
22+
string(REGEX REPLACE ".*=" "" _jindosdk_ver "${_jindosdk_ver}")
23+
string(REGEX REPLACE "([0-9]+)\\..*" "\\1" _jindosdk_major "${_jindosdk_ver}")
24+
if(APPLE)
25+
set(JINDOSDK_C_INSTALLED_NAME "libjindosdk_c.${_jindosdk_ver}.dylib")
26+
set(JINDOSDK_C_RUNTIME_NAME "libjindosdk_c.${_jindosdk_major}.dylib")
27+
else()
28+
set(JINDOSDK_C_INSTALLED_NAME "libjindosdk_c.so")
29+
set(JINDOSDK_C_RUNTIME_NAME "libjindosdk_c.so.${_jindosdk_major}")
30+
endif()
31+
1832
set(PAIMON_CPP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/paimon-cpp)
1933
set(PAIMON_CPP_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/paimon-cpp-install)
2034
set(PAIMON_CPP_INCLUDE ${PAIMON_CPP_PREFIX}/include)
@@ -23,8 +37,7 @@ file(MAKE_DIRECTORY ${PAIMON_CPP_INCLUDE})
2337

2438
set(PAIMON_CPP_PATCHES
2539
${CMAKE_CURRENT_SOURCE_DIR}/patches/paimon-cpp-install-arrow-headers.patch
26-
${CMAKE_CURRENT_SOURCE_DIR}/patches/paimon-cpp-link-arrow-brotli-libs.patch
27-
${CMAKE_CURRENT_SOURCE_DIR}/patches/paimon-cpp-disable-glog-unwind.patch)
40+
${CMAKE_CURRENT_SOURCE_DIR}/patches/paimon-cpp-macos-ndebug-for-checked-cast.patch)
2841

2942
# Build patch command: apply each patch idempotently
3043
set(PAIMON_CPP_PATCH_SCRIPT "")
@@ -43,6 +56,7 @@ ExternalProject_Add(paimon_cpp_ep
4356
-DCMAKE_INSTALL_PREFIX=${PAIMON_CPP_PREFIX}
4457
-DCMAKE_INSTALL_LIBDIR=lib64
4558
-DLIBUNWIND_LIBRARY=FALSE
59+
-DPAIMON_DEPENDENCY_SOURCE=BUNDLED
4660
-DPAIMON_BUILD_TESTS=OFF
4761
-DPAIMON_BUILD_SHARED=ON
4862
-DPAIMON_BUILD_STATIC=OFF
@@ -52,16 +66,29 @@ ExternalProject_Add(paimon_cpp_ep
5266
-DPAIMON_ENABLE_LUMINA=OFF
5367
-DPAIMON_ENABLE_LUCENE=OFF
5468
BUILD_BYPRODUCTS
55-
${PAIMON_CPP_LIB}/libpaimon.so
56-
${PAIMON_CPP_LIB}/libpaimon_local_file_system.so
57-
${PAIMON_CPP_LIB}/libpaimon_jindo_file_system.so
58-
${PAIMON_CPP_LIB}/libjindosdk_c.so
59-
${PAIMON_CPP_LIB}/libpaimon_parquet_file_format.so
60-
${PAIMON_CPP_LIB}/libpaimon_orc_file_format.so
61-
${PAIMON_CPP_LIB}/libpaimon_avro_file_format.so
62-
${PAIMON_CPP_LIB}/libpaimon_blob_file_format.so
69+
${PAIMON_CPP_LIB}/libpaimon${CMAKE_SHARED_LIBRARY_SUFFIX}
70+
${PAIMON_CPP_LIB}/libpaimon_local_file_system${CMAKE_SHARED_LIBRARY_SUFFIX}
71+
${PAIMON_CPP_LIB}/libpaimon_jindo_file_system${CMAKE_SHARED_LIBRARY_SUFFIX}
72+
${PAIMON_CPP_LIB}/${JINDOSDK_C_INSTALLED_NAME}
73+
${PAIMON_CPP_LIB}/libpaimon_parquet_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
74+
${PAIMON_CPP_LIB}/libpaimon_orc_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
75+
${PAIMON_CPP_LIB}/libpaimon_avro_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
76+
${PAIMON_CPP_LIB}/libpaimon_blob_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
6377
)
6478

79+
# On macOS, paimon-cpp installs the JindoSDK dylib with a versioned filename
80+
# (e.g. libjindosdk_c.6.10.2.dylib) but its install_name uses the short
81+
# version (libjindosdk_c.6.dylib). Add a post-install step to provide the
82+
# short-named copy that runtime lookup expects.
83+
if(APPLE)
84+
ExternalProject_Add_Step(paimon_cpp_ep jindosdk_short_name
85+
DEPENDEES install
86+
BYPRODUCTS ${PAIMON_CPP_LIB}/${JINDOSDK_C_RUNTIME_NAME}
87+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
88+
${PAIMON_CPP_LIB}/${JINDOSDK_C_INSTALLED_NAME}
89+
${PAIMON_CPP_LIB}/${JINDOSDK_C_RUNTIME_NAME})
90+
endif()
91+
6592
# Extension sources
6693
set(EXTENSION_SOURCES
6794
src/paimon_extension.cpp
@@ -90,30 +117,38 @@ add_dependencies(${TARGET_NAME}_loadable_extension paimon_cpp_ep)
90117

91118
# Link with paimon-cpp
92119
set(PAIMON_CPP_LIBS
93-
${PAIMON_CPP_LIB}/libpaimon.so
94-
-Wl,--no-as-needed
95-
${PAIMON_CPP_LIB}/libpaimon_local_file_system.so
96-
${PAIMON_CPP_LIB}/libpaimon_jindo_file_system.so
97-
${PAIMON_CPP_LIB}/libjindosdk_c.so
98-
${PAIMON_CPP_LIB}/libpaimon_parquet_file_format.so
99-
${PAIMON_CPP_LIB}/libpaimon_orc_file_format.so
100-
${PAIMON_CPP_LIB}/libpaimon_avro_file_format.so
101-
${PAIMON_CPP_LIB}/libpaimon_blob_file_format.so
102-
-Wl,--as-needed
120+
${PAIMON_CPP_LIB}/libpaimon${CMAKE_SHARED_LIBRARY_SUFFIX}
121+
$<$<NOT:$<PLATFORM_ID:Darwin>>:-Wl,--no-as-needed>
122+
${PAIMON_CPP_LIB}/libpaimon_local_file_system${CMAKE_SHARED_LIBRARY_SUFFIX}
123+
${PAIMON_CPP_LIB}/libpaimon_jindo_file_system${CMAKE_SHARED_LIBRARY_SUFFIX}
124+
${PAIMON_CPP_LIB}/${JINDOSDK_C_INSTALLED_NAME}
125+
${PAIMON_CPP_LIB}/libpaimon_parquet_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
126+
${PAIMON_CPP_LIB}/libpaimon_orc_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
127+
${PAIMON_CPP_LIB}/libpaimon_avro_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
128+
${PAIMON_CPP_LIB}/libpaimon_blob_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
129+
$<$<NOT:$<PLATFORM_ID:Darwin>>:-Wl,--as-needed>
103130
)
104131
target_link_libraries(${EXTENSION_NAME} ${PAIMON_CPP_LIBS})
105132
target_link_libraries(${TARGET_NAME}_loadable_extension ${PAIMON_CPP_LIBS})
106133

134+
if(APPLE)
135+
# Propagate rpath so unittest/shell can find paimon-cpp shared libraries.
136+
target_link_options(${EXTENSION_NAME} INTERFACE "LINKER:-rpath,${PAIMON_CPP_LIB}")
137+
set(PAIMON_RPATH "@loader_path")
138+
else()
139+
set(PAIMON_RPATH "\$ORIGIN")
140+
endif()
141+
107142
# Bundle paimon-cpp runtime dependencies next to paimon.duckdb_extension.
108143
set(PAIMON_CPP_RUNTIME_BUNDLE_LIBS
109-
${PAIMON_CPP_LIB}/libpaimon.so
110-
${PAIMON_CPP_LIB}/libpaimon_local_file_system.so
111-
${PAIMON_CPP_LIB}/libpaimon_jindo_file_system.so
112-
${PAIMON_CPP_LIB}/libjindosdk_c.so.6
113-
${PAIMON_CPP_LIB}/libpaimon_parquet_file_format.so
114-
${PAIMON_CPP_LIB}/libpaimon_orc_file_format.so
115-
${PAIMON_CPP_LIB}/libpaimon_avro_file_format.so
116-
${PAIMON_CPP_LIB}/libpaimon_blob_file_format.so
144+
${PAIMON_CPP_LIB}/libpaimon${CMAKE_SHARED_LIBRARY_SUFFIX}
145+
${PAIMON_CPP_LIB}/libpaimon_local_file_system${CMAKE_SHARED_LIBRARY_SUFFIX}
146+
${PAIMON_CPP_LIB}/libpaimon_jindo_file_system${CMAKE_SHARED_LIBRARY_SUFFIX}
147+
${PAIMON_CPP_LIB}/${JINDOSDK_C_RUNTIME_NAME}
148+
${PAIMON_CPP_LIB}/libpaimon_parquet_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
149+
${PAIMON_CPP_LIB}/libpaimon_orc_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
150+
${PAIMON_CPP_LIB}/libpaimon_avro_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
151+
${PAIMON_CPP_LIB}/libpaimon_blob_file_format${CMAKE_SHARED_LIBRARY_SUFFIX}
117152
)
118153
foreach(lib IN LISTS PAIMON_CPP_RUNTIME_BUNDLE_LIBS)
119154
add_custom_command(
@@ -124,11 +159,9 @@ foreach(lib IN LISTS PAIMON_CPP_RUNTIME_BUNDLE_LIBS)
124159
$<TARGET_FILE_DIR:${TARGET_NAME}_loadable_extension>
125160
)
126161
endforeach()
127-
128-
# Make runtime library lookup relocatable for the shipped loadable extension.
129162
set_target_properties(${TARGET_NAME}_loadable_extension PROPERTIES
130-
BUILD_RPATH "\$ORIGIN"
131-
INSTALL_RPATH "\$ORIGIN"
163+
BUILD_RPATH "${PAIMON_RPATH}"
164+
INSTALL_RPATH "${PAIMON_RPATH}"
132165
BUILD_WITH_INSTALL_RPATH ON
133166
INSTALL_RPATH_USE_LINK_PATH OFF
134167
)
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
diff --git a/CMakeLists.txt b/CMakeLists.txt
2-
index 8a81fbb..93234b3 100644
32
--- a/CMakeLists.txt
43
+++ b/CMakeLists.txt
5-
@@ -310,6 +310,11 @@ install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
4+
@@ -321,6 +321,11 @@ install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
65
DESTINATION "include"
76
FILES_MATCHING
87
PATTERN "*.h")
@@ -11,6 +10,6 @@ index 8a81fbb..93234b3 100644
1110
+ FILES_MATCHING
1211
+ PATTERN "*.h"
1312
+ PATTERN "*.hpp")
14-
13+
1514
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
1615
set(CMAKE_C_VISIBILITY_PRESET hidden)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
diff --git a/cmake_modules/BuildUtils.cmake b/cmake_modules/BuildUtils.cmake
2+
index ed27ed7..1a4e79c 100644
3+
--- a/cmake_modules/BuildUtils.cmake
4+
+++ b/cmake_modules/BuildUtils.cmake
5+
@@ -176,7 +176,13 @@ function(add_paimon_lib LIB_NAME)
6+
target_link_libraries(${LIB_NAME}_shared
7+
PUBLIC "$<BUILD_INTERFACE:paimon_sanitizer_flags>")
8+
9+
- if(NOT APPLE)
10+
+ if(APPLE)
11+
+ # Arrow's checked_cast uses dynamic_cast in Debug builds, which
12+
+ # fails across dylib boundaries on macOS due to duplicate RTTI
13+
+ # from static Arrow archives. Define NDEBUG so checked_cast
14+
+ # falls back to static_cast (same as Release mode).
15+
+ target_compile_definitions(${LIB_NAME}_objlib PRIVATE $<$<CONFIG:Debug>:NDEBUG>)
16+
+ else()
17+
target_link_options(${LIB_NAME}_shared
18+
PRIVATE
19+
-Wl,--exclude-libs,ALL

third_party/paimon-cpp

Submodule paimon-cpp updated 435 files

0 commit comments

Comments
 (0)