diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index c3270410..00295e0e 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -89,9 +89,82 @@ jobs: name: python-wheels-${{ matrix.os }}-${{ matrix.python-version }} path: ./bazel-bin/*.whl + build_wheels_for_legacy_systems: + runs-on: ${{ matrix.os }} + needs: [create_version] + strategy: + fail-fast: true + matrix: + os: [ubuntu-22.04] + python-version: ['3.10', '3.11', '3.12', '3.13'] + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4 + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v5 + with: + python-version: ${{ matrix.python-version }} + + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: version-file + path: version + + + - name: Set Python Version + env: + TARGET_PYTHON: ${{ matrix.python-version }} + run: | + echo "set version to ${TARGET_PYTHON}" + python _update_bazel_py_version.py $TARGET_PYTHON + + - name: build custom C++ toolchain + env: + TARGET_PYTHON: ${{ matrix.python-version }} + run: | + . devtools/build_with_custom_toolchain.sh + + + - name: Set up Bazel + uses: bazel-contrib/setup-bazel@083175551ceeceebc757ebee2127fde78840ca77 # 0.18.0 + with: + bazelisk-cache: true + disk-cache: ${{ github.workflow }} + repository-cache: true + + + - name: Build package + env: + TARGET_PYTHON: ${{ matrix.python-version }} + run: | + export GLIBC_VERSION=2_28 + echo $GLIBC_VERSION + sed "s/^MANYLINUX_VERSION.*/MANYLINUX_VERSION=\"manylinux_${GLIBC_VERSION}_x86_64.manylinux2014_x86_64\"/" BUILD -i || true + bazel build --define GLIBC_VERSION=$GLIBC_VERSION --define TARGET_VERSION="$(python -c "print(\"py${TARGET_PYTHON}\".replace(\".\", \"\"))")" --define VERSION="$(cat version/version.txt)" :tesseract_decoder_wheel + + + - name: Test + run: | + pip install pytest sinter auditwheel + + auditwheel show $(ls bazel-bin/*.whl) + + pip install bazel-bin/*.whl + + mv src/py/ src/_lib # rename because `py` causes pytest issues. + rm src/_lib/stub_test.py # ignore this test because it uses os flags that are set by bazel + rm src/_lib/tesseract_sinter_compat_test.py # ignore this test because it mixes np.int64 and int which doesn't work with older python versions + + PYTHONPATH=src/_lib/::$PYTHONPATH pytest src/_lib/ + + + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + with: + name: python-wheels-${{ matrix.os }}-${{ matrix.python-version }}-legacy + path: ./bazel-bin/*.whl + release-wheels: name: Publish all wheels - needs: [build_wheels] + needs: [build_wheels,build_wheels_for_legacy_systems] runs-on: ubuntu-24.04 steps: diff --git a/MODULE.bazel b/MODULE.bazel index dc2140ef..7291bf4c 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,9 +1,9 @@ module(name = "tesseract", version = "1.0") -bazel_dep(name = "bazel_skylib", version = "1.7.1") -bazel_dep(name = "platforms", version = "0.0.10") -bazel_dep(name = "rules_python", version = "0.40.0") -bazel_dep(name = "rules_cc", version = "0.0.17") +bazel_dep(name = "bazel_skylib", version = "1.9.0") +bazel_dep(name = "platforms", version = "1.0.0") +bazel_dep(name = "rules_python", version = "1.9.0") +bazel_dep(name = "rules_cc", version = "0.2.17") bazel_dep(name = "pybind11_bazel", version = "2.13.6") DEFAULT_PYTHON_VERSION = "3.13" @@ -29,3 +29,76 @@ pip.parse( ) use_repo(pip, "pypi") + +http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") +bazel_dep(name = "zlib", version = "1.3.2") + +HIGHS_VERSION = "1.9.0" +HIGHS_SHA_256 = "dff575df08d88583c109702c7c5c75ff6e51611e6eacca8b5b3fdfba8ecc2cb4" + +git_repository( + name = "stim", + commit = "bd60b73525fd5a9b30839020eb7554ad369e4337", + remote = "https://github.com/quantumlib/stim.git", + shallow_since = "1741128853 +0000", +) + +http_archive( + name = "highs", + sha256 = HIGHS_SHA_256, + build_file = "//external:highs.BUILD", + strip_prefix = "HiGHS-" + HIGHS_VERSION, + urls = ["https://github.com/ERGO-Code/HiGHS/archive/refs/tags/v" + HIGHS_VERSION + ".tar.gz"], +) + +GTEST_VERSION = "1.13.0" + +GTEST_SHA256 = "ad7fdba11ea011c1d925b3289cf4af2c66a352e18d4c7264392fead75e919363" + +http_archive( + name = "gtest", + sha256 = GTEST_SHA256, + strip_prefix = "googletest-%s" % GTEST_VERSION, + urls = ["https://github.com/google/googletest/archive/refs/tags/v%s.tar.gz" % GTEST_VERSION], +) + +ARGPARSE_SHA_256 = "3e5a59ab7688dcd1f918bc92051a10564113d4f36c3bbed3ef596c25e519a062" + +http_archive( + name = "argparse", + build_file = "//external:argparse.BUILD", + sha256 = ARGPARSE_SHA_256, + strip_prefix = "argparse-3.1", + urls = ["https://github.com/p-ranav/argparse/archive/refs/tags/v3.1.zip"], +) + +git_repository( + name = "nlohmann_json", + commit = "9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03", + remote = "https://github.com/nlohmann/json.git", + shallow_since = "1701207391 +0100", +) + + + + +BOOST_VERSION = "1.83.0" +BOOST_ARCHIVE_NAME = "boost_{}".format(BOOST_VERSION.replace(".", "_")) + +http_archive( + name = "boost", + urls = [ + "https://archives.boost.io/release/{}/source/{}.tar.gz".format( + BOOST_VERSION, + BOOST_ARCHIVE_NAME, + ) + ], + strip_prefix = BOOST_ARCHIVE_NAME, + sha256 = "c0685b68dd44cc46574cce86c4e17c0f611b15e195be9848dfd0769a0a207628", + build_file = "//external:boost.BUILD", +) + +cc_compatibility_proxy = use_extension("@rules_cc//cc:extensions.bzl", "compatibility_proxy") +use_repo(cc_compatibility_proxy, "cc_compatibility_proxy") + diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index aba6cd30..00000000 --- a/WORKSPACE +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2025 Google LLC -# -# Licensed 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. - -load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -HIGHS_VERSION = "1.9.0" -HIGHS_SHA_256 = "dff575df08d88583c109702c7c5c75ff6e51611e6eacca8b5b3fdfba8ecc2cb4" - -git_repository( - name = "stim", - commit = "bd60b73525fd5a9b30839020eb7554ad369e4337", - remote = "https://github.com/quantumlib/stim.git", - shallow_since = "1741128853 +0000", -) - -http_archive( - name = "highs", - sha256 = HIGHS_SHA_256, - build_file = "//external:highs.BUILD", - strip_prefix = "HiGHS-" + HIGHS_VERSION, - urls = ["https://github.com/ERGO-Code/HiGHS/archive/refs/tags/v" + HIGHS_VERSION + ".tar.gz"], -) - -GTEST_VERSION = "1.13.0" - -GTEST_SHA256 = "ad7fdba11ea011c1d925b3289cf4af2c66a352e18d4c7264392fead75e919363" - -http_archive( - name = "gtest", - sha256 = GTEST_SHA256, - strip_prefix = "googletest-%s" % GTEST_VERSION, - urls = ["https://github.com/google/googletest/archive/refs/tags/v%s.tar.gz" % GTEST_VERSION], -) - -ARGPARSE_SHA_256 = "3e5a59ab7688dcd1f918bc92051a10564113d4f36c3bbed3ef596c25e519a062" - -http_archive( - name = "argparse", - build_file = "//external:argparse.BUILD", - sha256 = ARGPARSE_SHA_256, - strip_prefix = "argparse-3.1", - urls = ["https://github.com/p-ranav/argparse/archive/refs/tags/v3.1.zip"], -) - -git_repository( - name = "nlohmann_json", - commit = "9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03", - remote = "https://github.com/nlohmann/json.git", - shallow_since = "1701207391 +0100", -) - -http_archive( - name = "platforms", - urls = ["https://github.com/bazelbuild/platforms/archive/refs/tags/0.0.6.zip"], - strip_prefix = "platforms-0.0.6", -) - - - - -BOOST_VERSION = "1.83.0" -BOOST_ARCHIVE_NAME = "boost_{}".format(BOOST_VERSION.replace(".", "_")) - -http_archive( - name = "boost", - urls = [ - "https://archives.boost.io/release/{}/source/{}.tar.gz".format( - BOOST_VERSION, - BOOST_ARCHIVE_NAME, - ) - ], - strip_prefix = BOOST_ARCHIVE_NAME, - sha256 = "c0685b68dd44cc46574cce86c4e17c0f611b15e195be9848dfd0769a0a207628", - build_file = "//external:boost.BUILD", -) \ No newline at end of file diff --git a/devtools/build_with_custom_toolchain.sh b/devtools/build_with_custom_toolchain.sh new file mode 100644 index 00000000..228dc2b5 --- /dev/null +++ b/devtools/build_with_custom_toolchain.sh @@ -0,0 +1,71 @@ +# 1. Start a temporary background container named 'sysroot-builder' +docker run -d --name sysroot-builder debian:10 sleep 3600 + +# 2. Run the installation and packaging process inside the container +docker exec sysroot-builder bash -c " + sed 's/deb.debian.org/archive.debian.org/g' /etc/apt/sources.list -i + + apt-get update && apt-get upgrade -y && apt-get install -y build-essential libc6-dev symlinks apt-utils + + # Convert absolute symlinks to relative (CRITICAL so Clang doesn't read your host OS files) + symlinks -rc /lib /usr/lib /usr/include + + # Create the staging directory + mkdir -p /sysroot/usr/lib /sysroot/usr/include /sysroot/lib /sysroot/lib64 + + ldd --version + + # Copy files while preserving symlinks (-a) + cp -a /usr/include/* /sysroot/usr/include/ + cp -a /usr/lib/* /sysroot/usr/lib/ + cp -a /lib/* /sysroot/lib/ 2>/dev/null || true + cp -a /lib64/* /sysroot/lib64/ 2>/dev/null || true + + # Create a tarball inside the container + cd /sysroot && tar -czf /sysroot.tar.gz . +" + +# 3. Copy the tarball from the container directly to your host machine +docker cp sysroot-builder:/sysroot.tar.gz ./sysroot.tar.gz + +# 4. Extract the contents into your project and clean up +mkdir -p custom_sysroot +tar -xzf sysroot.tar.gz -C custom_sysroot +rm sysroot.tar.gz +docker rm -f sysroot-builder +ls -l -R custom_sysroot + +# create custom_sysroot/BUILD +echo """filegroup( + name = \"sysroot\", + srcs = glob([\"**/*\"]), + visibility = [\"//visibility:public\"], +)""" > custom_sysroot/BUILD + +# update MODULE.bazel to use the custom toolchain +echo """bazel_dep(name = \"toolchains_llvm\", version = \"1.6.0\") + +llvm = use_extension(\"@toolchains_llvm//toolchain/extensions:llvm.bzl\", \"llvm\") +llvm.toolchain( + name = \"llvm_toolchain\", + llvm_version = \"17.0.6\", +) + +llvm.sysroot( + name = \"llvm_toolchain\", + label = \"//custom_sysroot:sysroot\", + targets = [\"linux-x86_64\"], +) +use_repo(llvm, \"llvm_toolchain\") + +register_toolchains(\"@llvm_toolchain//:all\") +""" >> MODULE.bazel + + +sudo apt-get update +sudo apt-get install -y libxml2 + +cd custom_sysroot/lib64/ +rm -f ld-linux-x86-64.so.2 +ln -s ../lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ld-linux-x86-64.so.2 +cd ../..