Skip to content

Commit 2c97faa

Browse files
authored
Merge pull request #5 from caiyunapp/ci/release
ci: build wheel
2 parents e613828 + eb41631 commit 2c97faa

13 files changed

Lines changed: 1073 additions & 301 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: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
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+
HARFBUZZ_VER=12.3.0
9+
MAPNIK_VER=4.2.0
10+
11+
log() {
12+
echo ">> $*"
13+
}
14+
15+
has_pkg_config() {
16+
pkg-config --exists "$1" 2>/dev/null
17+
}
18+
19+
version_ge() {
20+
[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
21+
}
22+
23+
has_pkg_config_version() {
24+
local name="$1"
25+
local min_version="$2"
26+
local version
27+
version="$(pkg-config --modversion "$name" 2>/dev/null || true)"
28+
[ -n "$version" ] && version_ge "$version" "$min_version"
29+
}
30+
31+
find_mapnik_pc() {
32+
log "libmapnik.pc locations (if any):"
33+
find /usr /opt /usr/local -name "libmapnik.pc" -print 2>/dev/null || true
34+
}
35+
36+
install_with_apt() {
37+
mkdir -p /etc/apt/sources.list.d /etc/apt/preferences.d
38+
echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
39+
echo 'Package: *
40+
Pin: release a=sid
41+
Pin-Priority: 100' > /etc/apt/preferences.d/sid
42+
apt-get update
43+
# Install base build dependencies including OpenSSL and Boost
44+
apt-get install -y \
45+
build-essential \
46+
pkg-config \
47+
libbz2-dev \
48+
libssl-dev \
49+
libboost-dev \
50+
libboost-filesystem-dev \
51+
libboost-program-options-dev \
52+
libboost-regex-dev \
53+
libboost-system-dev
54+
# Install Mapnik from sid (this will pull in most other dependencies)
55+
apt-get install -y -t sid libmapnik-dev
56+
}
57+
58+
detect_dnf() {
59+
if command -v dnf >/dev/null 2>&1; then
60+
echo "dnf"
61+
return
62+
fi
63+
if command -v yum >/dev/null 2>&1; then
64+
echo "yum"
65+
return
66+
fi
67+
return 1
68+
}
69+
70+
prepare_dnf() {
71+
local dnf_bin="$1"
72+
if command -v dnf >/dev/null 2>&1; then
73+
dnf install -y dnf-plugins-core
74+
# Enable repo variants across EL8/EL9.
75+
dnf config-manager --set-enabled powertools || true
76+
dnf config-manager --set-enabled crb || true
77+
else
78+
yum install -y yum-utils || true
79+
fi
80+
"$dnf_bin" install -y epel-release || true
81+
}
82+
83+
install_base_deps_dnf() {
84+
local dnf_bin="$1"
85+
"$dnf_bin" install -y \
86+
bzip2-devel \
87+
gcc gcc-c++ make \
88+
pkgconfig \
89+
openssl-devel
90+
}
91+
92+
install_build_deps_dnf() {
93+
local dnf_bin="$1"
94+
"$dnf_bin" install -y \
95+
boost-devel \
96+
freetype-devel \
97+
libpng-devel \
98+
libjpeg-turbo-devel \
99+
libtiff-devel \
100+
libicu-devel \
101+
zlib-devel \
102+
libxml2-devel \
103+
proj-devel \
104+
geos-devel \
105+
gdal-devel \
106+
harfbuzz-devel \
107+
cairo-devel \
108+
libcurl-devel \
109+
sqlite-devel \
110+
json-c-devel \
111+
libgeotiff-devel \
112+
git \
113+
curl \
114+
wget \
115+
tar \
116+
cmake \
117+
xz
118+
# Optional deps for more Mapnik features; ignore if not available on EL8.
119+
"$dnf_bin" install -y zstd-devel || true
120+
"$dnf_bin" install -y libwebp-devel || true
121+
"$dnf_bin" install -y libavif-devel || true
122+
"$dnf_bin" install -y postgresql-devel || true
123+
"$dnf_bin" install -y expat-devel || true
124+
"$dnf_bin" install -y libqb3-devel || true
125+
"$dnf_bin" install -y glibc-gconv-extra || true
126+
}
127+
128+
python_for_build() {
129+
ls -d /opt/python/cp312-cp312/bin/python /opt/python/cp3*/bin/python | head -1
130+
}
131+
132+
build_boost() {
133+
log "Building Boost ${BOOST_VER}"
134+
local workdir="/tmp/boost-src"
135+
rm -rf "$workdir"
136+
mkdir -p "$workdir"
137+
cd "$workdir"
138+
local tarball="boost_${BOOST_VER_UNDERSCORE}.tar.bz2"
139+
curl -L -o "$tarball" "https://archives.boost.io/release/${BOOST_VER}/source/boost_${BOOST_VER_UNDERSCORE}.tar.bz2"
140+
tar -xjf "$tarball"
141+
cd "boost_${BOOST_VER_UNDERSCORE}"
142+
./bootstrap.sh --prefix=/usr/local --with-libraries=regex,program_options,system,filesystem,thread,url,context
143+
if ! ./b2 -d0 --abbreviate-paths -j"$(nproc)" link=shared runtime-link=shared install > /tmp/boost-build.log 2>&1; then
144+
echo "Boost build failed. Last 200 lines:"
145+
tail -200 /tmp/boost-build.log
146+
exit 1
147+
fi
148+
ldconfig
149+
export LD_LIBRARY_PATH="/usr/local/lib:/usr/local/lib64:${LD_LIBRARY_PATH:-}"
150+
}
151+
152+
build_proj() {
153+
log "Building PROJ ${PROJ_VER}"
154+
rm -rf /tmp/proj-src
155+
git -c advice.detachedHead=false clone --depth 1 --branch "${PROJ_VER}" https://github.com/OSGeo/PROJ.git /tmp/proj-src
156+
mkdir -p /tmp/proj-src/build
157+
cd /tmp/proj-src/build
158+
if ! {
159+
cmake /tmp/proj-src \
160+
-DCMAKE_BUILD_TYPE=Release \
161+
-DCMAKE_INSTALL_PREFIX=/usr/local \
162+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
163+
-DCMAKE_C_FLAGS="-fPIC" \
164+
-DCMAKE_CXX_FLAGS="-Wno-psabi -fPIC" \
165+
-DBUILD_SHARED_LIBS=ON \
166+
-DBUILD_TESTING=OFF \
167+
-DENABLE_TIFF=OFF \
168+
--log-level=WARNING
169+
make -s -j"$(nproc)"
170+
make -s install
171+
} > /tmp/proj-build.log 2>&1; then
172+
echo "PROJ build failed. Last 200 lines:"
173+
tail -200 /tmp/proj-build.log
174+
exit 1
175+
fi
176+
ldconfig
177+
}
178+
179+
build_harfbuzz() {
180+
log "Building HarfBuzz ${HARFBUZZ_VER}"
181+
local workdir="/tmp/harfbuzz-src"
182+
rm -rf "$workdir"
183+
mkdir -p "$workdir"
184+
cd "$workdir"
185+
local tarball="harfbuzz-${HARFBUZZ_VER}.tar.xz"
186+
curl -L -o "$tarball" "https://github.com/harfbuzz/harfbuzz/releases/download/${HARFBUZZ_VER}/harfbuzz-${HARFBUZZ_VER}.tar.xz"
187+
tar -xJf "$tarball"
188+
cd "harfbuzz-${HARFBUZZ_VER}"
189+
mkdir -p build
190+
cd build
191+
if ! {
192+
cmake .. \
193+
-DCMAKE_BUILD_TYPE=Release \
194+
-DCMAKE_INSTALL_PREFIX=/usr/local \
195+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
196+
-DCMAKE_C_FLAGS="-fPIC" \
197+
-DCMAKE_CXX_FLAGS="-fPIC" \
198+
-DBUILD_SHARED_LIBS=ON \
199+
-DHB_HAVE_FREETYPE=ON \
200+
-DHB_BUILD_TESTS=OFF \
201+
-DHB_BUILD_UTILS=OFF \
202+
-DHB_BUILD_SUBSET=OFF \
203+
--log-level=WARNING
204+
make -s -j"$(nproc)"
205+
make -s install
206+
} > /tmp/harfbuzz-build.log 2>&1; then
207+
echo "HarfBuzz build failed. Last 200 lines:"
208+
tail -200 /tmp/harfbuzz-build.log
209+
exit 1
210+
fi
211+
ldconfig
212+
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/local/share/pkgconfig:${PKG_CONFIG_PATH:-}"
213+
}
214+
215+
build_gdal() {
216+
log "Building GDAL ${GDAL_VER}"
217+
rm -rf /tmp/gdal-src
218+
git -c advice.detachedHead=false clone --depth 1 --branch "v${GDAL_VER}" https://github.com/OSGeo/gdal.git /tmp/gdal-src
219+
cd /tmp/gdal-src
220+
git -c advice.detachedHead=false submodule update --init --recursive
221+
mkdir -p /tmp/gdal-src/build
222+
cd /tmp/gdal-src/build
223+
local use_geos=OFF
224+
local geos_dir=""
225+
local use_zstd=OFF
226+
local use_geotiff=OFF
227+
local use_jsonc=OFF
228+
if command -v geos-config >/dev/null 2>&1 && has_pkg_config geos; then
229+
use_geos=ON
230+
geos_dir="$(geos-config --prefix)"
231+
fi
232+
if has_pkg_config libzstd || has_pkg_config zstd; then
233+
use_zstd=ON
234+
fi
235+
if has_pkg_config geotiff; then
236+
use_geotiff=ON
237+
fi
238+
if has_pkg_config json-c; then
239+
use_jsonc=ON
240+
fi
241+
if ! {
242+
cmake /tmp/gdal-src \
243+
-DCMAKE_BUILD_TYPE=Release \
244+
-DCMAKE_INSTALL_PREFIX=/usr/local \
245+
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
246+
-DCMAKE_C_FLAGS="-fPIC" \
247+
-DCMAKE_CXX_FLAGS="-Wno-psabi -fPIC" \
248+
-DBUILD_SHARED_LIBS=ON \
249+
-DBUILD_TESTING=OFF \
250+
-DBUILD_PYTHON_BINDINGS=OFF \
251+
-DGDAL_BUILD_PYTHON_BINDINGS=OFF \
252+
-DGDAL_ENABLE_PYTHON=OFF \
253+
-DGDAL_USE_INTERNAL_LIBS=ON \
254+
-DGDAL_USE_GEOS="${use_geos}" \
255+
-DGEOS_DIR="${geos_dir}" \
256+
-DGDAL_USE_PROJ=ON \
257+
-DGDAL_USE_ZSTD="${use_zstd}" \
258+
-DGDAL_USE_GEOTIFF="${use_geotiff}" \
259+
-DGDAL_USE_JSONC="${use_jsonc}" \
260+
--log-level=WARNING
261+
make -s -j"$(nproc)"
262+
make -s install
263+
} > /tmp/gdal-build.log 2>&1; then
264+
echo "GDAL build failed. Last 200 lines:"
265+
tail -200 /tmp/gdal-build.log
266+
exit 1
267+
fi
268+
ldconfig
269+
}
270+
271+
build_mapnik() {
272+
local pybin="$1"
273+
log "Building Mapnik ${MAPNIK_VER}"
274+
rm -rf /tmp/mapnik-src
275+
git clone --depth 1 --branch "v${MAPNIK_VER}" https://github.com/mapnik/mapnik.git /tmp/mapnik-src
276+
cd /tmp/mapnik-src
277+
git -c advice.detachedHead=false submodule update --init --recursive
278+
mkdir -p /tmp/mapnik-src/build
279+
cd /tmp/mapnik-src/build
280+
local use_harfbuzz=OFF
281+
if has_pkg_config_version harfbuzz 8.3.0; then
282+
use_harfbuzz=ON
283+
fi
284+
if ! {
285+
cmake /tmp/mapnik-src \
286+
-DCMAKE_BUILD_TYPE=Release \
287+
-DCMAKE_INSTALL_PREFIX=/usr/local \
288+
-DBUILD_DEMO_VIEWER=OFF \
289+
-DBUILD_TESTING=OFF \
290+
-DCMAKE_CXX_FLAGS="-Wno-psabi" \
291+
-DWITH_JPEG=ON \
292+
-DWITH_PNG=ON \
293+
-DWITH_TIFF=ON \
294+
-DWITH_WEBP=ON \
295+
-DWITH_AVIF=ON \
296+
-DWITH_PROJ=ON \
297+
-DWITH_GDAL=ON \
298+
-DWITH_CAIRO=ON \
299+
-DWITH_HARFBUZZ="${use_harfbuzz}" \
300+
-DWITH_FREETYPE=ON \
301+
-DWITH_SQLITE=ON \
302+
-DWITH_POSTGRESQL=ON \
303+
--log-level=WARNING
304+
make -s -j"$(nproc)"
305+
make -s install
306+
} > /tmp/mapnik-build.log 2>&1; then
307+
echo "Mapnik build failed. Last 200 lines:"
308+
tail -200 /tmp/mapnik-build.log
309+
exit 1
310+
fi
311+
ldconfig
312+
cd /
313+
}
314+
315+
build_mapnik_from_source() {
316+
local dnf_bin="$1"
317+
log "mapnik-devel not available in enabled repos; building Mapnik from source."
318+
"$dnf_bin" repolist || true
319+
"$dnf_bin" list available "mapnik*" || true
320+
install_build_deps_dnf "$dnf_bin"
321+
322+
local pybin
323+
pybin="$(python_for_build)"
324+
"$pybin" -m pip install --upgrade pip
325+
"$pybin" -m pip install scons
326+
327+
build_boost
328+
build_proj
329+
if ! has_pkg_config_version harfbuzz 8.3.0; then
330+
build_harfbuzz
331+
fi
332+
build_gdal
333+
build_mapnik "$pybin"
334+
}
335+
336+
if command -v apt-get >/dev/null 2>&1; then
337+
log "Using apt-get for Mapnik dependencies."
338+
install_with_apt
339+
elif dnf_bin="$(detect_dnf)"; then
340+
log "Using ${dnf_bin} for Mapnik dependencies."
341+
prepare_dnf "$dnf_bin"
342+
install_base_deps_dnf "$dnf_bin"
343+
if ! "$dnf_bin" install -y mapnik-devel; then
344+
build_mapnik_from_source "$dnf_bin"
345+
fi
346+
else
347+
echo "No supported package manager found (apt-get or dnf/yum)." >&2
348+
exit 1
349+
fi
350+
351+
find_mapnik_pc

0 commit comments

Comments
 (0)