Skip to content

Commit a7c1202

Browse files
authored
Merge pull request #2522 from SCIInstitute/amorris/manylinux-build
Switch Linux build to manylinux_2_28 for GLIBC 2.28 compatibility with HPC clusters
2 parents b7a709d + c0e8509 commit a7c1202

9 files changed

Lines changed: 85 additions & 38 deletions

File tree

.github/workflows/Dockerfile

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
1-
# Based on old ubuntu to create more compatible binaries
1+
# Based on manylinux_2_28 (AlmaLinux 8, GLIBC 2.28) for maximum HPC compatibility
2+
# Binaries built here will run on RHEL/Rocky/Alma 8+, Ubuntu 20.04+, and most HPC clusters
23

34
# To build (e.g. for ShapeWorks 6.7):
4-
# docker build --progress=plain -t akenmorris/ubuntu-build-box-jammy-sw67 .
5+
# docker build --progress=plain -t akenmorris/manylinux-build-box-sw67 .
56
# To publish:
6-
# docker push akenmorris/ubuntu-build-box-jammy-sw67
7+
# docker push akenmorris/manylinux-build-box-sw67
78

8-
FROM ubuntu:jammy-20250819 AS env
9-
MAINTAINER akenmorris@gmail.com
9+
FROM quay.io/pypa/manylinux_2_28_x86_64 AS env
10+
LABEL maintainer="akenmorris@gmail.com"
1011

1112
# Set environment variables
12-
ENV PATH=/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
13+
ENV PATH=/opt/rh/gcc-toolset-13/root/usr/bin:/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
1314

14-
ARG DEBIAN_FRONTEND=noninteractive
15-
ENV TZ=Etc/UTC
15+
# Enable PowerTools repo for additional development packages
16+
RUN dnf install -y dnf-plugins-core && dnf config-manager --set-enabled powertools
1617

17-
# Update
18-
RUN apt-get update -y && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get install build-essential software-properties-common -y && add-apt-repository ppa:ubuntu-toolchain-r/test -y && apt-get update -y
18+
# Update and install build tools
19+
# gcc-toolset-13 provides GCC 13 with GLIBCXX_3.4.31, required by conda Qt5/ICU packages.
20+
# This keeps GLIBC 2.28 for binary compatibility while providing modern C++ library symbols.
21+
RUN dnf update -y && dnf groupinstall -y "Development Tools" \
22+
&& dnf install -y gcc-toolset-13-gcc gcc-toolset-13-gcc-c++ gcc-toolset-13-binutils gcc-toolset-13-libstdc++-devel
1923

2024
# Install git and git-lfs
21-
RUN add-apt-repository ppa:git-core/ppa
22-
RUN apt-get update
23-
RUN apt-get install git curl -y
24-
RUN curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
25-
RUN apt-get install git-lfs -y
25+
RUN dnf install -y git curl
26+
RUN curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.rpm.sh | bash
27+
RUN dnf install -y git-lfs
2628

2729
# Install other dependencies
28-
RUN apt-get install rsync freeglut3-dev libgl1-mesa-dev libegl1-mesa zip libcups2 pigz wget ccache -y
30+
RUN dnf install -y rsync freeglut-devel mesa-libGL-devel mesa-libEGL-devel zip cups-libs pigz wget ccache
2931

3032
# Install conda
3133
RUN curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o /tmp/Miniconda3-latest-Linux-x86_64.sh \
@@ -38,6 +40,15 @@ RUN curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -
3840
&& echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc \
3941
&& echo "conda activate base" >> ~/.bashrc
4042

43+
# Install modern libstdc++ with GLIBCXX_3.4.30+ required by conda Qt5/ICU packages
44+
# gcc-toolset-13 only provides static libstdc++, so we use conda-forge's libstdcxx-ng
45+
RUN /opt/conda/bin/conda install -y -c conda-forge libstdcxx-ng=13 \
46+
&& LIBSTDCXX=$(ls /opt/conda/lib/libstdc++.so.6.0.* | head -1) \
47+
&& cp -f "$LIBSTDCXX" /usr/lib64/ \
48+
&& rm -f /usr/lib64/libstdc++.so.6 \
49+
&& ln -s $(basename "$LIBSTDCXX") /usr/lib64/libstdc++.so.6 \
50+
&& ldconfig
51+
4152
# Get and decompress linuxdeployqt, it's complicated to use fuse with docker due to the kernel module
4253
RUN curl -L -o $HOME/linuxdeployqt.AppImage https://github.com/probonopd/linuxdeployqt/releases/download/5/linuxdeployqt-5-x86_64.AppImage && chmod +x $HOME/linuxdeployqt.AppImage ; cd $HOME ; ./linuxdeployqt.AppImage --appimage-extract
4354
RUN ln -s /root/squashfs-root/usr/bin/linuxdeployqt /usr/bin

