diff --git a/.github/scripts/cibw-before-all-linux.sh b/.github/scripts/cibw-before-all-linux.sh new file mode 100755 index 000000000..b79685770 --- /dev/null +++ b/.github/scripts/cibw-before-all-linux.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +set -euxo pipefail +if command -v yum >/dev/null 2>&1; then + yum install -y wget tar gzip pkgconfig libuuid-devel libblkid-devel +elif command -v dnf >/dev/null 2>&1; then + dnf install -y wget tar gzip pkgconfig libuuid-devel libblkid-devel +else + echo "No supported package manager found (expected yum or dnf)." ; exit 1 +fi +if (command -v dnf >/dev/null 2>&1 && dnf install -y java-17-openjdk-devel) \ + || (command -v yum >/dev/null 2>&1 && yum install -y java-17-openjdk-devel); then + export JAVA_HOME="$(dirname "$(dirname "$(readlink -f "$(command -v javac)")")")" +else + ARCH="$(uname -m)" + mkdir -p /opt/java + if [ "$ARCH" = "x86_64" ]; then + JDK_URL="https://download.oracle.com/java/17/archive/jdk-17.0.12_linux-x64_bin.tar.gz" + else + # aarch64 + JDK_URL="https://download.oracle.com/java/17/archive/jdk-17.0.12_linux-aarch64_bin.tar.gz" + fi + curl -L -o /tmp/jdk17.tar.gz "$JDK_URL" + tar -xzf /tmp/jdk17.tar.gz -C /opt/java + export JAVA_HOME=$(echo /opt/java/jdk-17.0.12*) +fi +export PATH="$JAVA_HOME/bin:$PATH" +java -version + +chmod +x mvnw || true +./mvnw -Pwith-cpp clean package \ + -DskipTests -Dbuild.test=OFF \ + -Dspotless.check.skip=true -Dspotless.apply.skip=true +test -d cpp/target/build/lib && test -d cpp/target/build/include diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 148266ce9..d61677838 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -99,47 +99,31 @@ jobs: -Dcmake.args="-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0" otool -l cpp/target/build/lib/libtsfile*.dylib | grep -A2 LC_VERSION_MIN_MACOSX || true - - name: Build wheels via cibuildwheel - if: matrix.platform != 'macos' - env: + - name: Build wheels via cibuildwheel (Linux cp39-cp313) + if: matrix.platform == 'linux' + env: CIBW_ARCHS_LINUX: ${{ matrix.cibw_archs_linux }} -# CIBW_ARCHS_WINDOWS: ${{ matrix.cibw_archs_windows }} - - CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" CIBW_SKIP: "pp* *-musllinux*" + MACOSX_DEPLOYMENT_TARGET: "12.0" + CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*" + CIBW_MANYLINUX_X86_64_IMAGE: "manylinux2014" + CIBW_MANYLINUX_AARCH64_IMAGE: "manylinux2014" + CIBW_BEFORE_ALL_LINUX: bash .github/scripts/cibw-before-all-linux.sh + CIBW_TEST_COMMAND: > + python -c "import tsfile, tsfile.tsfile_reader as r; print('import-ok:')" + CIBW_BUILD_VERBOSITY: "1" + run: cibuildwheel --output-dir wheelhouse python + - name: Build wheels via cibuildwheel (Linux cp314) + if: matrix.platform == 'linux' + env: + CIBW_ARCHS_LINUX: ${{ matrix.cibw_archs_linux }} + CIBW_SKIP: "pp* *-musllinux*" + MACOSX_DEPLOYMENT_TARGET: "12.0" + CIBW_BUILD: "cp314-*" CIBW_MANYLINUX_X86_64_IMAGE: "manylinux_2_28" CIBW_MANYLINUX_AARCH64_IMAGE: "manylinux_2_28" - - MACOSX_DEPLOYMENT_TARGET: "12.0" - - CIBW_BEFORE_ALL_LINUX: | - set -euxo pipefail - if command -v yum >/dev/null 2>&1; then - yum install -y wget tar gzip pkgconfig libuuid-devel libblkid-devel - else - echo "Not a yum-based image?" ; exit 1 - fi - ARCH="$(uname -m)" - mkdir -p /opt/java - if [ "$ARCH" = "x86_64" ]; then - JDK_URL="https://download.oracle.com/java/17/archive/jdk-17.0.12_linux-x64_bin.tar.gz" - else - # aarch64 - JDK_URL="https://download.oracle.com/java/17/archive/jdk-17.0.12_linux-aarch64_bin.tar.gz" - fi - curl -L -o /tmp/jdk17.tar.gz "$JDK_URL" - tar -xzf /tmp/jdk17.tar.gz -C /opt/java - export JAVA_HOME=$(echo /opt/java/jdk-17.0.12*) - export PATH="$JAVA_HOME/bin:$PATH" - java -version - - chmod +x mvnw || true - ./mvnw -Pwith-cpp clean package \ - -DskipTests -Dbuild.test=OFF \ - -Dspotless.check.skip=true -Dspotless.apply.skip=true - test -d cpp/target/build/lib && test -d cpp/target/build/include - + CIBW_BEFORE_ALL_LINUX: bash .github/scripts/cibw-before-all-linux.sh CIBW_TEST_COMMAND: > python -c "import tsfile, tsfile.tsfile_reader as r; print('import-ok:')" CIBW_BUILD_VERBOSITY: "1" @@ -245,7 +229,7 @@ jobs: uses: msys2/setup-msys2@v2 with: msystem: MINGW64 - update: false + update: true install: >- mingw-w64-x86_64-gcc mingw-w64-x86_64-make @@ -263,7 +247,7 @@ jobs: set -euxo pipefail export JAVA_HOME="$(cygpath "$JAVA_HOME")" export PYTHON_HOME="$(cygpath "$pythonLocation")" - export PATH="$PYTHON_HOME:$PYTHON_HOME/Scripts:$JAVA_HOME/bin:$PATH" + export PATH="/mingw64/bin:$PYTHON_HOME:$PYTHON_HOME/Scripts:$JAVA_HOME/bin:$PATH" # Build wheel via Maven (no clean — keep C++ artifacts from previous job) chmod +x mvnw || true diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 93342c113..8ff564d52 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -160,6 +160,17 @@ endif() add_dependencies(tsfile utils_obj encoding_obj) +# Static-link MinGW runtime on Windows so libtsfile.dll does not depend on +# libstdc++/libgcc DLL versions that may differ across CI runners. +if(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_link_options(tsfile PRIVATE + -static-libgcc + -static-libstdc++ + -Wl,--whole-archive + -lwinpthread + -Wl,--no-whole-archive) +endif() + set(LIBTSFILE_PROJECT_VERSION ${TsFile_CPP_VERSION}) set(LIBTSFILE_SO_VERSION ${TsFile_CPP_VERSION}) set_target_properties(tsfile PROPERTIES VERSION ${LIBTSFILE_PROJECT_VERSION}) diff --git a/cpp/src/utils/util_define.h b/cpp/src/utils/util_define.h index ee96616f1..62739716b 100644 --- a/cpp/src/utils/util_define.h +++ b/cpp/src/utils/util_define.h @@ -95,13 +95,13 @@ typedef int mode_t; #endif /* ======== inline ======== */ -#if defined(__GNUC__) || defined(__clang__) +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MINGW32__) #define FORCE_INLINE inline __attribute__((always_inline)) #elif defined(_MSC_VER) #define FORCE_INLINE __forceinline #else #define FORCE_INLINE inline -#endif // __GNUC__ +#endif #ifdef BUILD_FOR_SMALL_BINARY #define INLINE FORCE_INLINE diff --git a/cpp/third_party/antlr4-cpp-runtime-4/CMakeLists.txt b/cpp/third_party/antlr4-cpp-runtime-4/CMakeLists.txt index 9e293de75..cf20c95dc 100644 --- a/cpp/third_party/antlr4-cpp-runtime-4/CMakeLists.txt +++ b/cpp/third_party/antlr4-cpp-runtime-4/CMakeLists.txt @@ -28,15 +28,37 @@ project(LIBANTLR4) if(CMAKE_VERSION VERSION_EQUAL "3.0.0" OR CMAKE_VERSION VERSION_GREATER "3.0.0") CMAKE_POLICY(SET CMP0026 NEW) - CMAKE_POLICY(SET CMP0054 OLD) - CMAKE_POLICY(SET CMP0045 OLD) - CMAKE_POLICY(SET CMP0042 OLD) + # CMake 4.x no longer allows OLD behavior for these policies. + if(CMAKE_VERSION VERSION_LESS "4.0") + CMAKE_POLICY(SET CMP0054 OLD) + CMAKE_POLICY(SET CMP0045 OLD) + CMAKE_POLICY(SET CMP0042 OLD) + else() + if(POLICY CMP0054) + CMAKE_POLICY(SET CMP0054 NEW) + endif() + if(POLICY CMP0045) + CMAKE_POLICY(SET CMP0045 NEW) + endif() + if(POLICY CMP0042) + CMAKE_POLICY(SET CMP0042 NEW) + endif() + endif() endif() if(CMAKE_VERSION VERSION_EQUAL "3.3.0" OR CMAKE_VERSION VERSION_GREATER "3.3.0") - CMAKE_POLICY(SET CMP0059 OLD) - CMAKE_POLICY(SET CMP0054 OLD) + if(CMAKE_VERSION VERSION_LESS "4.0") + CMAKE_POLICY(SET CMP0059 OLD) + CMAKE_POLICY(SET CMP0054 OLD) + else() + if(POLICY CMP0059) + CMAKE_POLICY(SET CMP0059 NEW) + endif() + if(POLICY CMP0054) + CMAKE_POLICY(SET CMP0054 NEW) + endif() + endif() endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux") diff --git a/cpp/third_party/antlr4-cpp-runtime-4/runtime/CMakeLists.txt b/cpp/third_party/antlr4-cpp-runtime-4/runtime/CMakeLists.txt index a143befb0..f2fd3f421 100644 --- a/cpp/third_party/antlr4-cpp-runtime-4/runtime/CMakeLists.txt +++ b/cpp/third_party/antlr4-cpp-runtime-4/runtime/CMakeLists.txt @@ -61,7 +61,7 @@ else() GIT_TAG "v3.1.1" SOURCE_DIR ${UTFCPP_DIR} UPDATE_DISCONNECTED 1 - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${UTFCPP_DIR}/install -DUTF8_TESTS=off -DUTF8_SAMPLES=off + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${UTFCPP_DIR}/install -DUTF8_TESTS=off -DUTF8_SAMPLES=off -DCMAKE_POLICY_VERSION_MINIMUM=3.5 STEP_TARGETS build ) diff --git a/python/setup.py b/python/setup.py index 19ada7921..24a0ef9ef 100644 --- a/python/setup.py +++ b/python/setup.py @@ -148,9 +148,8 @@ def _find_lib(root, patterns): ) if win_toolchain == "mingw": - # Copy MinGW runtime DLLs next to tsfile.dll so Python can find them. - # Python 3.8+ does not search PATH for DLLs; they must sit in the - # same directory as the .pyd extensions (os.add_dll_directory). + # libtsfile.dll is statically linked against libstdc++/libgcc; copy the + # MinGW runtime used to build the Python extensions from PATH. for _mingw_dll in ( "libstdc++-6.dll", "libgcc_s_seh-1.dll", diff --git a/python/tsfile/__init__.py b/python/tsfile/__init__.py index 1026ec673..d5f106bf8 100644 --- a/python/tsfile/__init__.py +++ b/python/tsfile/__init__.py @@ -22,15 +22,32 @@ _pkg_dir = os.path.dirname(os.path.abspath(__file__)) + +def _preload_dll(path): + if not os.path.isfile(path): + return + try: + ctypes.CDLL(path) + except OSError: + pass + + if sys.platform == "win32": # Keep the handle alive for the lifetime of this module. CPython's reference # counting frees the object immediately if not stored, which calls # RemoveDllDirectory and undoes the registration before any .pyd is loaded. _dll_dir = os.add_dll_directory(_pkg_dir) - # Preload the tsfile DLL so Windows finds it by base-name when loading the - # Cython extensions. Store the handle to prevent the DLL from being - # unloaded prematurely. + # Preload MinGW runtime DLLs used by Python extensions. libtsfile.dll is + # statically linked against libstdc++/libgcc and only needs libwinpthread. + for _mingw_dll in ( + "libwinpthread-1.dll", + "libgcc_s_seh-1.dll", + "libstdc++-6.dll", + ): + _preload_dll(os.path.join(_pkg_dir, _mingw_dll)) + # Preload the tsfile DLL so Windows finds it when loading Cython extensions. # MSVC builds produce "tsfile.dll"; MinGW builds produce "libtsfile.dll". + _tsfile_cdll = None for _dll_name in ("tsfile.dll", "libtsfile.dll"): _tsfile_dll = os.path.join(_pkg_dir, _dll_name) if os.path.isfile(_tsfile_dll):