forked from filecoin-project/filecoin-ffi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstall-filcrypto
executable file
·245 lines (201 loc) · 9.05 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
#!/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
#
find -L "${rust_sources_dir}/target/release" -type f -name filcrypto.h -exec cp -- "{}" . \;
find -L "${rust_sources_dir}/target/release" -type f -name libfilcrypto.a -exec cp -- "{}" . \;
find -L "${rust_sources_dir}" -type f -name filcrypto.pc -exec cp -- "{}" . \;
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 either the non-optimized standard or standard-blst release.
if [ "${FFI_USE_BLST}" == "1" ]; then
release_flag_name="standard-blst"
else
release_flag_name="standard-pairing"
fi
# 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
# Default to use gpu flags, unless specified to disable
gpu_flags=",gpu"
if [ "${FFI_USE_GPU}" == "0" ]; then
gpu_flags=""
fi
# Default to use multicore_sdr flags, unless specified to disable
use_multicore_sdr="--features 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="--no-default-features ${use_multicore_sdr} --features blst --features blst-portable${gpu_flags}"
elif [ "${FFI_USE_BLST}" == "1" ]; then
additional_flags="--no-default-features ${use_multicore_sdr} --features blst${gpu_flags}"
else
additional_flags="--no-default-features ${use_multicore_sdr} --features pairing${gpu_flags}"
fi
if [ -n "${__release_flags}" ]; then
RUSTFLAGS="-C target-feature=${__release_flags}" ./scripts/build-release.sh "${__library_name}" "$(cat rust-toolchain)" "${additional_flags}"
else
./scripts/build-release.sh "${__library_name}" "$(cat rust-toolchain)" "${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)
feature_map=("adx:+adx" "sha_ni:+sha" "sha2:+sha2" "sse2:+sse2" "avx2:+avx2" "avx:+avx" "sse4_2:+sse4.2" "sse4_1:+sse4.1")
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() {
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