.github/workflows/build-linux-debug.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
build:
2525

2626
runs-on: ubuntu-latest
27-
container: akenmorris/ubuntu-build-box-jammy-sw67
27+
container: akenmorris/manylinux-build-box-sw67
2828

2929
steps:
3030

@@ -66,7 +66,7 @@ jobs:
6666
uses: actions/cache/restore@v3
6767
with:
6868
path: /github/home/install
69-
key: ${{ runner.os }}-deps-debug-${{ hashFiles('.github/workflows/gha_deps.sh', 'install_shapeworks.sh', 'python_requirements.txt', 'build_dependencies.sh') }}
69+
key: ${{ runner.os }}-deps-debug-${{ hashFiles('.github/workflows/Dockerfile', '.github/workflows/gha_deps.sh', 'install_shapeworks.sh', 'python_requirements.txt', 'build_dependencies.sh') }}
7070

7171
- name: Check space3.5
7272
run: df -h
@@ -107,7 +107,7 @@ jobs:
107107
uses: actions/cache/save@v3
108108
with:
109109
path: /github/home/install
110-
key: ${{ runner.os }}-deps-debug-${{ hashFiles('.github/workflows/gha_deps.sh', 'install_shapeworks.sh', 'python_requirements.txt', 'build_dependencies.sh') }}
110+
key: ${{ runner.os }}-deps-debug-${{ hashFiles('.github/workflows/Dockerfile', '.github/workflows/gha_deps.sh', 'install_shapeworks.sh', 'python_requirements.txt', 'build_dependencies.sh') }}
111111

112112
- name: Check space5
113113
run: df -h

.github/workflows/build-linux.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
build:
2626

2727
runs-on: ubuntu-latest
28-
container: akenmorris/ubuntu-build-box-jammy-sw67
28+
container: akenmorris/manylinux-build-box-sw67
2929

3030
steps:
3131

@@ -64,7 +64,7 @@ jobs:
6464
uses: actions/cache/restore@v3
6565
with:
6666
path: /github/home/install
67-
key: ${{ runner.os }}-deps-${{ hashFiles('.github/workflows/gha_deps.sh', 'install_shapeworks.sh', 'python_requirements.txt', 'build_dependencies.sh') }}
67+
key: ${{ runner.os }}-deps-${{ hashFiles('.github/workflows/Dockerfile', '.github/workflows/gha_deps.sh', 'install_shapeworks.sh', 'python_requirements.txt', 'build_dependencies.sh') }}
6868

6969
- name: try import vtk
7070
shell: bash -l {0}
@@ -81,7 +81,7 @@ jobs:
8181
uses: actions/cache/save@v3
8282
with:
8383
path: /github/home/install
84-
key: ${{ runner.os }}-deps-${{ hashFiles('.github/workflows/gha_deps.sh', 'install_shapeworks.sh', 'python_requirements.txt', 'build_dependencies.sh') }}
84+
key: ${{ runner.os }}-deps-${{ hashFiles('.github/workflows/Dockerfile', '.github/workflows/gha_deps.sh', 'install_shapeworks.sh', 'python_requirements.txt', 'build_dependencies.sh') }}
8585

8686
- name: Check space4
8787
run: df -h

.github/workflows/gha_conda.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ else
1313
cd ${GITHUB_WORKSPACE}
1414

1515
# run install
16-
source ./install_shapeworks.sh --developer
16+
source ./install_shapeworks.sh --developer || exit 1
1717
conda clean -p -t -y
1818
pip cache info
1919
pip cache purge

