-
-
Save TeoZosa/da88a858ad73a18e3f7410c4b615466d to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash | |
######################################################################################################################## | |
# This is a build script for misc. TensorFlow dependencies which do NOT have pre-compiled packages available for | |
# M-series (Apple Silicon) macs. | |
# | |
# Who: team members who use M1 macs and would like to run the project | |
# | |
# Caution: This script will use all available processors (rendering the machine relatively unusable) and will take a | |
# significant amount of time (about 2h 0m 15s on an M1 mac). | |
# | |
# Please set aside sufficient time to run this build script. | |
######################################################################################################################## | |
# WARNING: MUST run prior to enabling bash strict mode or else it will fail | |
source deactivate || true # deactivate any current venvs | |
# Set Bash "strict" mode | |
# see: http://redsymbol.net/articles/unofficial-bash-strict-mode/ | |
set -euo pipefail | |
set -x # Print command traces for debugging (feel free to comment this out if it is too noisy for you) | |
IFS=$'\n\t' | |
# Variables used throughout script | |
PROJECT_ROOT="$(git rev-parse --show-toplevel || pwd)" | |
SRC_BUILD_FOLDER_NAME="source_builds" | |
SRC_BUILDS_ROOT="${PROJECT_ROOT}/${SRC_BUILD_FOLDER_NAME}" | |
# In Monterey, there is an issue with OS versions not being properly inferred for built wheels, resulting in wheels | |
# using older platform specifiers. When attempting to install these wheels, they may erroneously be reported as, | |
# "... *.whl is not a supported wheel on this platform." However, they *are* supported, and the error is due solely to | |
# metadata mismatch (i.e., if you manually changed the metadata, it would install and work just fine). | |
# Manually set this C-compiler flag so wheels are correctly built for the host platform. | |
MACOSX_MAJOR_VERSION="$(sw_vers -productVersion | awk -F. '{print $1}')" # e.g., 12 | |
export MACOSX_DEPLOYMENT_TARGET="${MACOSX_MAJOR_VERSION}.0" # e.g., 12.0 | |
ARCH="$(arch)" #i.e., arm64 | |
# Install Bazel build tool for tensorflow ecosystem projects source builds | |
brew install bazelisk | |
export USE_BAZEL_VERSION="4.2.2" # the max version known to work with the below TF versions combination as of 2021/11/13 | |
# TF ecosystem versions as of 2021/11/13 | |
TF_VERSION="2.7.0" | |
TF_TEXT_VERSION="2.7.3" | |
TF_IO_VERSION="0.22.0" # built against TF version 2.7.0 | |
TF_ADDONS_VERSION="0.15.0" # built against TF version 2.7.0 | |
## Main build logic | |
main() { | |
pushd "$(pwd)" # save the current directory to restore after the build process completes | |
sudo -v # login at start of script so that remainder can run without interruption | |
build_dependencies_from_source | |
sudo -k # logout of sudo | |
popd | |
printf "\n************************************************************************************" | |
printf "\nSource packages built:\n\n%s" "$(ls "$(get_source_build_wheel_output_root)")" | |
printf "\n************************************************************************************" | |
} | |
build_dependencies_from_source() { | |
setup_src_build_dir_venv_and_enter | |
build_tensorflow | |
build_tensorflow_io # depends on tensorflow | |
build_tensorflow_addons # depends on tensorflow, tensorflow-io | |
build_tensorflow_text # depends on tensorflow, tensorflow-io | |
} | |
## Build commands | |
setup_src_build_dir_venv_and_enter() { | |
mkdir -p "${SRC_BUILDS_ROOT}" | |
cd "${SRC_BUILDS_ROOT}" | |
python -m venv .venv | |
source .venv/bin/activate | |
pip install pip wheel numpy | |
pip install keras_preprocessing --no-deps | |
} | |
build_tensorflow() { | |
clone_setup_and_enter_tf_proj_dir "tensorflow" "v${TF_VERSION}" | |
yes '' | ./configure || true #fallback to true to prevent non-zero exit code of configuration script from making the script exit early | |
local WHEEL_OUTPUT_ROOT="./tmp/tensorflow_pkg" | |
# sudo or else won't pick up the darwin_arm64 cc toolchain... | |
sudo bazel build --config="macos_${ARCH}" //tensorflow/tools/pip_package:build_pip_package | |
./bazel-bin/tensorflow/tools/pip_package/build_pip_package "${WHEEL_OUTPUT_ROOT}" | |
copy_wheel_to_source_builds_packages_dir "${WHEEL_OUTPUT_ROOT}/tensorflow-${TF_VERSION}-"*.whl | |
} | |
build_tensorflow_io() { | |
# https://github.com/tensorflow/io/issues/1298#issuecomment-958610412 | |
clone_setup_and_enter_tf_proj_dir "io" "v${TF_IO_VERSION}" | |
python setup.py -q bdist_wheel --project tensorflow_io_gcs_filesystem | |
copy_wheel_to_source_builds_packages_dir ./dist/tensorflow_io_gcs_filesystem-*.whl | |
} | |
build_tensorflow_addons() { | |
# https://github.com/tensorflow/addons | |
clone_setup_and_enter_tf_proj_dir "addons" "v${TF_ADDONS_VERSION}" | |
local WHEEL_OUTPUT_ROOT="./tmp/tensorflow_addon_pkg" | |
# Install Tensorflow IO & Tensorflow needed for text (built in the previous steps) | |
# Note: TF depends on TF IO, so must be installed in this order | |
pip install "$(get_source_build_wheel_output_root)/tensorflow_io_gcs_filesystem-${TF_IO_VERSION}-"*"${ARCH}.whl" | |
pip install "$(get_source_build_wheel_output_root)/tensorflow-${TF_VERSION}-"*"${ARCH}.whl" | |
python ./configure.py | |
# Update to compatible platform extension [OPTIONAL; here for conformity ] | |
sed -i '' "s/11_0_arm64/${MACOSX_DEPLOYMENT_TARGET}-$(arch)/g" "./build_deps/build_pip_pkg.sh" | |
bazel build build_pip_pkg | |
bazel-bin/build_pip_pkg "${WHEEL_OUTPUT_ROOT}" | |
copy_wheel_to_source_builds_packages_dir "${WHEEL_OUTPUT_ROOT}/tensorflow_addons-"*.whl | |
} | |
build_tensorflow_text() { | |
# Note: built bazel bin exported to path, so must restore old path upon function exit | |
local OLD_PATH="${PATH}" | |
local ORIG_BAZEL="$(which bazel)" | |
local ORIG_BAZEL_VER="$(get_bazel_version)" | |
_build_bazel3_7_2 | |
## https://github.com/tensorflow/text | |
clone_setup_and_enter_tf_proj_dir "text" "v${TF_TEXT_VERSION}" | |
# Install deps needed for text (built in the previous steps) | |
pip install "$(get_source_build_wheel_output_root)/tensorflow"*"${ARCH}.whl" | |
# Update to compatible platform extension [MANDATORY] | |
sed -i '' "s/10.9-x86_64/${MACOSX_DEPLOYMENT_TARGET}-$(arch)/g" "./oss_scripts/pip_package/build_pip_package.sh" | |
./oss_scripts/run_build.sh | |
copy_wheel_to_source_builds_packages_dir ./tensorflow_text-*.whl | |
rm .bazelversion | |
export PATH="${OLD_PATH}" | |
if [ "${ORIG_BAZEL_VER}" != "$(get_bazel_version)" ]; then | |
echo "Original bazel on path (${ORIG_BAZEL}) not the same bazel that is on path now! ($(which bazel)" | |
exit 2 | |
fi | |
} | |
## Bazel 3.7.2 needed for tensorflow-text | |
_build_bazel3_7_2() { | |
cd "${SRC_BUILDS_ROOT}" | |
local BAZEL_VER="3.7.2" | |
local BAZEL_RELEASES_URL="https://github.com/bazelbuild/bazel/releases/download" | |
local BAZEL_DIST_ARCHIVE="bazel-${BAZEL_VER}-dist.zip" | |
local BAZEL_DIST_ARCHIVE_CHECKSUM="${BAZEL_DIST_ARCHIVE}.sha256" | |
local BAZEL_DIST_PATH="${SRC_BUILDS_ROOT}/bazel" | |
mkdir -p "${BAZEL_DIST_PATH}" | |
# WARNING: do NOT try to be clever and pipe `curl` with `-L` directly to `tar`; the redirect will grab the GitHub source | |
# tree which is NOT what we want since only the distribution archive is configured to boostrap Bazel. | |
# https://docs.bazel.build/versions/main/install-compile-source.html#download-distfile | |
wget "${BAZEL_RELEASES_URL}/${BAZEL_VER}/${BAZEL_DIST_ARCHIVE}" | |
wget "${BAZEL_RELEASES_URL}/${BAZEL_VER}/${BAZEL_DIST_ARCHIVE_CHECKSUM}" | |
sha256sum -c "${BAZEL_DIST_ARCHIVE_CHECKSUM}" | |
unzip "${BAZEL_DIST_ARCHIVE}" -d "${BAZEL_DIST_PATH}" | |
rm "${BAZEL_DIST_ARCHIVE}" "${BAZEL_DIST_ARCHIVE_CHECKSUM}" | |
cd "${BAZEL_DIST_PATH}" | |
# https://github.com/bazelbuild/bazel/issues/11399#issuecomment-628945756 | |
brew install openjdk@11 | |
export JAVA_HOME="$(brew --prefix openjdk@11)/libexec/openjdk.jdk/Contents/Home" | |
# Specify EMBED_LABEL to override auto-generated (potentially-broken) bazel version imputed on dist builds | |
env \ | |
EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk" \ | |
EMBED_LABEL="${BAZEL_VER}" \ | |
bash ./compile.sh | |
# Note: would ideally like to just return `BAZEL_BIN_PATH` | |
# and perform the below in the calling function, but for some reason | |
# this doesn't make it out of the function to be captured; leaving | |
# it here is the only way to make it work | |
local BAZEL_BIN_PATH="$(pwd)/output" | |
export PATH="${BAZEL_BIN_PATH}:${PATH}" | |
if [ "${BAZEL_VER}" != "$(get_bazel_version)" ]; then | |
echo "bazel on path ($(which bazel)) not the same bazel that was just built! (${BAZEL_BIN_PATH}/bazel)" | |
exit 1 | |
fi | |
bazel --version # Log bazel version as a sanity check | |
} | |
## Helper commands | |
clone_setup_and_enter_tf_proj_dir() { | |
local TF_PROJ="${1}" | |
local GIT_TAG="${2}" | |
clone_and_enter_proj_dir "tensorflow/${TF_PROJ}" | |
git checkout "${GIT_TAG}" | |
get_bazel_version >.bazelversion # Use the newest bazel version; versions < 4.0 not supported on M1 and tensorflow sets this to version 3.7.1 as of 2021/11/13 | |
} | |
clone_and_enter_proj_dir() { | |
local GIT_REPO="${1}" | |
cd "${SRC_BUILDS_ROOT}" | |
local PROJ_DIR="$(basename ${GIT_REPO})" | |
rm -rf "${PROJ_DIR}" | |
git clone "https://github.com/${GIT_REPO}.git" && cd "${PROJ_DIR}" | |
} | |
get_bazel_version() { | |
bazel --version | awk '{print $2}' | |
} | |
copy_wheel_to_source_builds_packages_dir() { | |
local WHEEL_PATH="${1}" | |
cp -v "${WHEEL_PATH}" "$(get_source_build_wheel_output_root)" | |
} | |
get_source_build_wheel_output_root() { | |
local WHEEL_OUTPUT_ROOT="${PROJECT_ROOT}/packages/${SRC_BUILD_FOLDER_NAME}" | |
mkdir -p "${WHEEL_OUTPUT_ROOT}" | |
echo "${WHEEL_OUTPUT_ROOT}" | |
} | |
## Execute build process | |
main |
@TeoZosa The script keeps failing at line number 24, indicating it's not a git repo!
PROJECT_ROOT="$(git rev-parse --show-toplevel)"
Hey @nityansuman, feel free to replace that value with whatever directory you want. It only affects where the builds occur & packages are stored.
I am trying to install tensorflow-text to make it work on M1-Max chip. All the help will be appreciated. I have already installed metal and tf-macos from Apple.
FYI the tensorflow-text
built by this script may not be compatible with Apple's tensorflow-macos
and tensorflow-metal
; this script builds TF from scratch (without metal support) to link against. If it does work, let me know!
I tried your solution. And i had these errors and changed them respectively. And it worked fine.
python not found:
- changed python with python3
Could not build wheels for numpy which use PEP 517 and cannot be installed directly
- add one line before numpy install (remove also wheel and pip) pip install --upgrade pip setuptools wheel
And it stopped after keras. I needed to rerun it. But nothing changed. it says:
Cloning into 'tensorflow'...
remote: Enumerating objects: 1437548, done.
remote: Counting objects: 100% (265/265), done.
remote: Compressing objects: 100% (173/173), done.
Receiving objects: 33% (485407/1437548), 478.43 MiB | 3.01 MiB/s
but then stop running again.
@TeoZosa - thanks for the script.
But I get this error . I think tensorflow compiled fine but io package build failed. Before I start fixing myself , any thoughts ?
ERROR: tensorflow_io_gcs_filesystem-0.22.0-*arm64.whl is not a valid wheel filename.
@TeoZosa - thanks for the script. But I get this error . I think tensorflow compiled fine but io package build failed. Before I start fixing myself , any thoughts ? ERROR: tensorflow_io_gcs_filesystem-0.22.0-*arm64.whl is not a valid wheel filename.
@ashsha21: Hm, sounds like it. That error message is probably from the build_tensorflow_addons
step which sounds like the wheel didn't build and thus didn't get copied to the expected wheel output folder.
- Do you have any other error logs?
- Are any wheels built into the
io/dist
folder? - If (1) & (2) don't provide any useful clues, I just updated the script to include command traces and make
copy_wheel_to_source_builds_packages_dir
more verbose. You can try running the script again and seeing if any useful error messages pop up near that failed build step.- if Tensorflow already built sucessfully, then you can comment out
build_tensorflow
on line 66 to start compiling at the Tensorflow IO step.
- if Tensorflow already built sucessfully, then you can comment out
@TeoZosa thanks for the reply Teo. No , no other error messages. But for now I could use the prebuilt wheel from here https://github.com/sun1638650145/Libraries-and-Extensions-for-TensorFlow-for-Apple-Silicon/releases/tag/v2.8 . It worked to my surprise. The io and tf wheels were built but i guess add-on build failed because of "*" in the filename. Fo some reason script could not expand it.
@TeoZosa The script keeps failing at line number 24, indicating it's not a git repo!
PROJECT_ROOT="$(git rev-parse --show-toplevel)"
I am trying to install tensorflow-text to make it work on M1-Max chip. All the help will be appreciated. I have already installed metal and tf-macos from Apple.