Skip to content

Commit 221722f

Browse files
committed
setup libsqlite3-dev and sqlite3 binary to match stack's libsqlite3-0
With inspiration from @KevinBrolly, this patch uses the stack image SQLite3 package but also still providing the dev headers and binary that users may still be using today. The benefit is that we won't need to rebuild all the python binaries for this to take affect. We can just stop shipping SQLite3 from future binaries. In addition, we don't need to worry about what version and when to update SQLite3 and maintaining the packages ourselves. This also includes updates to Python 2.7.15 and Python 3.6.6 so they can rebuilt with the stack image dev headers instead of building our own vendored SQLite3.
1 parent e82f1e4 commit 221722f

File tree

7 files changed

+146
-4
lines changed

7 files changed

+146
-4
lines changed

bin/compile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ cp -R "$CACHE_DIR/.heroku/python" .heroku/ &> /dev/null || true
160160
cp -R "$CACHE_DIR/.heroku/python-stack" .heroku/ &> /dev/null || true
161161
# A plain text file which contains the current python version being used (used for cache busting).
162162
cp -R "$CACHE_DIR/.heroku/python-version" .heroku/ &> /dev/null || true
163+
# A plain text file which contains the current sqlite3 version being used (used for cache busting).
164+
cp -R "$CACHE_DIR/.heroku/python-sqlite3-version" .heroku/ &> /dev/null || true
163165
# Any pre-compiled binaries, provided by the buildpack.
164166
cp -R "$CACHE_DIR/.heroku/vendor" .heroku/ &> /dev/null || true
165167
# "editable" installations of code repositories, via pip or pipenv.
@@ -274,6 +276,16 @@ sub_env "$BIN_DIR/steps/geo-libs"
274276
# shellcheck source=bin/steps/gdal
275277
source "$BIN_DIR/steps/gdal"
276278

279+
# SQLite3 support.
280+
# This sets up and installs sqlite3 dev headers and the sqlite3 binary but not the
281+
# libsqlite3-0 library since that exists on the stack image.
282+
# Note: This only applies to Python 2.7.15+ and Python 3.6.6+
283+
(( start=$(nowms) ))
284+
# shellcheck source=bin/steps/sqlite3
285+
source "$BIN_DIR/steps/sqlite3"
286+
buildpack_sqlite3_install
287+
mtime "sqlite3.install.time" "${start}"
288+
277289
# pip install
278290
# -----------
279291

bin/steps/python

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,15 @@ fi
2929

3030
if [[ "$STACK" != "$CACHED_PYTHON_STACK" ]]; then
3131
puts-step "Stack has changed from $CACHED_PYTHON_STACK to $STACK, clearing cache"
32-
rm -fr .heroku/python-stack .heroku/python-version .heroku/python .heroku/vendor
32+
rm -fr .heroku/python-stack .heroku/python-version .heroku/python .heroku/vendor .heroku/python .heroku/python-sqlite3-version
33+
fi
34+
35+
# need to clear the cache for first time installing SQLite3,
36+
# since the version is changing and could lead to runtime errors
37+
# with compiled extensions.
38+
if [ -d .heroku/python ] && [ ! -f .heroku/python-sqlite3-version ] && python_sqlite3_check "$PYTHON_VERSION"; then
39+
puts-step "Need to update SQLite3, clearing cache"
40+
rm -fr .heroku/python-stack .heroku/python-version .heroku/python .heroku/vendor
3341
fi
3442

3543
if [ -f .heroku/python-version ]; then

