Skip to content

Commit c6cbae6

Browse files
committed
ci: build wheel
1 parent e613828 commit c6cbae6

5 files changed

Lines changed: 364 additions & 60 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Setup Mapnik build env
2+
description: Configure cibuildwheel env vars for Mapnik builds
3+
runs:
4+
using: composite
5+
steps:
6+
- name: Export cibuildwheel env vars
7+
shell: bash
8+
run: |
9+
{
10+
echo "CIBW_BUILD_FRONTEND=pip"
11+
echo "CIBW_ENVIRONMENT_LINUX=PKG_CONFIG_PATH=/usr/lib64/pkgconfig:/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:/opt/lib/pkgconfig:\$PKG_CONFIG_PATH"
12+
echo "CIBW_BEFORE_ALL_LINUX=bash .github/actions/setup-mapnik/setup-manylinux.sh"
13+
} >> "$GITHUB_ENV"
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
BOOST_VER=1.83.0
5+
BOOST_VER_UNDERSCORE=1_83_0
6+
PROJ_VER=9.7.1
7+
GDAL_VER=3.12.1
8+
MAPNIK_VER=4.2.0
9+
10+
log() {
11+
echo ">> $*"
12+
}
13+
14+
has_pkg_config() {
15+
pkg-config --exists "$1" 2>/dev/null
16+
}
17+
18+
find_mapnik_pc() {
19+
log "libmapnik.pc locations (if any):"
20+
find /usr /opt /usr/local -name "libmapnik.pc" -print 2>/dev/null || true
21+
}
22+
23+
install_with_apt() {
24+
mkdir -p /etc/apt/sources.list.d /etc/apt/preferences.d
25+
echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
26+
echo 'Package: *
27+
Pin: release a=sid
28+
Pin-Priority: 100' > /etc/apt/preferences.d/sid
29+
apt-get update
30+
apt-get install -y build-essential pkg-config libbz2-dev
31+
apt-get install -y -t sid libmapnik-dev fonts-noto-cjk
32+
}
33+
34+
detect_dnf() {
35+
if command -v dnf >/dev/null 2>&1; then
36+
echo "dnf"
37+
return
38+
fi
39+
if command -v yum >/dev/null 2>&1; then
40+
echo "yum"
41+
return
42+
fi
43+
return 1
44+
}
45+
46+
prepare_dnf() {
47+
local dnf_bin="$1"
48+
if command -v dnf >/dev/null 2>&1; then
49+
dnf install -y dnf-plugins-core
50+
# Enable repo variants across EL8/EL9.
51+
dnf config-manager --set-enabled powertools || true
52+
dnf config-manager --set-enabled crb || true
53+
else
54+
yum install -y yum-utils || true
55+
fi
56+
"$dnf_bin" install -y epel-release || true
57+
}
58+
59+
install_base_deps_dnf() {
60+
local dnf_bin="$1"
61+
"$dnf_bin" install -y \
62+
bzip2-devel \
63+
gcc gcc-c++ make \
64+
pkgconfig
65+
}
66+
67+
install_fonts_dnf() {
68+
local dnf_bin="$1"
69+
"$dnf_bin" install -y google-noto-sans-cjk-ttc-fonts || \
70+
"$dnf_bin" install -y google-noto-cjk-fonts || \
71+
"$dnf_bin" install -y noto-sans-cjk-fonts || true
72+
}
73+
74+
install_build_deps_dnf() {
75+
local dnf_bin="$1"
76+
"$dnf_bin" install -y \
77+
boost-devel \
78+
freetype-devel \
79+
libpng-devel \
80+
libjpeg-turbo-devel \
81+
libtiff-devel \
82+
libicu-devel \
83+
zlib-devel \
84+
libxml2-devel \
85+
proj-devel \
86+
geos-devel \
87+
gdal-devel \
88+
harfbuzz-devel \
89+
cairo-devel \
90+
libcurl-devel \
91+
sqlite-devel \
92+
json-c-devel \
93+
zstd-devel \
94+
libgeotiff-devel \
95+
git \
96+
curl \
97+
wget \
98+
tar \
99+
cmake
100+
# Optional deps for more Mapnik features; ignore if not available on EL8.
101+
"$dnf_bin" install -y libwebp-devel || true
102+
"$dnf_bin" install -y libavif-devel || true
103+
"$dnf_bin" install -y postgresql-devel || true
104+
"$dnf_bin" install -y expat-devel || true
105+
"$dnf_bin" install -y libqb3-devel || true
106+
"$dnf_bin" install -y glibc-gconv-extra || true
107+
}
108+
109+
python_for_build() {
110+
ls -d /opt/python/cp312-cp312/bin/python /opt/python/cp3*/bin/python | head -1
111+
}
112+
113+
build_boost() {
114+
log "Building Boost ${BOOST_VER}"
115+
local workdir="/tmp/boost-src"
116+
rm -rf "$workdir"
117+
mkdir -p "$workdir"
118+
cd "$workdir"
119+
local tarball="boost_${BOOST_VER_UNDERSCORE}.tar.bz2"
120+
curl -L -o "$tarball" "https://archives.boost.io/release/${BOOST_VER}/source/boost_${BOOST_VER_UNDERSCORE}.tar.bz2"
121+
tar -xjf "$tarball"
122+
cd "boost_${BOOST_VER_UNDERSCORE}"
123+
./bootstrap.sh --prefix=/usr/local --with-libraries=regex,program_options,system,filesystem,thread
124+
if ! ./b2 -d0 --abbreviate-paths -j"$(nproc)" link=shared runtime-link=shared install > /tmp/boost-build.log 2>&1; then
125+
echo "Boost build failed. Last 200 lines:"
126+
tail -200 /tmp/boost-build.log
127+
exit 1
128+
fi
129+
ldconfig
130+
export LD_LIBRARY_PATH="/usr/local/lib:/usr/local/lib64:${LD_LIBRARY_PATH:-}"
131+
}
132+
133+
build_proj() {
134+
log "Building PROJ ${PROJ_VER}"
135+
rm -rf /tmp/proj-src
136+
git -c advice.detachedHead=false clone --depth 1 --branch "${PROJ_VER}" https://github.com/OSGeo/PROJ.git /tmp/proj-src
137+
mkdir -p /tmp/proj-src/build
138+
cd /tmp/proj-src/build
139+
if ! {
140+
cmake /tmp/proj-src \
141+
-DCMAKE_BUILD_TYPE=Release \
142+
-DCMAKE_INSTALL_PREFIX=/usr/local \
143+
-DBUILD_TESTING=OFF \
144+
-DCMAKE_CXX_FLAGS="-Wno-psabi" \
145+
-DENABLE_TIFF=OFF \
146+
--log-level=WARNING
147+
make -s -j"$(nproc)"
148+
make -s install
149+
} > /tmp/proj-build.log 2>&1; then
150+
echo "PROJ build failed. Last 200 lines:"
151+
tail -200 /tmp/proj-build.log
152+
exit 1
153+
fi
154+
ldconfig
155+
}
156+
157+
build_gdal() {
158+
log "Building GDAL ${GDAL_VER}"
159+
rm -rf /tmp/gdal-src
160+
git -c advice.detachedHead=false clone --depth 1 --branch "v${GDAL_VER}" https://github.com/OSGeo/gdal.git /tmp/gdal-src
161+
cd /tmp/gdal-src
162+
git -c advice.detachedHead=false submodule update --init --recursive
163+
mkdir -p /tmp/gdal-src/build
164+
cd /tmp/gdal-src/build
165+
local use_geos=OFF
166+
local use_zstd=OFF
167+
local use_geotiff=OFF
168+
local use_jsonc=OFF
169+
if command -v geos-config >/dev/null 2>&1 || has_pkg_config geos; then
170+
use_geos=ON
171+
fi
172+
if has_pkg_config libzstd || has_pkg_config zstd; then
173+
use_zstd=ON
174+
fi
175+
if has_pkg_config geotiff; then
176+
use_geotiff=ON
177+
fi
178+
if has_pkg_config json-c; then
179+
use_jsonc=ON
180+
fi
181+
if ! {
182+
cmake /tmp/gdal-src \
183+
-DCMAKE_BUILD_TYPE=Release \
184+
-DCMAKE_INSTALL_PREFIX=/usr/local \
185+
-DBUILD_TESTING=OFF \
186+
-DCMAKE_CXX_FLAGS="-Wno-psabi" \
187+
-DGDAL_USE_INTERNAL_LIBS=ON \
188+
-DGDAL_USE_GEOS="${use_geos}" \
189+
-DGDAL_USE_PROJ=ON \
190+
-DGDAL_USE_ZSTD="${use_zstd}" \
191+
-DGDAL_USE_GEOTIFF="${use_geotiff}" \
192+
-DGDAL_USE_JSONC="${use_jsonc}" \
193+
--log-level=WARNING
194+
make -s -j"$(nproc)"
195+
make -s install
196+
} > /tmp/gdal-build.log 2>&1; then
197+
echo "GDAL build failed. Last 200 lines:"
198+
tail -200 /tmp/gdal-build.log
199+
exit 1
200+
fi
201+
ldconfig
202+
}
203+
204+
build_mapnik() {
205+
local pybin="$1"
206+
log "Building Mapnik ${MAPNIK_VER}"
207+
rm -rf /tmp/mapnik-src
208+
git clone --depth 1 --branch "v${MAPNIK_VER}" https://github.com/mapnik/mapnik.git /tmp/mapnik-src
209+
cd /tmp/mapnik-src
210+
git -c advice.detachedHead=false submodule update --init --recursive
211+
mkdir -p /tmp/mapnik-src/build
212+
cd /tmp/mapnik-src/build
213+
if ! {
214+
cmake /tmp/mapnik-src \
215+
-DCMAKE_BUILD_TYPE=Release \
216+
-DCMAKE_INSTALL_PREFIX=/usr/local \
217+
-DBUILD_DEMO_VIEWER=OFF \
218+
-DBUILD_TESTING=OFF \
219+
-DCMAKE_CXX_FLAGS="-Wno-psabi" \
220+
-DWITH_JPEG=ON \
221+
-DWITH_PNG=ON \
222+
-DWITH_TIFF=ON \
223+
-DWITH_WEBP=ON \
224+
-DWITH_AVIF=ON \
225+
-DWITH_PROJ=ON \
226+
-DWITH_GDAL=ON \
227+
-DWITH_CAIRO=ON \
228+
-DWITH_HARFBUZZ=ON \
229+
-DWITH_FREETYPE=ON \
230+
-DWITH_SQLITE=ON \
231+
-DWITH_POSTGRESQL=ON \
232+
--log-level=WARNING
233+
make -s -j"$(nproc)"
234+
make -s install
235+
} > /tmp/mapnik-build.log 2>&1; then
236+
echo "Mapnik build failed. Last 200 lines:"
237+
tail -200 /tmp/mapnik-build.log
238+
exit 1
239+
fi
240+
ldconfig
241+
cd /
242+
}
243+
244+
build_mapnik_from_source() {
245+
local dnf_bin="$1"
246+
log "mapnik-devel not available in enabled repos; building Mapnik from source."
247+
"$dnf_bin" repolist || true
248+
"$dnf_bin" list available "mapnik*" || true
249+
install_build_deps_dnf "$dnf_bin"
250+
251+
local pybin
252+
pybin="$(python_for_build)"
253+
"$pybin" -m pip install --upgrade pip
254+
"$pybin" -m pip install scons
255+
256+
build_boost
257+
build_proj
258+
build_gdal
259+
build_mapnik "$pybin"
260+
}
261+
262+
if command -v apt-get >/dev/null 2>&1; then
263+
log "Using apt-get for Mapnik dependencies."
264+
install_with_apt
265+
elif dnf_bin="$(detect_dnf)"; then
266+
log "Using ${dnf_bin} for Mapnik dependencies."
267+
prepare_dnf "$dnf_bin"
268+
install_base_deps_dnf "$dnf_bin"
269+
if ! "$dnf_bin" install -y mapnik-devel; then
270+
build_mapnik_from_source "$dnf_bin"
271+
fi
272+
install_fonts_dnf "$dnf_bin"
273+
else
274+
echo "No supported package manager found (apt-get or dnf/yum)." >&2
275+
exit 1
276+
fi
277+
278+
find_mapnik_pc

0 commit comments

Comments
 (0)