forked from filecoin-project/filecoin-ffi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
install-filcrypto
executable file
·271 lines (221 loc) · 9.85 KB
/
install-filcrypto
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#!/usr/bin/env bash
# shellcheck disable=SC2155 enable=require-variable-braces
set -Exeo pipefail
auth_header=()
if [ -n "${GITHUB_TOKEN}" ]; then
auth_header=("-H" "Authorization: token ${GITHUB_TOKEN}")
fi
# set CWD to the root of filecoin-ffi
#
cd "$(dirname "${BASH_SOURCE[0]}")"
# tracks where the Rust sources are were we to build locally instead of
# downloading from GitHub Releases
#
rust_sources_dir="rust"
# an array of values passed as 'target-feature' to the Rust compiler if we're
# building an optimized libfilcrypto (which takes advantage of some perf-boosting
# instruction sets)
#
#optimized_release_rustc_target_features=$(jq -r '.[].rustc_target_feature' < "${rust_sources_dir}/rustc-target-features-optimized.json")
# each value in this area is checked against the "features" of the hosts CPU
# in order to determine if the host is suitable for an optimized release
#
cpu_features_required_for_optimized_release=$(jq -r '.[].check_cpu_for_feature | select(. != null)' < "${rust_sources_dir}/rustc-target-features-optimized.json")
main() {
local __release_flags=$(get_release_flags)
if [ "${FFI_BUILD_FROM_SOURCE}" != "1" ] && download_release_tarball __tarball_path "${rust_sources_dir}" "filecoin-ffi" "${__release_flags}"; then
local __tmp_dir=$(mktemp -d)
# silence shellcheck warning as the assignment happened in
# `download_release_tarball()`
# shellcheck disable=SC2154
# extract downloaded tarball to temporary directory
#
tar -C "${__tmp_dir}" -xzf "${__tarball_path}"
# copy build assets into root of filecoin-ffi
#
find -L "${__tmp_dir}" -type f -name filcrypto.h -exec cp -- "{}" . \;
find -L "${__tmp_dir}" -type f -name libfilcrypto.a -exec cp -- "{}" . \;
find -L "${__tmp_dir}" -type f -name filcrypto.pc -exec cp -- "{}" . \;
check_installed_files
(>&2 echo "[install-filcrypto/main] successfully installed prebuilt libfilcrypto")
else
(>&2 echo "[install-filcrypto/main] building libfilcrypto from local sources (dir = ${rust_sources_dir})")
# build libfilcrypto (and corresponding header and pkg-config)
#
build_from_source "filcrypto" "${rust_sources_dir}" "${__release_flags}"
# copy from Rust's build directory (target) to root of filecoin-ffi
#
if [ "$(uname -s)" = "Darwin" ] && [ "$(uname -m)" = "x86_64" ]; then
find -L "${rust_sources_dir}/target/universal/release" -type f -name libfilcrypto.a -exec cp -- "{}" . \;
else
find -L "${rust_sources_dir}/target/release" -type f -name libfilcrypto.a -exec cp -- "{}" . \;
fi
find -L "${rust_sources_dir}" -type f -name filcrypto.h -exec cp -- "{}" . \;
find -L "${rust_sources_dir}" -type f -name filcrypto.pc -exec cp -- "{}" . \;
pwd
ls ./*filcrypto*
check_installed_files
(>&2 echo "[install-filcrypto/main] successfully built and installed libfilcrypto from source")
fi
}
download_release_tarball() {
local __resultvar=$1
local __rust_sources_path=$2
local __repo_name=$3
local __release_flags=$4
local __release_sha1=$(git rev-parse HEAD)
local __release_tag="${__release_sha1:0:16}"
local __release_tag_url="https://api.github.com/repos/filecoin-project/${__repo_name}/releases/tags/${__release_tag}"
# Download the non-optimized standard release.
release_flag_name="standard"
# TODO: This function shouldn't make assumptions about how these releases'
# names are constructed. Marginally less-bad would be to require that this
# function's caller provide the release name.
#
local __release_name="${__repo_name}-$(uname)-${release_flag_name}"
(>&2 echo "[download_release_tarball] acquiring release @ ${__release_tag}")
local __release_response=$(curl "${auth_header[@]}" \
--retry 3 \
--location "${__release_tag_url}")
local __release_url=$(echo "${__release_response}" | jq -r ".assets[] | select(.name | contains(\"${__release_name}\")) | .url")
local __tar_path="/tmp/${__release_name}_$(basename "${__release_url}").tar.gz"
if [[ -z "${__release_url}" ]]; then
(>&2 echo "[download_release_tarball] failed to download release (tag URL: ${__release_tag_url}, response: ${__release_response})")
return 1
fi
local __asset_url=$(curl "${auth_header[@]}" \
--head \
--retry 3 \
--header "Accept:application/octet-stream" \
--location \
--output /dev/null \
-w "%{url_effective}" \
"${__release_url}")
if ! curl --retry 3 --output "${__tar_path}" "${__asset_url}"; then
(>&2 echo "[download_release_tarball] failed to download release asset (tag URL: ${__release_tag_url}, asset URL: ${__asset_url})")
return 1
fi
# set $__resultvar (which the caller provided as $1), which is the poor
# man's way of returning a value from a function in Bash
#
eval "${__resultvar}='${__tar_path}'"
}
build_from_source() {
local __library_name=$1
local __rust_sources_path=$2
local __release_flags=$3
local __repo_sha1=$(git rev-parse HEAD)
local __repo_sha1_truncated="${__repo_sha1:0:16}"
(>&2 echo "building from source @ ${__repo_sha1_truncated}")
if ! [ -x "$(command -v cargo)" ]; then
(>&2 echo '[build_from_source] Error: cargo is not installed.')
(>&2 echo '[build_from_source] install Rust toolchain to resolve this problem.')
exit 1
fi
if ! [ -x "$(command -v rustup)" ]; then
(>&2 echo '[build_from_source] Error: rustup is not installed.')
(>&2 echo '[build_from_source] install Rust toolchain installer to resolve this problem.')
exit 1
fi
pushd "${__rust_sources_path}"
cargo --version
additional_flags=""
# For building on Darwin, we try to use cargo-lipo instead of cargo build.
# Note that the cross compile works on x86_64 for m1, but doesn't work on m1.
# For m1, we will build natively if building from source.
if [ "$(uname -s)" = "Darwin" ] && [ "$(uname -m)" = "x86_64" ]; then
build="lipo"
additional_flags="--targets x86_64-apple-darwin,aarch64-apple-darwin "
else
build="build"
fi
# Default to use gpu flags, unless specified to disable
gpu_flags=",opencl"
if [ "${FFI_USE_CUDA}" == "1" ]; then
gpu_flags=",cuda"
fi
if [ "${FFI_USE_GPU}" == "0" ]; then
gpu_flags=""
fi
# Default to use multicore_sdr flags, unless specified to disable
use_multicore_sdr="multicore-sdr"
if [ "${FFI_USE_MULTICORE_SDR}" == "0" ]; then
use_multicore_sdr=""
fi
# Add feature specific rust flags as needed here.
if [ "${FFI_USE_BLST_PORTABLE}" == "1" ]; then
additional_flags="${additional_flags} --no-default-features --features ${use_multicore_sdr},blst-portable${gpu_flags}"
else
additional_flags="${additional_flags} --no-default-features --features ${use_multicore_sdr}${gpu_flags}"
fi
echo "Using additional build flags: ${additional_flags}"
if [ -n "${__release_flags}" ]; then
RUSTFLAGS="-C target-feature=${__release_flags}" ./scripts/build-release.sh "${__library_name}" "$(cat rust-toolchain)" ${build} "${additional_flags}"
else
./scripts/build-release.sh "${__library_name}" "$(cat rust-toolchain)" ${build} "${additional_flags}"
fi
popd
}
get_release_flags() {
local __features=""
# determine where to look for CPU features
#
if [[ ! -f "/proc/cpuinfo" ]]; then
(>&2 echo "[get_release_flags] no /proc/cpuinfo file; falling back to Darwin feature detection")
__features=$(sysctl -a | grep machdep.cpu | tr '[:upper:]' '[:lower:]' | grep features)
else
#aarch64_uname=$(uname -a | grep aarch64)
x86_64_uname=$(uname -a | grep x86_64)
# shellcheck disable=SC2002
if [ -n "${x86_64_uname}" ]; then
__features=$(cat /proc/cpuinfo | grep flags | head -n 1)
else
# For now we assume aarch64. If another supported platform is added, explicitly check for it
__features=$(cat /proc/cpuinfo | grep Features | head -n 1)
fi
fi
# Maps cpu flag to rust flags (related to entries in rust/rustc-target-features-optimized.json)
if [ "$(uname -s)" = "Darwin" ] && [ "$(uname -m)" = "x86_64" ]; then
feature_map=("adx:+adx" "sha_ni:+sha" "sha2:+sha2" "avx2:+avx2" "sse4_2:+sse4.2" "sse4_1:+sse4.1")
else
feature_map=("adx:+adx" "sha_ni:+sha" "sha2:+sha2" "sse2:+sse2" "avx2:+avx2" "avx:+avx" "sse4_2:+sse4.2" "sse4_1:+sse4.1")
fi
target_features=""
# check for the presence of each required CPU feature
#
# shellcheck disable=SC2068 # the splitting is intentional
for x in ${cpu_features_required_for_optimized_release[@]}; do
current_feature=$(echo "${__features}" | grep -c "${x}")
if [ "1" = "${current_feature}" ]; then
for feature in "${feature_map[@]}"; do
key=${feature%%:*}
if [ "${key}" == "${x}" ]; then
val=${feature#*:}
if [ -z "${target_features}" ]; then
target_features="${val}"
else
target_features="${target_features},${val}"
fi
fi
done
fi
done
echo "${target_features}"
}
check_installed_files() {
pwd
ls ./*filcrypto*
if [[ ! -f "./filcrypto.h" ]]; then
(>&2 echo "[check_installed_files] failed to install filcrypto.h")
exit 1
fi
if [[ ! -f "./libfilcrypto.a" ]]; then
(>&2 echo "[check_installed_files] failed to install libfilcrypto.a")
exit 1
fi
if [[ ! -f "./filcrypto.pc" ]]; then
(>&2 echo "[check_installed_files] failed to install filcrypto.pc")
exit 1
fi
}
main "$@"; exit