bin/steps/sqlite3

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/usr/bin/env bash
2+
3+
# shellcheck source=bin/utils
4+
source "$BIN_DIR/utils"
5+
6+
sqlite3_version() {
7+
SQLITE3_VERSION=${SQLITE3_VERSION:-$(dpkg -s libsqlite3-0 | grep Version | sed 's/Version: //')}
8+
9+
export SQLITE3_VERSION
10+
}
11+
12+
sqlite3_install() {
13+
HEROKU_PYTHON_DIR="$1"
14+
SQLITE3_VERSION="$2"
15+
HEADERS_ONLY="$3"
16+
17+
mkdir -p "$HEROKU_PYTHON_DIR"
18+
19+
APT_CACHE_DIR="$HEROKU_PYTHON_DIR/apt/cache"
20+
APT_STATE_DIR="$HEROKU_PYTHON_DIR/apt/state"
21+
22+
mkdir -p "$APT_CACHE_DIR/archives/partial"
23+
mkdir -p "$APT_STATE_DIR/lists/partial"
24+
25+
APT_OPTIONS="-o debug::nolocking=true"
26+
APT_OPTIONS="$APT_OPTIONS -o dir::cache=$APT_CACHE_DIR"
27+
APT_OPTIONS="$APT_OPTIONS -o dir::state=$APT_STATE_DIR"
28+
APT_OPTIONS="$APT_OPTIONS -o dir::etc::sourcelist=/etc/apt/sources.list"
29+
30+
apt-get $APT_OPTIONS update > /dev/null 2>&1
31+
if [ -z "$HEADERS_ONLY" ]; then
32+
apt-get $APT_OPTIONS -y -d --reinstall install libsqlite3-dev="$SQLITE3_VERSION" sqlite3="$SQLITE3_VERSION" > /dev/null 2>&1
33+
else
34+
apt-get $APT_OPTIONS -y -d --reinstall install libsqlite3-dev="$SQLITE3_VERSION"
35+
fi
36+
37+
find "$APT_CACHE_DIR/archives/" -name "*.deb" -exec dpkg -x {} "$HEROKU_PYTHON_DIR/sqlite3/" \;
38+
39+
mkdir -p "$HEROKU_PYTHON_DIR/include"
40+
mkdir -p "$HEROKU_PYTHON_DIR/lib"
41+
42+
# remove old sqlite3 libraries/binaries
43+
find "$HEROKU_PYTHON_DIR/include/" -name "sqlite3*.h" -exec rm -f {} \;
44+
find "$HEROKU_PYTHON_DIR/lib/" -name "libsqlite3.*" -exec rm -f {} \;
45+
rm -f "$HEROKU_PYTHON_DIR/lib/pkgconfig/sqlite3.pc"
46+
rm -f "$HEROKU_PYTHON_DIR/bin/sqlite3"
47+
48+
# copy over sqlite3 headers & bins and setup linking against the stack image library
49+
mv "$HEROKU_PYTHON_DIR/sqlite3/usr/include/"* "$HEROKU_PYTHON_DIR/include/"
50+
mv "$HEROKU_PYTHON_DIR/sqlite3/usr/lib/x86_64-linux-gnu"/libsqlite3.*a "$HEROKU_PYTHON_DIR/lib/"
51+
mkdir -p "$HEROKU_PYTHON_DIR/lib/pkgconfig"
52+
# set the right prefix/lib directories
53+
sed -e 's/prefix=\/usr/prefix=\/app\/.heroku\/python/' -e 's/\/x86_64-linux-gnu//' "$HEROKU_PYTHON_DIR/sqlite3/usr/lib/x86_64-linux-gnu/pkgconfig/sqlite3.pc" > "$HEROKU_PYTHON_DIR/lib/pkgconfig/sqlite3.pc"
54+
# need to point the libsqlite3.so to the stack image library for /usr/bin/ld -lsqlite3
55+
SQLITE3_LIBFILE="/usr/lib/x86_64-linux-gnu/$(readlink -n "$HEROKU_PYTHON_DIR/sqlite3/usr/lib/x86_64-linux-gnu/libsqlite3.so")"
56+
ln -s "$SQLITE3_LIBFILE" "$HEROKU_PYTHON_DIR/lib/libsqlite3.so"
57+
if [ -z "$HEADERS_ONLY" ]; then
58+
mv "$HEROKU_PYTHON_DIR/sqlite3/usr/bin"/* "$HEROKU_PYTHON_DIR/bin/"
59+
fi
60+
61+
# cleanup
62+
rm -rf "$HEROKU_PYTHON_DIR/sqlite3/"
63+
rm -rf "$HEROKU_PYTHON_DIR/apt/"
64+
}
65+
66+
buildpack_sqlite3_install() {
67+
sqlite3_version
68+
HEROKU_PYTHON_DIR="$BUILD_DIR/.heroku/python"
69+
70+
SQLITE3_VERSION_FILE="$BUILD_DIR/.heroku/python-sqlite3-version"
71+
if [ -f "$SQLITE3_VERSION_FILE" ]; then
72+
INSTALLED_SQLITE3_VERSION=$(cat "$SQLITE3_VERSION_FILE")
73+
fi
74+
75+
# python version check
76+
if python_sqlite3_check "$PYTHON_VERSION"; then
77+
# only install if the sqlite3 version has changed
78+
if [ "$INSTALLED_SQLITE3_VERSION" != "$SQLITE3_VERSION" ]; then
79+
puts-step "Installing SQLite3"
80+
sqlite3_install "$BUILD_DIR/.heroku/python" "$SQLITE3_VERSION"
81+
82+
# save version installed
83+
mkdir -p "$CACHE_DIR/.heroku/"
84+
echo "$SQLITE3_VERSION" > "$CACHE_DIR/.heroku/python-sqlite3-version"
85+
fi
86+
fi
87+
}

bin/utils

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,14 @@ python3_check() {
8585

8686
version_gte "$VERSION" "python-3.0.0" && version_gt "python-4.0.0" "$VERSION"
8787
}
88+
89+
# Check if Python version needs to install SQLite3
90+
python_sqlite3_check() {
91+
VERSION="$1"
92+
MIN_PYTHON_3="python-3.6.6"
93+
MIN_PYTHON_2="python-2.7.15"
94+
95+
( python2_check "$VERSION" && version_gte "$VERSION" "$MIN_PYTHON_2" ) \
96+
|| ( python3_check "$VERSION" && version_gte "$VERSION" "$MIN_PYTHON_3" ) \
97+
|| ( version_gte "$VERSION" "3.7.0" )
98+
}

builds/runtimes/python-2.7.15

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
#!/usr/bin/env bash
22
# Build Path: /app/.heroku/python/
3-
# Build Deps: libraries/sqlite
43

54
OUT_PREFIX=$1
5+
BIN_DIR="$(cd "$(dirname "$0")"/../.. || exit; pwd)/bin"
6+
export BIN_DIR
7+
8+
# shellcheck source=bin/utils
9+
source "$BIN_DIR/steps/sqlite3"
10+
11+
sqlite3_version
12+
echo "Setting up SQLite3 Headers for $SQLITE3_VERSION"
13+
sqlite3_install "$OUT_PREFIX" "$SQLITE3_VERSION" 1
614

715
echo "Building Python…"
816
SOURCE_TARBALL='https://python.org/ftp/python/2.7.15/Python-2.7.15.tgz'

builds/runtimes/python-3.6.6

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
#!/usr/bin/env bash
22
# Build Path: /app/.heroku/python/
3-
# Build Deps: libraries/sqlite
43

54
OUT_PREFIX=$1
5+
BIN_DIR="$(cd "$(dirname "$0")"/../.. || exit; pwd)/bin"
6+
export BIN_DIR
7+
8+
# shellcheck source=bin/utils
9+
source "$BIN_DIR/steps/sqlite3"
10+
11+
sqlite3_version
12+
echo "Setting up SQLite3 Headers for $SQLITE3_VERSION"
13+
sqlite3_install "$OUT_PREFIX" "$SQLITE3_VERSION" 1
614

715
echo "Building Python…"
816
SOURCE_TARBALL='https://python.org/ftp/python/3.6.6/Python-3.6.6.tgz'

builds/runtimes/python-3.7.0

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
#!/usr/bin/env bash
22
# Build Path: /app/.heroku/python/
3-
# Build Deps: libraries/sqlite
43

54
OUT_PREFIX=$1
5+
BIN_DIR="$(cd "$(dirname "$0")"/../.. || exit; pwd)/bin"
6+
export BIN_DIR
7+
8+
# shellcheck source=bin/utils
9+
source "$BIN_DIR/steps/sqlite3"
10+
11+
sqlite3_version
12+
echo "Setting up SQLite3 Headers for $SQLITE3_VERSION"
13+
sqlite3_install "$OUT_PREFIX" "$SQLITE3_VERSION" 1
614

715
echo "Building Python…"
816
SOURCE_TARBALL='https://python.org/ftp/python/3.7.0/Python-3.7.0.tgz'

0 commit comments

Comments
 (0)