Skip to content

Commit bf8ce0a

Browse files
authored
CentOS 7 build (#13)
1 parent b9ca880 commit bf8ce0a

File tree

6 files changed

+190
-55
lines changed

6 files changed

+190
-55
lines changed

.github/workflows/build.yml

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ env:
55
APT_DEPS: libzstd-dev samtools tabix libhts-dev pigz python3-pip
66
BREW_DEPS: [email protected] sqlite zstd samtools pigz coreutils
77
PIP_DEPS: pytest pytest-xdist
8+
SQLITE_VERSION: 3340000
89

910
jobs:
1011

@@ -59,7 +60,7 @@ jobs:
5960
- name: test
6061
run: env -C build ctest -V
6162

62-
linux-so:
63+
linux-x86-64-so:
6364
runs-on: ubuntu-20.04
6465
steps:
6566
- uses: actions/checkout@v2
@@ -70,18 +71,25 @@ jobs:
7071
sudo apt-get -qq update
7172
sudo apt-get install -y $APT_DEPS
7273
sudo pip3 install --system $PIP_DEPS
73-
cmake -DCMAKE_BUILD_TYPE=Release -B build . && cmake --build build -j $(nproc)
74+
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS='-D_GLIBCXX_USE_CXX11_ABI=0' -B build . && cmake --build build -j $(nproc)
7475
rm build/libgenomicsqlite.so
7576
sudo apt-get remove -y libzstd-dev # should be linked into libgenomicsqlite.so
7677
- name: build portable .so in docker
77-
run: docker build -t genomicsqlite . && docker run -v $(pwd):/mnt --rm genomicsqlite cp build/libgenomicsqlite.so /mnt/build/
78-
- name: ldd
78+
run: docker build --build-arg "SQLITE_VERSION=${SQLITE_VERSION}" -t genomicsqlite . && docker run -v $(pwd):/mnt --rm genomicsqlite cp /usr/local/lib/{libgenomicsqlite.so,libsqlite3.so.0} /mnt/build/
79+
- name: symbols & digests
7980
run: |
80-
docker run genomicsqlite ldd -v -r build/libgenomicsqlite.so
81+
readelf -d build/libgenomicsqlite.so
82+
ldd -r build/libgenomicsqlite.so
8183
echo "----"
82-
ldd -v -r build/libgenomicsqlite.so
84+
echo "libgenomicsqlite.so GLIBC version requirements:"
85+
objdump -t build/libgenomicsqlite.so | grep -o 'GLIBC_.*' | sort -Vr | head -n1
86+
objdump -t build/libgenomicsqlite.so | grep -o 'GLIBCXX_.*' | sort -Vr | head -n1
87+
echo "libsqlite3.so.0 GLIBC version requirements:"
88+
objdump -t build/libsqlite3.so.0 | grep -o 'GLIBC_.*' | sort -Vr | head -n1
8389
echo "----"
84-
sha256sum build/libgenomicsqlite.so
90+
sha256sum build/libgenomicsqlite.so build/libsqlite3.so.0
91+
sudo cp build/libsqlite3.so.0 /usr/local/lib
92+
sudo ldconfig
8593
- name: rust toolchain
8694
uses: actions-rs/toolchain@v1
8795
with:
@@ -96,13 +104,17 @@ jobs:
96104
bindings/rust/cargo test --release
97105
bindings/rust/cargo package --list | grep libgenomicsqlite.so
98106
- name: prepare artifacts
99-
run: cp build/libgenomicsqlite.so include/genomicsqlite.h .
107+
run: cp build/{libgenomicsqlite.so,libsqlite3.so.0} .
100108
- uses: actions/upload-artifact@v2
101109
with:
102110
name: libgenomicsqlite.so
103111
path: libgenomicsqlite.so
112+
- uses: actions/upload-artifact@v2
113+
with:
114+
name: libsqlite3.so.0
115+
path: libsqlite3.so.0
104116

105-
macOS-dylib:
117+
macOS-x86-64-dylib:
106118
runs-on: macOS-10.15
107119
steps:
108120
- uses: actions/checkout@v2
@@ -111,9 +123,10 @@ jobs:
111123
- name: dependencies
112124
run: |
113125
rm -f /usr/local/bin/2to3 # https://github.com/pypa/pipenv/issues/3831
114-
brew update
115-
brew upgrade
116-
brew install $BREW_DEPS
126+
brew update || (sleep 2; brew update)
127+
for dep in $BREW_DEPS ; do
128+
brew install $dep || brew upgrade $dep
129+
done
117130
/usr/local/bin/pip3 install $PIP_DEPS
118131
- name: rust toolchain
119132
uses: actions-rs/toolchain@v1
@@ -136,7 +149,7 @@ jobs:
136149
-DCMAKE_PREFIX_PATH=$(brew --prefix)/opt/sqlite \
137150
-B build .
138151
cmake --build build -j 4
139-
- name: otool
152+
- name: symbols & digests
140153
run: |
141154
otool -L build/libgenomicsqlite.dylib
142155
sha256sum build/libgenomicsqlite.dylib
@@ -160,13 +173,17 @@ jobs:
160173

161174
artifacts:
162175
runs-on: ubuntu-20.04
163-
needs: [linux-so, macOS-dylib]
176+
needs: [linux-x86-64-so, macOS-x86-64-dylib]
164177
steps:
165178
- uses: actions/checkout@v2
166179
- name: fetch libgenomicsqlite.so
167180
uses: actions/download-artifact@v2
168181
with:
169182
name: libgenomicsqlite.so
183+
- name: fetch libsqlite3.so.0
184+
uses: actions/download-artifact@v2
185+
with:
186+
name: libsqlite3.so.0
170187
- name: fetch libgenomicsqlite.dylib
171188
uses: actions/download-artifact@v2
172189
with:
@@ -188,7 +205,7 @@ jobs:
188205
cp libgenomicsqlite.so libgenomicsqlite.dylib bindings/jdbc/genomicsqlite-jdbc/src/main/resources/
189206
mvn deploy -Drevision=${{ env.GIT_REVISION }} -B -f bindings/jdbc/genomicsqlite-jdbc/pom.xml
190207
- name: digests
191-
run: sha256sum *genomicsqlite* bindings/jdbc/genomicsqlite-jdbc/target/genomicsqlite*.jar
208+
run: sha256sum *genomicsqlite* bindings/jdbc/genomicsqlite-jdbc/target/genomicsqlite*.jar libsqlite3.so.0
192209
- uses: actions/upload-artifact@v2
193210
with:
194211
name: genomicsqlite-jdbc-${{ env.GIT_REVISION }}

Dockerfile

Lines changed: 111 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,36 @@
1-
# Builds libgenomicsqlite.so in old ubuntu (16.04) to maximize portability. Also bakes in Zstandard.
2-
# This recipe works on 14.04 too, but there are C++ symbol differences before & after g++ 5.1:
3-
# https://gcc.gnu.org/onlinedocs/gcc-5.2.0/libstdc++/manual/manual/using_dual_abi.html
4-
FROM ubuntu:16.04
1+
# Builds libgenomicsqlite.so in CentOS 7 (+ devtoolset-8) to maximize compatibility. Bakes in
2+
# Zstandard, and also builds a compatible libsqlite3.so.0 for users unable/unwilling to upgrade
3+
# their host's.
4+
FROM centos:7 as builder
55

66
ARG CMAKE_VERSION=3.17.3
7-
ARG SQLITE_VERSION=3310000
8-
ARG ZSTD_VERSION=1.4.7
9-
ARG CPU_ARCH=haswell
10-
7+
ARG SQLITE_VERSION=3340000
8+
ARG ZSTD_VERSION=1.4.8
9+
ARG CPU_ARCH=ivybridge
1110
ENV CFLAGS="-march=${CPU_ARCH} -O3"
1211
ENV CXXFLAGS=${CFLAGS}
12+
# https://www.sqlite.org/compile.html
13+
ENV SQLITE_CFLAGS="\
14+
-DSQLITE_ENABLE_LOAD_EXTENSION \
15+
-DSQLITE_USE_URI \
16+
-DSQLITE_DQS=0 \
17+
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
18+
-DSQLITE_DEFAULT_MEMSTATUS=0 \
19+
-DSQLITE_MAX_EXPR_DEPTH=0 \
20+
-DSQLITE_ENABLE_NULL_TRIM \
21+
-DSQLITE_USE_ALLOCA \
22+
-DSQLITE_HAVE_ISNAN \
23+
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT \
24+
-DSQLITE_ENABLE_COLUMN_METADATA \
25+
-DSQLITE_ENABLE_DBSTAT_VTAB \
26+
-DSQLITE_ENABLE_FTS5 \
27+
-DSQLITE_ENABLE_RTREE \
28+
-DSQLITE_ENABLE_PREUPDATE_HOOK \
29+
-DSQLITE_ENABLE_SESSION \
30+
"
1331

14-
# apt
15-
RUN apt-get -qq update && DEBIAN_FRONTEND=noninteractive apt-get -qq install -y \
16-
build-essential wget zip rsync git-core
32+
RUN yum install -y -q wget unzip rsync git centos-release-scl
33+
RUN yum install -y -q devtoolset-8-gcc devtoolset-8-gcc-c++ devtoolset-8-make
1734

1835
RUN mkdir -p /work/GenomicSQLite
1936

@@ -22,16 +39,16 @@ WORKDIR /work
2239
RUN wget -nv https://www.sqlite.org/2020/sqlite-amalgamation-${SQLITE_VERSION}.zip \
2340
&& unzip -o sqlite-amalgamation-${SQLITE_VERSION}.zip
2441
WORKDIR /work/sqlite-amalgamation-${SQLITE_VERSION}
25-
RUN gcc -shared -o libsqlite3.so.0 -fPIC -shared -Wl,-soname,libsqlite3.so.0 -g ${CFLAGS} sqlite3.c
26-
RUN gcc -o sqlite3 -g ${CFLAGS} sqlite3.c shell.c -lpthread -ldl
42+
RUN bash -c "scl enable devtoolset-8 'gcc -shared -o libsqlite3.so.0 -fPIC -shared -Wl,-soname,libsqlite3.so.0 -g ${CFLAGS} ${SQLITE_CFLAGS} sqlite3.c' & pid=$? \
43+
scl enable devtoolset-8 'gcc -o sqlite3 -g ${CFLAGS} ${SQLITE_CFLAGS} sqlite3.c shell.c -lpthread -ldl -lm' && wait $pid"
2744
RUN cp libsqlite3.so.0 /usr/local/lib && cp *.h /usr/local/include && cp sqlite3 /usr/local/bin
2845
RUN ln -s /usr/local/lib/libsqlite3.so.0 /usr/local/lib/libsqlite3.so
2946

3047
# Zstandard -- hacked with -fPIC for use with ZSTD_WHOLE_ARCHIVE
3148
WORKDIR /work
3249
RUN wget -nv -O - https://github.com/facebook/zstd/releases/download/v${ZSTD_VERSION}/zstd-${ZSTD_VERSION}.tar.gz | tar zx
3350
WORKDIR /work/zstd-${ZSTD_VERSION}
34-
RUN CFLAGS="${CFLAGS} -fPIC" make install -j $(nproc)
51+
RUN scl enable devtoolset-8 "CFLAGS='${CFLAGS} -fPIC' make install -j $(nproc)"
3552

3653
# CMake
3754
WORKDIR /work
@@ -44,7 +61,83 @@ RUN ldconfig
4461
# libgenomicsqlite.so
4562
ADD . /work/GenomicSQLite
4663
WORKDIR /work/GenomicSQLite
47-
RUN rm -rf build && cmake -DCMAKE_BUILD_TYPE=Release -DZSTD_WHOLE_ARCHIVE=true -B build . && cmake --build build --target genomicsqlite -j $(nproc)
48-
RUN ldd -v -r build/libgenomicsqlite.so
49-
RUN sqlite3 -cmd '.load build/libgenomicsqlite.so' :memory: 'select genomicsqlite_version()'
50-
RUN sha256sum build/libgenomicsqlite.so
64+
RUN rm -rf build
65+
RUN scl enable devtoolset-8 "cmake -DCMAKE_BUILD_TYPE=Release -DZSTD_WHOLE_ARCHIVE=true -B build . && cmake --build build --target genomicsqlite -j $(nproc)"
66+
RUN sqlite3 -cmd '.load build/libgenomicsqlite.so' :memory: 'select sqlite_version(); select genomicsqlite_version()'
67+
68+
69+
70+
71+
###################################################################################################
72+
# Run-up in fresh centos:7, to confirm no dependencies crept into the .so's
73+
74+
FROM centos:7
75+
76+
COPY --from=builder /usr/local/bin/sqlite3 /usr/local/bin/
77+
COPY --from=builder /usr/local/include/sqlite3.h /usr/local/include/
78+
79+
# NOTE: /usr/local/lib is NOT a default ld path in CentOS -- https://unix.stackexchange.com/q/356624
80+
RUN mkdir -p /work/lib
81+
WORKDIR /work
82+
COPY --from=builder /usr/local/lib/libsqlite3.so.0 ./lib/
83+
COPY --from=builder /work/GenomicSQLite/build/libgenomicsqlite.so ./
84+
# the following approximates how bindings will usually load the extension at runtime:
85+
# - libsqlite3.so.0 in the ld search path (if not already resident in the process)
86+
# - given absolute path to libgenomicsqlite3.so
87+
RUN LD_LIBRARY_PATH=$(pwd)/lib sqlite3 -cmd ".load $(pwd)/libgenomicsqlite.so" :memory: 'select sqlite_version(); select genomicsqlite_version()'
88+
# if troubleshooting that: set LD_DEBUG=libs for extremely detailed dlopen() logs
89+
90+
# now try capi_smoke_test, with some hoops to ensure it's not dependent on implicit RPATHs
91+
RUN yum install -y -q gcc && gcc -v
92+
RUN mv libgenomicsqlite.so lib/ && ln -s libsqlite3.so.0 lib/libsqlite3.so
93+
ADD ./test/capi_smoke_test.c ./include/genomicsqlite.h ./
94+
RUN gcc -o genomicsqlite_capi_smoke_test ${CFLAGS} -L$(pwd)/lib -Wl,-rpath,\$ORIGIN -Wl,-z,origin \
95+
capi_smoke_test.c -lgenomicsqlite -lsqlite3 \
96+
&& readelf -d genomicsqlite_capi_smoke_test
97+
RUN mv lib/{libgenomicsqlite.so,libsqlite3.so.0} . && rm -rf lib
98+
RUN ./genomicsqlite_capi_smoke_test
99+
# ^ we didn't need LD_LIBRARY_PATH even though the .so's aren't at their linktime locations
100+
101+
# test rust bindings too
102+
FROM centos:7
103+
104+
RUN yum install -y -q gcc git
105+
ADD https://sh.rustup.rs /usr/local/bin/rustup-init.sh
106+
RUN chmod +x /usr/local/bin/rustup-init.sh && rustup-init.sh -y
107+
ENV PATH=${PATH}:/root/.cargo/bin
108+
109+
RUN mkdir -p /work/lib
110+
WORKDIR /work
111+
COPY --from=builder /usr/local/lib/libsqlite3.so.0 ./lib/
112+
RUN ln -s libsqlite3.so.0 lib/libsqlite3.so
113+
ADD ./.git ./.git
114+
ADD ./bindings/rust ./rust
115+
COPY --from=builder /work/GenomicSQLite/build/libgenomicsqlite.so ./rust/
116+
RUN LD_LIBRARY_PATH=$(pwd)/lib LIBRARY_PATH=$(pwd)/lib rust/cargo test --release
117+
118+
###################################################################################################
119+
# Run-up in ubuntu 16.04
120+
121+
FROM ubuntu:16.04
122+
123+
COPY --from=builder /usr/local/bin/sqlite3 /usr/local/bin/
124+
COPY --from=builder /usr/local/include/sqlite3.h /usr/local/include/
125+
COPY --from=builder /usr/local/lib/libsqlite3.so.0 /work/GenomicSQLite/build/libgenomicsqlite.so /usr/local/lib/
126+
RUN ln -s libsqlite3.so.0 /usr/local/lib/libsqlite3.so
127+
128+
RUN sqlite3 -cmd '.load /usr/local/lib/libgenomicsqlite.so' :memory: 'select sqlite_version(); select genomicsqlite_version()'
129+
130+
RUN mkdir /work
131+
WORKDIR /work
132+
133+
RUN apt-get -qq update && apt-get install -qq -y build-essential && gcc -v
134+
ADD ./test/capi_smoke_test.c ./include/genomicsqlite.h /work/
135+
RUN gcc -o genomicsqlite_capi_smoke_test ${CFLAGS} capi_smoke_test.c -lgenomicsqlite -lsqlite3
136+
RUN ./genomicsqlite_capi_smoke_test
137+
138+
# display dependencies & digests in docker build log
139+
RUN ldd -v -r /usr/local/lib/libgenomicsqlite.so
140+
RUN objdump -t /usr/local/lib/libgenomicsqlite.so | grep -o 'GLIBC_.*' | sort -Vr | head -n1
141+
RUN objdump -t /usr/local/lib/libgenomicsqlite.so | grep -o 'GLIBCXX_.*' | sort -Vr | head -n1
142+
RUN objdump -t /usr/local/lib/libsqlite3.so.0 | grep -o 'GLIBC_.*' | sort -Vr | head -n1
143+
RUN sha256sum /usr/local/lib/libgenomicsqlite.so /usr/local/lib/libsqlite3.so.0

docs/guide.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ The Genomics Extension integrates with your programming language's existing SQLi
4242
Link the program to `sqlite3` and `genomicsqlite` libraries; optionally,
4343
[SQLiteCpp](https://github.com/SRombauts/SQLiteCpp).
4444

45+
GNU/Linux: to link the prebuilt `libgenomicsqlite.so` distributed from our GitHub Releases, you
46+
may have to compile your source with `CXXFLAGS=-D_GLIBCXX_USE_CXX11_ABI=0`. This is because the
47+
library is built against an old libstdc++ version to improve runtime compatibility. The
48+
function of this flag is explained in the libstdc++ docs on
49+
[Dual ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html). If you build
50+
`libgenomicsqlite.so` from source, then the flag will not be needed.
51+
4552
General note: GenomicSQLite C++ routines are liable to throw exceptions.
4653

4754
=== "C"

docs/index.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ Our **[Colab notebook](https://colab.research.google.com/drive/1OlHPOcRQBhDmEnS1
2323

2424
**To use the Genomics Extension you might first need to upgrade SQLite itself.** The host program must link [SQLite version 3.31.0 (2020-01-22)](https://www.sqlite.org/releaselog/3_31_0.html) or newer. In your shell, `sqlite3 --version` displays the version installed with your OS, which is probably what your programs use; if in doubt, cause a program to report the result of `SELECT sqlite_version()`.
2525

26-
If this is too old, then upgrade SQLite3 using your preferred binary package manager (e.g. apt, yum, conda, brew), if possible. Otherwise, modify your program's linking step or runtime environment to cause it to use an up-to-date version, for example by setting rpath or LD_LIBRARY_PATH to the location of an up-to-date shared library file. Resources:
26+
If this is too old, then upgrade SQLite3 using your preferred binary package manager (e.g. apt, yum, conda, brew), if possible. Otherwise, modify your program's linking step or runtime environment to cause it to use an up-to-date version, for example by setting rpath or `LD_LIBRARY_PATH` to the location of an up-to-date shared library file. Resources:
2727

2828
* [How To Compile SQLite](https://www.sqlite.org/howtocompile.html)
2929
* [DreamHost Knowledge Base - Installing a custom version of SQLite3](https://help.dreamhost.com/hc/en-us/articles/360028047592-Installing-a-custom-version-of-SQLite3)
3030
* [Rpmfind: libsqlite3](https://rpmfind.net/linux/rpm2html/search.php?query=libsqlite3&submit=Search+...&system=&arch=)
3131
* [Sqlite :: Anaconda Cloud](https://anaconda.org/anaconda/sqlite)
3232
* Homebrew [formula/sqlite](https://formulae.brew.sh/formula/sqlite), [formula-linux/sqlite](https://formulae.brew.sh/formula-linux/sqlite)
33+
* As a last resort for GNU/Linux, our [GitHub Releases](https://github.com/mlin/GenomicSQLite/releases) include a `libsqlite3.so.0` that should be compatible with modern (2016+) hosts.
3334

3435
You can always `SELECT sqlite_version()` to verify the upgrade in your program.
3536

@@ -82,6 +83,13 @@ It's usually easiest to obtain the extension as a pre-compiled shared library (L
8283

8384
Recommendation: *also* install the Python package, which includes a useful command-line shell and smoke-test script.
8485

86+
GNU/Linux: to link the prebuilt `libgenomicsqlite.so` distributed from our GitHub Releases, you
87+
may have to compile your source with `CXXFLAGS=-D_GLIBCXX_USE_CXX11_ABI=0`. This is because the
88+
library is built against an old libstdc++ version to improve runtime compatibility. The
89+
function of this flag is explained in the libstdc++ docs on
90+
[Dual ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html). If you build
91+
`libgenomicsqlite.so` from source, then the flag will not be needed.
92+
8593
See our [GitHub README](https://github.com/mlin/GenomicSQLite) for the source build procedure, if needed.
8694

8795
We welcome community contributions to the available language bindings; see the Language Bindings Guide if interested.

0 commit comments

Comments
 (0)