forked from duckdb/duckdb-r
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfigure
More file actions
executable file
·212 lines (193 loc) · 9.21 KB
/
Copy pathconfigure
File metadata and controls
executable file
·212 lines (193 loc) · 9.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/bin/sh
set -ex
# Setup parallel compilation if MAKEFLAGS not already set
cd "$(dirname "$0")"
if [ -z "${MAKEFLAGS}" ]; then
makeflags_value=$(Rscript tools/setup-makeflags.R 2>/dev/null || echo "")
# Rscript reports a file it cannot open on *stdout* and exits 2, so neither
# the redirect nor the `||` keeps that message out of the capture. Accept
# only the -jN the helper produces, so anything else leaves MAKEFLAGS unset.
case "${makeflags_value}" in
-j*)
makeflags_digits="${makeflags_value#-j}"
case "${makeflags_digits}" in
'' | *[!0-9]*) makeflags_value="" ;;
esac
;;
*) makeflags_value="" ;;
esac
if [ -n "${makeflags_value}" ]; then
export MAKEFLAGS="${makeflags_value}"
echo "Setting MAKEFLAGS=${makeflags_value} for parallel compilation"
echo "Set NOT_CRAN or MAKEFLAGS to override"
fi
else
echo "MAKEFLAGS already set to: ${MAKEFLAGS}"
fi
PKG_ROOT="$(dirname "$0")"
cd "${PKG_ROOT}/src"
# Not used on Linux, for completeness.
echo DUCKDB_RSTRTMGR=1 > Makevars.rstrtmgr
echo DUCKDB_RSTRTMGR_LIB= >> Makevars.rstrtmgr
# Drop any Makevars.system-lib left behind by an earlier
# DUCKDB_R_USE_SYSTEM_LIB build; the branch below rewrites it when the
# opt-in is active. Without this, the stale file keeps emptying SOURCES
# and adding -lduckdb, so a plain `R CMD INSTALL .` silently stays on the
# fast path -- producing a package that resolves DuckDB symbols from the
# system library (a different extension set and autoinstall default)
# while looking like a vendored build.
rm -f Makevars.system-lib
# Opt-in mode: skip compilation of the ~1700 vendored .cpp files and
# link the R package against a system-installed libduckdb instead.
# Shrinks `R CMD INSTALL .` from minutes to seconds. Intended for local
# development, CI smoke tests, and coding-agent iteration. Not for
# `R CMD build` / CRAN-style tarballs: the resulting installation
# depends on libduckdb being present at runtime.
#
# Linux and macOS only.
#
# How this works:
# * The R glue code uses ~71 internal DuckDB C++ headers (templates,
# extension internals, Arrow integration) that are NOT in the
# amalgamated duckdb.hpp shipped with libduckdb releases. So we
# keep using the vendored header tree in src/duckdb/src/include/
# for the *headers*, and only swap the *implementation* for the
# system libduckdb.
# * That is only safe if the vendored sources and the system library
# were built from the same commit. We hard-fail otherwise, by
# checking that the DUCKDB_SOURCE_ID string in the vendored
# pragma_version.cpp is embedded in libduckdb.{so,dylib}.
# * Under `R CMD check`, the package is first tarballed by `R CMD
# build`, which runs cleanup and compresses src/duckdb/ into
# src/duckdb.tar.xz. We extract that tarball below so the headers
# are available for compilation of the glue code.
if [ "${DUCKDB_R_USE_SYSTEM_LIB}" = "1" ] || [ "${DUCKDB_R_USE_SYSTEM_LIB}" = "true" ]; then
uname_s=$(uname -s)
case "${uname_s}" in
Linux) lib_ext=so ;;
Darwin) lib_ext=dylib ;;
*)
echo "DUCKDB_R_USE_SYSTEM_LIB is only supported on Linux and macOS (got: ${uname_s})" >&2
exit 1
;;
esac
# Resolve libduckdb directory.
# Precedence: DUCKDB_R_LIB_DIR -> pkg-config duckdb -> standard system paths.
# ${HOME}/.local/lib leads the fallbacks because it is where
# scripts/install-libduckdb.sh writes by default, so it is the copy most
# likely to match the vendored commit; a system one that does not match is
# rejected by the check below either way.
duckdb_lib_dir="${DUCKDB_R_LIB_DIR}"
if [ -z "${duckdb_lib_dir}" ] && command -v pkg-config >/dev/null 2>&1 && pkg-config --exists duckdb 2>/dev/null; then
duckdb_lib_dir=$(pkg-config --variable=libdir duckdb 2>/dev/null)
fi
if [ -z "${duckdb_lib_dir}" ]; then
for candidate in "${HOME:-/nonexistent}/.local/lib" /usr/local/lib /opt/homebrew/lib /usr/lib/x86_64-linux-gnu /usr/lib/aarch64-linux-gnu /usr/lib; do
if [ -f "${candidate}/libduckdb.${lib_ext}" ]; then
duckdb_lib_dir="${candidate}"
break
fi
done
fi
if [ -z "${duckdb_lib_dir}" ] || [ ! -f "${duckdb_lib_dir}/libduckdb.${lib_ext}" ]; then
echo "DUCKDB_R_USE_SYSTEM_LIB=1 but libduckdb.${lib_ext} not found." >&2
echo "Set DUCKDB_R_LIB_DIR to the directory containing libduckdb.${lib_ext}," >&2
echo "or run scripts/install-libduckdb.sh to install a matching build." >&2
exit 1
fi
echo "Using system libduckdb from: ${duckdb_lib_dir}/libduckdb.${lib_ext}"
# Extract the vendored headers if R CMD build has compressed them.
# Must happen before the version check, which reads from the vendored
# pragma_version.cpp, and before the glue compile, which resolves
# #include "duckdb/..." under -Iduckdb/src/include.
if [ -f duckdb.tar.xz ]; then
if command -v gtar >/dev/null 2>&1 && command -v xz >/dev/null 2>&1; then
TAR=gtar
else
TAR=tar
fi
$TAR xJf duckdb.tar.xz
fi
# Hard-fail unless the system libduckdb was built from the same upstream
# commit as the vendored sources. The glue compiles against the vendored
# internal headers; the only thing that guarantees the layout matches
# the loaded library is an exact-commit match. We check the embedded
# DUCKDB_SOURCE_ID string in the .so/.dylib.
#
# The two abbreviations need not be the same length: DuckDB truncates the
# commit hash to 10 chars in the binary (CMake SUBSTRING 0 10), while the
# vendored pragma_version.cpp sometimes carries 11. Both abbreviate the
# same SHA, so we compare on the shared 10-char prefix.
#
# Newly vendored trees carry 10, because the vendor scripts pin core.abbrev
# in the upstream clone; the prefix comparison stays for the trees vendored
# before that, which a branch keeps until its next vendor commit.
version_file=duckdb/src/function/table/version/pragma_version.cpp
if [ -f "${version_file}" ]; then
vendored_version=$(sed -n 's/^#define DUCKDB_VERSION "\(.*\)"$/\1/p' "${version_file}")
vendored_source_id=$(sed -n 's/^#define DUCKDB_SOURCE_ID "\(.*\)"$/\1/p' "${version_file}")
echo "Vendored DuckDB headers: ${vendored_version} (commit ${vendored_source_id})"
if ! command -v strings >/dev/null 2>&1; then
echo "Cannot find 'strings' to verify libduckdb commit. Install binutils." >&2
exit 1
fi
# Compare on the first 10 hex chars (DuckDB's canonical binary length).
vendored_prefix=$(printf '%s' "${vendored_source_id}" | cut -c1-10)
if [ -n "${vendored_prefix}" ] && ! strings "${duckdb_lib_dir}/libduckdb.${lib_ext}" | grep -qE "^${vendored_prefix}"; then
installed_source_id=$(strings "${duckdb_lib_dir}/libduckdb.${lib_ext}" | grep -E '^[0-9a-f]{10,}$' | head -n 1)
echo "" >&2
echo "ERROR: vendored headers and system libduckdb were built from different commits." >&2
echo " vendored headers expect commit: ${vendored_source_id} (${vendored_version})" >&2
echo " ${duckdb_lib_dir}/libduckdb.${lib_ext} reports commit: ${installed_source_id:-<not found>}" >&2
echo "" >&2
echo "The R glue includes internal DuckDB C++ headers; these are only" >&2
echo "ABI-compatible with the matching commit's libduckdb. Either:" >&2
echo " * run scripts/install-libduckdb.sh to install a matching build, or" >&2
echo " * unset DUCKDB_R_USE_SYSTEM_LIB to compile the vendored sources." >&2
exit 1
fi
fi
# Write Makevars.system-lib, which Makevars picks up via `include`.
# The file is ignored by git; the rest of the build (Makevars.duckdb
# and friends) is left untouched.
{
echo "# Generated by configure (DUCKDB_R_USE_SYSTEM_LIB=1). Do not edit."
echo "SOURCES="
echo "PKG_LIBS=-L${duckdb_lib_dir} -lduckdb -Wl,-rpath,${duckdb_lib_dir}"
} > Makevars.system-lib
# Skip the prebuilt-archive logic below; we have nothing to compile.
exit 0
fi
# The purpose of this is to avoid rebuilding duckdb in every CI/CD run.
# We set the DUCKDB_R_PREBUILT_ARCHIVE environment variable to a file path
# that contains a .tar of all object files.
# This .tar file is cached and restored in CI/CD, keyed by compiler, OS,
# and hash of the duckdb/src subtree.
#
# Depending on the availability of the file, we either use the object files
# (via the rules in include/from-tar.mk), or create them as usual
# (via include/to-tar.mk). In the latter case, if the DUCKDB_R_PREBUILT_ARCHIVE
# environment variable is set, the .tar file is created.
#
# For local installations, this is typically not needed
# because ccache achieves the same purpose but better.
# In CI/CD, this approach gives better results than ccache.
#
# This logic is identical for Windows or non-Windows builds,
# only that we need to-tar-win.mk instead of to-tar.mk on Windows.
if [ -f "${DUCKDB_R_PREBUILT_ARCHIVE}" ] && tar -xm -f "${DUCKDB_R_PREBUILT_ARCHIVE}"; then
cp include/from-tar.mk Makevars.duckdb
else
cp include/to-tar.mk Makevars.duckdb
fi
# The duckdb sources are xz-compressed in the tarball to keep it under 5000000 bytes.
# This happens in the cleanup script.
if [ -f duckdb.tar.xz ]; then
# Use gtar if available (e.g., on macOS via Homebrew), otherwise tar.
if command -v gtar >/dev/null 2>&1 && command -v xz >/dev/null 2>&1; then
TAR=gtar
else
TAR=tar
fi
$TAR xJf duckdb.tar.xz
fi