Libs/Python/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
pybind11_add_module(shapeworks_py
1+
# NO_EXTRAS disables LTO which can cause GCC internal compiler errors
2+
pybind11_add_module(shapeworks_py NO_EXTRAS
23
ShapeworksPython.cpp
34
PythonAnalyze.cpp
45
PythonGroom.cpp

Python/shapeworks/shapeworks/network_analysis.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import trimesh
66
import itertools
7-
import open3d as o3d
87
import scipy
98
import spm1d
109
import vtk
@@ -19,6 +18,8 @@
1918
import shapeworks as sw
2019
np.random.seed(0)
2120

21+
# open3d is imported lazily when needed (not available on all platforms)
22+
2223

2324
class NetworkAnalysis:
2425
def __init__(self, project):
@@ -85,6 +86,16 @@ def compute_mean_shape(self):
8586
return mesh_points, mesh_normals, mean_shape, surface
8687

8788
def run(self):
89+
# Import open3d here (lazy import - not available on all platforms)
90+
try:
91+
import open3d as o3d
92+
except ImportError:
93+
raise ImportError(
94+
"open3d is required for network analysis but is not installed. "
95+
"This feature may not be available on your platform/Python version. "
96+
"Try: pip install open3d-cpu (Linux) or pip install open3d (macOS/Windows)"
97+
)
98+
8899
project = self.project
89100
analyze = self.analyze
90101
num_pts = analyze.get_num_particles()

Python/shapeworks/shapeworks/network_analysis_figures.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import trimesh
1111
# import itertools
1212
# import operator
13-
import open3d as o3d
1413
import scipy
1514
# import spm1d
1615
import vtk
@@ -24,11 +23,23 @@
2423
import vedo
2524
import cv2
2625

26+
# open3d is imported lazily when needed (not available on all platforms)
27+
2728
class NetworkAnalysisFigures:
2829
def __init__(self, network_analysis):
2930
self.network_analysis = network_analysis
3031

3132
def run(self):
33+
# Import open3d here (lazy import - not available on all platforms)
34+
try:
35+
import open3d as o3d
36+
except ImportError:
37+
raise ImportError(
38+
"open3d is required for network analysis figures but is not installed. "
39+
"This feature may not be available on your platform/Python version. "
40+
"Try: pip install open3d-cpu (Linux) or pip install open3d (macOS/Windows)"
41+
)
42+
3243
# In[4]:
3344

3445
analyze = self.network_analysis.analyze

Support/package.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ else
138138
linuxdeployqt ShapeWorksStudio -verbose=2
139139
cd ..
140140

141-
rm lib/libxcb* lib/libX* lib/libfont* lib/libfreetype*
141+
# Keep libfreetype as harfbuzz depends on it (FT_Get_Transform requires freetype 2.11+)
142+
rm lib/libxcb* lib/libX* lib/libfont*
142143
rm -rf geometry-central doc
143144
fi
144145

install_shapeworks.sh

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -179,22 +179,34 @@ function install_conda() {
179179
if ! python -m light_the_torch install torch==2.8.0 torchaudio==2.8.0 torchvision==0.23.0; then return 1; fi
180180
fi
181181

182-
# for network analysis
182+
# for network analysis (optional - not available on all platforms/Python versions)
183183
# open3d needs to be installed differently on each platform so it's not part of python_requirements.txt
184+
OPEN3D_INSTALLED=NO
184185
if [[ "$(uname)" == "Linux" ]]; then
185-
if ! pip install open3d-cpu==0.19.0; then return 1; fi
186+
if pip install open3d-cpu==0.19.0; then
187+
OPEN3D_INSTALLED=YES
188+
else
189+
echo "WARNING: open3d-cpu could not be installed. Network analysis features will not be available."
190+
fi
186191
elif [[ "$(uname)" == "Darwin" ]]; then
187-
if ! pip install open3d==0.19.0; then return 1; fi
188-
189-
if [[ "$(uname -m)" == "arm64" ]]; then
190-
pushd $CONDA_PREFIX/lib/python3.12/site-packages/open3d/cpu
191-
install_name_tool -change /opt/homebrew/opt/libomp/lib/libomp.dylib @rpath/libomp.dylib pybind.cpython-312-darwin.so
192-
install_name_tool -add_rpath @loader_path/../../../ pybind.cpython-312-darwin.so
193-
popd
194-
ln -sf "$CONDA_PREFIX/lib/libomp.dylib" "$CONDA_PREFIX/lib/python3.12/site-packages/open3d/cpu/../../../libomp.dylib"
192+
if pip install open3d==0.19.0; then
193+
OPEN3D_INSTALLED=YES
194+
if [[ "$(uname -m)" == "arm64" ]]; then
195+
pushd $CONDA_PREFIX/lib/python3.12/site-packages/open3d/cpu
196+
install_name_tool -change /opt/homebrew/opt/libomp/lib/libomp.dylib @rpath/libomp.dylib pybind.cpython-312-darwin.so
197+
install_name_tool -add_rpath @loader_path/../../../ pybind.cpython-312-darwin.so
198+
popd
199+
ln -sf "$CONDA_PREFIX/lib/libomp.dylib" "$CONDA_PREFIX/lib/python3.12/site-packages/open3d/cpu/../../../libomp.dylib"
200+
fi
201+
else
202+
echo "WARNING: open3d could not be installed. Network analysis features will not be available."
195203
fi
196204
else
197-
if ! pip install open3d==0.19.0; then return 1; fi
205+
if pip install open3d==0.19.0; then
206+
OPEN3D_INSTALLED=YES
207+
else
208+
echo "WARNING: open3d could not be installed. Network analysis features will not be available."
209+
fi
198210
fi
199211

200212
for package in DataAugmentationUtilsPackage DatasetUtilsPackage MONAILabelPackage DeepSSMUtilsPackage DocumentationUtilsPackage ShapeCohortGenPackage shapeworks ; do

0 commit comments

Comments
 (0)