diff --git a/.github/workflows/ci-nightly-build-test.yaml b/.github/workflows/ci-nightly-build-test.yaml index 2dda68e2a..9a748d476 100644 --- a/.github/workflows/ci-nightly-build-test.yaml +++ b/.github/workflows/ci-nightly-build-test.yaml @@ -69,7 +69,8 @@ concurrency: cancel-in-progress: true group: ${{github.workflow}}-${{github.event.pull_request.number||github.ref}} -permissions: read-all +permissions: + contents: read defaults: run: @@ -156,3 +157,46 @@ jobs: !/home/runner/.bazel/execroot/__main__/bazel-out/**/*.o !/home/runner/.bazel/execroot/__main__/bazel-out/**/_objs !/home/runner/.bazel/execroot/__main__/bazel-out/**/_solib_k8 + + Nightly-macOS: + if: needs.Decision.outputs.run == 'true' + name: Build and test (macOS) + needs: Decision + runs-on: macos-14 + steps: + - name: Check out a copy of the TFQ git repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Set up Python ${{inputs.py_version || env.py_version}} + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: ${{inputs.py_version || env.py_version}} + + - name: Set up Bazel + uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0 + with: + bazelrc: ${{env.bazelrc_additions}} + + - name: Build wheel + run: | + pip install --upgrade pip setuptools wheel + ./scripts/build_pip_package_test.sh + + - name: Test wheel + run: | + ./scripts/run_example.sh + + - name: Test rest of TFQ + run: | + set -o pipefail + ./scripts/test_all.sh 2>&1 | tee test_all.log + + - if: failure() || inputs.save_artifacts == 'true' + name: Make artifacts downloadable + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: test-artifacts-macos + retention-days: 7 + include-hidden-files: true + path: | + test_all.log diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7c61107f1..e2c6283e7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -34,7 +34,8 @@ concurrency: cancel-in-progress: true group: ${{github.workflow}}-${{github.event.pull_request.number||github.ref}} -permissions: read-all +permissions: + contents: read jobs: format-and-lint-checks: @@ -66,8 +67,12 @@ jobs: run: ./scripts/lint_all.sh wheel-build: - name: Wheel test - runs-on: ubuntu-22.04 + name: Wheel test (${{matrix.os}}) + runs-on: ${{matrix.os}} + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04, macos-14] timeout-minutes: 60 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -110,7 +115,28 @@ jobs: run: ./scripts/ci_install.sh - name: Configure CI TF - run: echo "Y\n" | ./configure.sh + run: printf "Y\n" | ./configure.sh + + - name: Full Library Test + run: ./scripts/test_all.sh + + bazel-tests-macos: + name: Library tests (macOS) + runs-on: macos-14 + timeout-minutes: 60 + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: ${{env.python-version}} + cache: pip + cache-dependency-path: requirements.txt + + - name: Install Bazel on CI + run: ./scripts/ci_install.sh + + - name: Configure CI TF + run: printf "Y\n" | ./configure.sh - name: Full Library Test run: ./scripts/test_all.sh diff --git a/README.md b/README.md index 85c382eec..5b81b2617 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ Please see the [installation instructions](https://www.tensorflow.org/quantum/install) in the documentation. _Compatibility_: At this time, TensorFlow Quantum is built and -tested on Linux with the following systems and software: +tested on Linux (`x86_64`) and macOS (Apple Silicon / `arm64`) with the +following systems and software: * Python 3.10–3.12 * TensorFlow 2.19.1 diff --git a/configure.sh b/configure.sh index f448c6aaf..881167cdd 100755 --- a/configure.sh +++ b/configure.sh @@ -107,7 +107,15 @@ while [[ -z "${TF_NEED_CUDA}" ]]; do read -p "${y_for_cpu}" INPUT || true case "${INPUT:-Y}" in [Yy]* ) echo "CPU build selected."; TF_NEED_CUDA=0;; - [Nn]* ) echo "GPU build selected."; TF_NEED_CUDA=1;; + [Nn]* ) + if is_macos; then + echo "GPU (CUDA) build is not supported on macOS; selecting CPU build." + TF_NEED_CUDA=0 + else + echo "GPU build selected." + TF_NEED_CUDA=1 + fi + ;; * ) echo "Please answer y or n.";; esac done @@ -141,10 +149,17 @@ lib_path = sc.get_lib() lib_dir = lib_path if os.path.isdir(lib_path) else os.path.dirname(lib_path) print(lib_dir) -cands = (glob.glob(os.path.join(lib_dir, 'libtensorflow_framework.so*')) or - glob.glob(os.path.join(lib_dir, 'libtensorflow.so*')) or - glob.glob(os.path.join(lib_dir, '_pywrap_tensorflow_internal.*'))) -print(os.path.basename(cands[0]) if cands else 'libtensorflow_framework.so.2') +if sys.platform == 'darwin': + cands = (glob.glob(os.path.join(lib_dir, 'libtensorflow_framework*.dylib')) or + glob.glob(os.path.join(lib_dir, 'libtensorflow*.dylib')) or + glob.glob(os.path.join(lib_dir, '_pywrap_tensorflow_internal.*'))) + default_lib = 'libtensorflow_framework.2.dylib' +else: + cands = (glob.glob(os.path.join(lib_dir, 'libtensorflow_framework.so*')) or + glob.glob(os.path.join(lib_dir, 'libtensorflow.so*')) or + glob.glob(os.path.join(lib_dir, '_pywrap_tensorflow_internal.*'))) + default_lib = 'libtensorflow_framework.so.2' +print(os.path.basename(sorted(cands)[0]) if cands else default_lib) PY ) @@ -189,11 +204,26 @@ write_bazelrc "common --experimental_repo_remote_exec" write_bazelrc "build --spawn_strategy=standalone" write_bazelrc "build --strategy=Genrule=standalone" write_bazelrc "build -c opt" -write_bazelrc "build --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=1" +if ! is_macos; then + write_bazelrc "build --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=1" +fi write_bazelrc "build --cxxopt=-std=c++17" +write_bazelrc "build --host_cxxopt=-std=c++17" write_bazelrc "build --action_env=TF_USE_LEGACY_KERAS=1" write_bazelrc "build --action_env=PYTHON_BIN_PATH=${PYTHON_BIN_PATH}" +if is_macos; then + write_bazelrc "build --macos_minimum_os=12.0" + write_bazelrc "build --host_macos_minimum_os=12.0" + write_bazelrc "build --copt=-DGRPC_BAZEL_BUILD" + write_bazelrc "build --host_copt=-DGRPC_BAZEL_BUILD" + write_bazelrc "build --features=archive_param_file" + write_bazelrc "build --linkopt=-Wl,-undefined,dynamic_lookup" + write_bazelrc "build --host_linkopt=-Wl,-undefined,dynamic_lookup" + write_bazelrc "build --linkopt=-Wl,-rpath,@loader_path/../../../tensorflow" + write_bazelrc "build --linkopt=-Wl,-rpath,@loader_path/../../../../tensorflow" +fi + # rpath so the dynamic linker finds TF’s shared lib if ! is_windows; then write_bazelrc "build --linkopt=-Wl,-rpath,${LIBDIR}" @@ -210,10 +240,12 @@ write_bazelrc 'build --per_file_copt=external/.*[.]c$@-Wno-deprecated-non-protot write_bazelrc 'build --host_per_file_copt=external/.*[.]c$@-Wno-deprecated-non-prototype' write_bazelrc "build --per_file_copt=external/com_google_protobuf/.*@-Wno-unused-function" write_bazelrc "build --host_per_file_copt=external/com_google_protobuf/.*@-Wno-unused-function" -write_bazelrc "build --per_file_copt=external/com_google_protobuf/.*@-Wno-stringop-overflow" -write_bazelrc "build --host_per_file_copt=external/com_google_protobuf/.*@-Wno-stringop-overflow" -write_bazelrc "build --per_file_copt=external/eigen/.*@-Wno-maybe-uninitialized" -write_bazelrc "build --host_per_file_copt=external/eigen/.*@-Wno-maybe-uninitialized" +if ! is_macos; then + write_bazelrc "build --per_file_copt=external/com_google_protobuf/.*@-Wno-stringop-overflow" + write_bazelrc "build --host_per_file_copt=external/com_google_protobuf/.*@-Wno-stringop-overflow" + write_bazelrc "build --per_file_copt=external/eigen/.*@-Wno-maybe-uninitialized" + write_bazelrc "build --host_per_file_copt=external/eigen/.*@-Wno-maybe-uninitialized" +fi # The following warnings come from qsim. # TODO: fix the code in qsim & update TFQ to use the updated version. diff --git a/docs/install.md b/docs/install.md index 7e90943e0..6402c1154 100644 --- a/docs/install.md +++ b/docs/install.md @@ -16,7 +16,7 @@ TensorFlow Quantum is supported on Python version 3.10 through 3.12 and depends ### Requirements -* pip 19.0 or later (requires `manylinux2014` support) +* pip 19.0 or later (requires `manylinux2014` support on Linux or macOS 12.0+ `arm64` on Apple Silicon) * [TensorFlow == 2.19.1](https://www.tensorflow.org/install/pip) See the [TensorFlow install guide](https://www.tensorflow.org/install/pip) to @@ -53,7 +53,7 @@ Success: TensorFlow Quantum is now installed. ## Build from source -The following steps are tested for Ubuntu-like systems. +The following steps are tested for Ubuntu-like Linux systems and macOS (Apple Silicon / `arm64`). ### 1. Set up a Python 3 development environment @@ -105,7 +105,9 @@ Download and install `bazel` version 6.5.0: -To prevent automatic updating of `bazel` to an incompatible version, run the following: +On macOS (Apple Silicon), you can install `bazelisk` via Homebrew (`brew install bazelisk`), which automatically selects Bazel 6.5.0 from `.bazelversion`, or download the `bazel-6.5.0-darwin-arm64` binary directly from the Bazel releases page. + +To prevent automatic updating of `bazel` to an incompatible version on Ubuntu/Debian, run the following:
diff --git a/release/README.md b/release/README.md
index f8cb277fb..8727ec11a 100644
--- a/release/README.md
+++ b/release/README.md
@@ -10,7 +10,7 @@ documents the process used by the TensorFlow Quantum maintainers to build and
release the packages for public TensorFlow Quantum distributions.
At present, binary distributions in the form of Python wheel files are made
-available only for Linux systems.
+available for Linux (`x86_64`) and macOS (Apple Silicon / `arm64`) systems.
## Version numbering policy
@@ -33,7 +33,8 @@ on, including:
* The version of Python and the local Python environment.
* The version of TensorFlow.
-* The TensorFlow build container used.
+* The TensorFlow build container used (on Linux) or Xcode/Clang toolchain
+ used (on macOS).
* The Crosstool configuration used.
* The dependency requirements implied by Cirq, TF-Keras, NumPy, Protobuf, and
other Python packages that TFQ and TF depend on.
@@ -61,8 +62,8 @@ into the upstream repository before proceeding further.
### Preliminary steps
-1. Make sure you have `docker`, `pyenv`, `pip`, and `jq` installed on your
- system.
+1. Make sure you have `pyenv`, `pip`, and `jq` installed on your system, plus
+ `docker` on Linux or Xcode Command Line Tools and Bazel 6.5.0 on macOS.
2. Git clone the TensorFlow Quantum repo to a directory on your computer.
@@ -94,7 +95,7 @@ into the upstream repository before proceeding further.
For each Python version _X.Y.Z_ that will be supported in the TFQ release, do
the following:
-1. Run `./release/build_release.sh X.Y.Z`.
+1. Run `./release/build_release.sh -p X.Y.Z`.
2. If the previous step fails, resolve the error.
diff --git a/release/build_distribution.sh b/release/build_distribution.sh
index fab8ddf02..a4859a287 100755
--- a/release/build_distribution.sh
+++ b/release/build_distribution.sh
@@ -71,21 +71,61 @@ while getopts "b:ehp:" opt; do
done
shift $((OPTIND -1))
-# See https://hub.docker.com/r/tensorflow/build/tags for available containers.
-docker_image="tensorflow/build:2.18-python${py_version}"
-
-# The next values must match what is used by the TF release being targeted. Look
-# in the TF .bazelrc file for the Linux CPU builds, specifically rbe_linux_cpu.
-tf_compiler="/usr/lib/llvm-18/bin/clang"
-tf_sysroot="/dt9"
-tf_crosstool="@local_config_cuda//crosstool:toolchain"
-
-# Create a script to be run by the shell inside the Docker container.
-build_script=$(mktemp /tmp/tfq_build.XXXXXX)
-trap 'rm -f "${build_script}" || true' EXIT
-
-# The printf'ed section dividers are to make it easier to search the output.
-cat < "${build_script}"
+if [[ "$(uname -s)" == "Darwin" ]]; then
+ cd "${repo_dir}"
+
+ if [[ -n "${PYTHON_BIN_PATH:-}" ]]; then
+ py_bin="${PYTHON_BIN_PATH}"
+ elif command -v "python${py_version}" > /dev/null 2>&1; then
+ py_bin="$(command -v "python${py_version}")"
+ else
+ py_bin="$(command -v python3)"
+ fi
+
+ printf ":::::::: Configuring Python environment (macOS) ::::::::\n\n"
+ "${py_bin}" -m pip install --upgrade pip
+ "${py_bin}" -m pip install -r requirements.txt
+
+ printf "\n\n:::::::: Configuring TFQ build (macOS) ::::::::\n\n"
+ printf "Y\n" | PYTHON_BIN_PATH="${py_bin}" ./configure.sh
+
+ printf "\n\n:::::::: Build configuration on macOS ::::::::\n"
+ printf " Platform: $(uname -s) ($(uname -m))\n"
+ printf " Python binary: ${py_bin}\n"
+ printf " Python version: "
+ "${py_bin}" --version | cut -d' ' -f2
+
+ printf "\n:::::::: Starting Bazel build ::::::::\n\n"
+ # shellcheck disable=SC2086
+ bazel build \
+ --cxxopt=-O3 \
+ ${extra_bazel_options} \
+ //release:build_pip_package
+
+ printf "\n:::::::: Creating Python wheel ::::::::\n\n"
+ mkdir -p /tmp/tensorflow_quantum
+ PYTHON_BIN_PATH="${py_bin}" ./bazel-bin/release/build_pip_package /tmp/tensorflow_quantum/
+
+ if [[ "${cleanup}" == "true" ]]; then
+ printf "\n:::::::: Cleaning up ::::::::\n\n"
+ bazel clean --async
+ fi
+else
+ # See https://hub.docker.com/r/tensorflow/build/tags for available containers.
+ docker_image="tensorflow/build:2.18-python${py_version}"
+
+ # The next values must match what is used by the TF release being targeted. Look
+ # in the TF .bazelrc file for the Linux CPU builds, specifically rbe_linux_cpu.
+ tf_compiler="/usr/lib/llvm-18/bin/clang"
+ tf_sysroot="/dt9"
+ tf_crosstool="@local_config_cuda//crosstool:toolchain"
+
+ # Create a script to be run by the shell inside the Docker container.
+ build_script=$(mktemp /tmp/tfq_build.XXXXXX)
+ trap 'rm -f "${build_script}" || true' EXIT
+
+ # The printf'ed section dividers are to make it easier to search the output.
+ cat < "${build_script}"
#!/bin/bash
set -o errexit
cd /tfq
@@ -127,17 +167,18 @@ if [[ "${cleanup}" == "true" ]]; then
fi
EOF
-chmod +x "${build_script}"
-
-echo "Spinning up a Docker container with ${docker_image} …"
-docker run -it --rm --network host \
- -w /tfq \
- -v "${repo_dir}":/tfq \
- -v /tmp/tensorflow_quantum:/build_output \
- -v "${build_script}:/tmp/build_script.sh" \
- -e HOST_PERMS="$(id -u):$(id -g)" \
- "${docker_image}" \
- /tmp/build_script.sh
+ chmod +x "${build_script}"
+
+ echo "Spinning up a Docker container with ${docker_image} …"
+ docker run -it --rm --network host \
+ -w /tfq \
+ -v "${repo_dir}":/tfq \
+ -v /tmp/tensorflow_quantum:/build_output \
+ -v "${build_script}:/tmp/build_script.sh" \
+ -e HOST_PERMS="$(id -u):$(id -g)" \
+ "${docker_image}" \
+ /tmp/build_script.sh
+fi
echo "Done. Look for wheel in /tmp/tensorflow_quantum/."
ls -l /tmp/tensorflow_quantum/
diff --git a/release/build_pip_package.sh b/release/build_pip_package.sh
index d8654e719..9e175d723 100755
--- a/release/build_pip_package.sh
+++ b/release/build_pip_package.sh
@@ -45,8 +45,8 @@ echo "Using Python: ${PY}"
EXPORT_DIR="bazel-bin/release/build_pip_package.runfiles/__main__"
main() {
- DEST="${1}"
- EXTRA_FLAGS="${2}"
+ DEST="${1:-}"
+ EXTRA_FLAGS="${2:-}"
if [[ -z "${DEST}" ]]; then
echo "No destination directory provided."
@@ -54,26 +54,33 @@ main() {
fi
mkdir -p "${DEST}"
+ DEST="$(cd "${DEST}" && pwd)"
echo "=== Destination directory for wheel file: ${DEST}"
# Build the pip package in a temporary directory.
- TMPDIR="$(mktemp -d -t tmp.XXXXXXXXXX)"
- echo "$(date) : === Using tmpdir: ${TMPDIR}"
+ # Avoid naming this variable TMPDIR because macOS exports TMPDIR in the
+ # environment, and overwriting it would cause `python -m build` to create its
+ # temporary isolated environment inside the package staging directory.
+ BUILD_TMPDIR="$(mktemp -d -t tmp.XXXXXXXXXX)"
+ trap 'rm -rf "${BUILD_TMPDIR}"' EXIT
+ echo "$(date) : === Using tmpdir: ${BUILD_TMPDIR}"
echo "=== Copying TFQ files"
- # Copy over files necessary to run setup.py
- cp "${EXPORT_DIR}/README.md" "${TMPDIR}"
- cp "${EXPORT_DIR}/release/setup.py" "${TMPDIR}"
- cp "${EXPORT_DIR}/release/MANIFEST.in" "${TMPDIR}"
- mkdir "${TMPDIR}/tensorflow_quantum"
- cp -r -v "${EXPORT_DIR}/tensorflow_quantum/"* "${TMPDIR}/tensorflow_quantum/"
+ # Copy over files necessary to run setup.py. Use -L so symlinks in Bazel's
+ # runfiles tree are dereferenced on both Linux (GNU cp) and macOS (BSD cp).
+ cp -L "${EXPORT_DIR}/README.md" "${BUILD_TMPDIR}"
+ cp -L "${EXPORT_DIR}/release/setup.py" "${BUILD_TMPDIR}"
+ cp -L "${EXPORT_DIR}/release/MANIFEST.in" "${BUILD_TMPDIR}"
+ mkdir "${BUILD_TMPDIR}/tensorflow_quantum"
+ cp -LR -v "${EXPORT_DIR}/tensorflow_quantum/"* "${BUILD_TMPDIR}/tensorflow_quantum/"
+ chmod -R u+w "${BUILD_TMPDIR}"
- pushd "${TMPDIR}"
+ pushd "${BUILD_TMPDIR}"
echo "$(date) : === Building wheel"
"${PY}" -m build -v --wheel ${EXTRA_FLAGS} > /dev/null
cp dist/*.whl "${DEST}"
popd
- rm -rf "${TMPDIR}"
+ rm -rf "${BUILD_TMPDIR}"
echo $(date) : "=== Output wheel file is in: ${DEST}"
}
diff --git a/release/build_release.sh b/release/build_release.sh
index 3d65ec25e..38cc4974c 100755
--- a/release/build_release.sh
+++ b/release/build_release.sh
@@ -71,15 +71,19 @@ if ! [[ "${py_version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
quit "The Python version must be a full version number in the form x.y.z."
fi
-setup_file="${repo_dir}/release/setup.py"
-if ! [[ -r "${setup_file}" ]]; then
- quit "Cannot read ${setup_file}"
+init_file="${repo_dir}/tensorflow_quantum/__init__.py"
+if ! [[ -r "${init_file}" ]]; then
+ quit "Cannot read ${init_file}"
fi
-tfq_cur_version=$(grep -m 1 CUR_VERSION "${setup_file}" | cut -f2 -d'"')
+tfq_cur_version=$(grep -E '^__version__' "${init_file}" | sed -E "s/.*['\"]([^'\"]+)['\"].*/\1/")
tfq_version=${tfq_cur_version}${build_number}
# Test these upfront to avoid failing mid-way through a long process.
-for program in docker pyenv jq; do
+required_programs=(pyenv jq)
+if [[ "$(uname -s)" != "Darwin" ]]; then
+ required_programs+=(docker)
+fi
+for program in "${required_programs[@]}"; do
if ! command -v "${program}" > /dev/null 2>&1; then
quit "Cannot run ${program} -- maybe it is not installed?"
fi
@@ -112,6 +116,9 @@ pyenv activate tfq-build-venv
pip install --upgrade pip
pip install wheel-inspect check-wheel-contents
+if [[ "$(uname -s)" == "Darwin" ]]; then
+ pip install delocate
+fi
# ~~~~~~~~ Build & clean the wheel ~~~~~~~~
diff --git a/release/clean_distribution.sh b/release/clean_distribution.sh
index 333aac357..eae9b258c 100755
--- a/release/clean_distribution.sh
+++ b/release/clean_distribution.sh
@@ -70,21 +70,42 @@ fi
wheel_path="$(cd "$(dirname "${1}")" && pwd)/$(basename "${1}")"
wheel_name="$(basename "${1}")"
-auditwheel_args=()
-if [[ "${action}" == "repair" ]]; then
- auditwheel_args+=(
- "--exclude" "libtensorflow_framework.so.2"
- "--plat" "${platform}"
- "-w" "/tfq/wheelhouse"
- )
-fi
+if [[ "$(uname -s)" == "Darwin" ]]; then
+ if ! command -v delocate-wheel > /dev/null 2>&1; then
+ echo "Installing delocate..."
+ python3 -m pip install delocate
+ fi
+
+ if [[ "${action}" == "show" ]]; then
+ echo "Running 'delocate-listdeps' on ${wheel_path}"
+ delocate-listdeps --all --depending "${wheel_path}"
+ else
+ mkdir -p "${repo_dir}/wheelhouse"
+ echo "Running 'delocate-wheel' on ${wheel_path}"
+ delocate-wheel \
+ -w "${repo_dir}/wheelhouse" \
+ -e "libtensorflow_framework" \
+ -v \
+ "${wheel_path}"
+ echo "Done. New wheel file written to ${repo_dir}/wheelhouse"
+ fi
+else
+ auditwheel_args=()
+ if [[ "${action}" == "repair" ]]; then
+ auditwheel_args+=(
+ "--exclude" "libtensorflow_framework.so.2"
+ "--plat" "${platform}"
+ "-w" "/tfq/wheelhouse"
+ )
+ fi
-echo "Running 'auditwheel ${action}' in Docker with image ${docker_image}"
-docker run -it --rm --network host \
- -w /tfq \
- -v "${repo_dir}":/tfq \
- -v "${wheel_path}":"/tmp/${wheel_name}" \
- "${docker_image}" \
- auditwheel "${action}" "${auditwheel_args[@]}" "/tmp/${wheel_name}"
+ echo "Running 'auditwheel ${action}' in Docker with image ${docker_image}"
+ docker run -it --rm --network host \
+ -w /tfq \
+ -v "${repo_dir}":/tfq \
+ -v "${wheel_path}":"/tmp/${wheel_name}" \
+ "${docker_image}" \
+ auditwheel "${action}" "${auditwheel_args[@]}" "/tmp/${wheel_name}"
-echo "Done. New wheel file written to ${repo_dir}/wheelhouse"
+ echo "Done. New wheel file written to ${repo_dir}/wheelhouse"
+fi
diff --git a/release/setup.py b/release/setup.py
index 83b94358e..78f60df6f 100644
--- a/release/setup.py
+++ b/release/setup.py
@@ -153,6 +153,8 @@ def has_ext_modules(self):
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Intended Audience :: Science/Research",
+ "Operating System :: MacOS :: MacOS X",
+ "Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
diff --git a/scripts/benchmark_all.sh b/scripts/benchmark_all.sh
index 642496aef..49ee3a8ec 100755
--- a/scripts/benchmark_all.sh
+++ b/scripts/benchmark_all.sh
@@ -14,7 +14,11 @@
# limitations under the License.
# ==============================================================================
echo "Testing benchmarks.";
-test_outputs=$(bazel test -c opt --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors $(bazel query //benchmarks/...))
+arch_cxxopts=()
+if [[ "$(uname -m)" == "x86_64" ]]; then
+ arch_cxxopts+=(--cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4")
+fi
+test_outputs=$(bazel test -c opt "${arch_cxxopts[@]}" --test_output=errors $(bazel query //benchmarks/...))
exit_code=$?
if [ "$exit_code" == "0" ]; then
@@ -26,5 +30,4 @@ else
fi
echo "Running preconfigured benchmarks.";
-bazel_run=${bazel run -c opt --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4"}
-bazel_run benchmarks/scripts:benchmark_clifford_circuit -- --op_density 1 --n_moments 10 --n_qubits 4
+bazel run -c opt "${arch_cxxopts[@]}" benchmarks/scripts:benchmark_clifford_circuit -- --op_density 1 --n_moments 10 --n_qubits 4
diff --git a/scripts/build_pip_package_test.sh b/scripts/build_pip_package_test.sh
index c77091945..a25100ee1 100755
--- a/scripts/build_pip_package_test.sh
+++ b/scripts/build_pip_package_test.sh
@@ -14,12 +14,19 @@
# limitations under the License.
# ==============================================================================
+set -e
+
pip install -r requirements.txt
# cd tensorflow_quantum
-echo "Y\n" | ./configure.sh
+printf "Y\n" | ./configure.sh
+
+arch_cxxopts=()
+if [[ "$(uname -m)" == "x86_64" ]]; then
+ arch_cxxopts+=(--cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4")
+fi
-bazel build -c opt --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" release:build_pip_package
-rm /tmp/tensorflow_quantum/* || echo ok
+bazel build -c opt "${arch_cxxopts[@]}" release:build_pip_package
+rm -f /tmp/tensorflow_quantum/* || echo ok
bazel-bin/release/build_pip_package /tmp/tensorflow_quantum/
pip install -U /tmp/tensorflow_quantum/*.whl
diff --git a/scripts/ci_install.sh b/scripts/ci_install.sh
index 28c58c2d7..2c2637bc6 100755
--- a/scripts/ci_install.sh
+++ b/scripts/ci_install.sh
@@ -13,7 +13,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
-wget https://github.com/bazelbuild/bazel/releases/download/6.5.0/bazel_6.5.0-linux-x86_64.deb
-sudo dpkg -i bazel_6.5.0-linux-x86_64.deb
+set -e
+
+BAZEL_VERSION="6.5.0"
+
+if [[ "$(uname -s)" == "Darwin" ]]; then
+ if ! command -v bazel >/dev/null 2>&1 || [[ "$(bazel --version 2>/dev/null)" != *"${BAZEL_VERSION}"* ]]; then
+ ARCH="$(uname -m)"
+ if [[ "${ARCH}" == "arm64" ]]; then
+ BAZEL_ARCH="arm64"
+ else
+ BAZEL_ARCH="x86_64"
+ fi
+ curl -fsSL -o /tmp/bazel \
+ "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-darwin-${BAZEL_ARCH}"
+ chmod +x /tmp/bazel
+ sudo mkdir -p /usr/local/bin
+ sudo mv /tmp/bazel /usr/local/bin/bazel
+ fi
+else
+ wget "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel_${BAZEL_VERSION}-linux-x86_64.deb"
+ sudo dpkg -i "bazel_${BAZEL_VERSION}-linux-x86_64.deb"
+fi
+
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
\ No newline at end of file
diff --git a/scripts/run_example.sh b/scripts/run_example.sh
index bb86edc22..be6953112 100755
--- a/scripts/run_example.sh
+++ b/scripts/run_example.sh
@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
+set -e
+export TF_USE_LEGACY_KERAS=1
cd ..
cp quantum/scripts/import_test.py import_test.py
python import_test.py
\ No newline at end of file
diff --git a/scripts/test_all.sh b/scripts/test_all.sh
index 1601a1607..7d7066a5e 100755
--- a/scripts/test_all.sh
+++ b/scripts/test_all.sh
@@ -14,7 +14,11 @@
# limitations under the License.
# ==============================================================================
echo "Testing All Bazel py_test and cc_tests.";
-test_outputs=$(bazel test -c opt --experimental_repo_remote_exec --test_output=errors --cxxopt="-std=c++17" --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" //tensorflow_quantum/...)
+arch_cxxopts=()
+if [[ "$(uname -m)" == "x86_64" ]]; then
+ arch_cxxopts+=(--cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4")
+fi
+test_outputs=$(bazel test -c opt --experimental_repo_remote_exec --test_output=errors --cxxopt="-std=c++17" "${arch_cxxopts[@]}" //tensorflow_quantum/...)
exit_code=$?
if [ "$exit_code" == "0" ]; then
echo "Testing Complete!";
diff --git a/scripts/test_benchmarks.sh b/scripts/test_benchmarks.sh
index 620676c4e..7ac92411a 100755
--- a/scripts/test_benchmarks.sh
+++ b/scripts/test_benchmarks.sh
@@ -14,7 +14,11 @@
# limitations under the License.
# ==============================================================================
echo "Testing all Benchmarks.";
-bazel test -c opt --cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4" --test_output=errors $(bazel query //benchmarks/scripts:all)
+arch_cxxopts=()
+if [[ "$(uname -m)" == "x86_64" ]]; then
+ arch_cxxopts+=(--cxxopt="-msse2" --cxxopt="-msse3" --cxxopt="-msse4")
+fi
+bazel test -c opt "${arch_cxxopts[@]}" --test_output=errors $(bazel query //benchmarks/scripts:all)
exit_code=$?
if [ "$exit_code" == "0" ]; then
echo "Testing Complete!";
diff --git a/tensorflow_quantum/core/ops/load_module.py b/tensorflow_quantum/core/ops/load_module.py
index 6fa350523..47b629e4c 100644
--- a/tensorflow_quantum/core/ops/load_module.py
+++ b/tensorflow_quantum/core/ops/load_module.py
@@ -15,8 +15,8 @@
"""Module to load python op libraries."""
import os
+import sysconfig
import types
-from distutils.sysconfig import get_python_lib
from tensorflow.python.framework import errors
from tensorflow.python.framework import load_library
@@ -49,7 +49,7 @@ def _load(self):
path = resource_loader.get_path_to_datafile(self._name)
self._module = load_library.load_op_library(path)
except (IOError, errors.NotFoundError):
- path = os.path.join(get_python_lib(),
+ path = os.path.join(sysconfig.get_path("platlib"),
"tensorflow_quantum/core/ops", self._name)
self._module = load_library.load_op_library(path)
return self._module
diff --git a/tensorflow_quantum/datasets/spin_system_test.py b/tensorflow_quantum/datasets/spin_system_test.py
index 682870c25..4b25379c5 100644
--- a/tensorflow_quantum/datasets/spin_system_test.py
+++ b/tensorflow_quantum/datasets/spin_system_test.py
@@ -91,7 +91,9 @@ def test_paulisum(self):
}
for n in self.random_subset_tfi_chain:
phi = cirq.Simulator().simulate(circuits[n]).final_state_vector
- e = pauli_sums[n].expectation_from_state_vector(phi, qubit_map)
+ e = pauli_sums[n].expectation_from_state_vector(phi,
+ qubit_map,
+ atol=1e-4)
self.assertAllClose(e, addinfo[n].gs_energy, rtol=1e-4)
def test_returned_objects(self):
@@ -190,7 +192,9 @@ def test_paulisum(self):
}
for n in self.random_subset_xxz_chain:
phi = cirq.Simulator().simulate(circuits[n]).final_state_vector
- e = pauli_sums[n].expectation_from_state_vector(phi, qubit_map)
+ e = pauli_sums[n].expectation_from_state_vector(phi,
+ qubit_map,
+ atol=1e-4)
self.assertAllClose(e, addinfo[n].gs_energy, rtol=5e-3)
def test_returned_objects(self):
@@ -293,7 +297,9 @@ def test_paulisum(self):
}
for n in self.random_subset_tfi_rectangular:
phi = cirq.Simulator().simulate(circuits[n]).final_state_vector
- e = pauli_sums[n].expectation_from_state_vector(phi, qubit_map)
+ e = pauli_sums[n].expectation_from_state_vector(phi,
+ qubit_map,
+ atol=1e-4)
self.assertAllClose(e, addinfo[n].gs_energy, rtol=5e-3)
def test_returned_objects(self):
diff --git a/third_party/tf/BUILD.tpl b/third_party/tf/BUILD.tpl
index f84d92959..0324951e2 100644
--- a/third_party/tf/BUILD.tpl
+++ b/third_party/tf/BUILD.tpl
@@ -9,7 +9,7 @@ cc_library(
cc_library(
name = "libtensorflow_framework",
- srcs = [":libtensorflow_framework.so"],
+ srcs = [":%{TF_SHARED_LIBRARY_OUTPUT}"],
#data = ["lib/libtensorflow_framework.so"],
visibility = ["//visibility:public"],
)
diff --git a/third_party/tf/tf_configure.bzl b/third_party/tf/tf_configure.bzl
index fedca1e38..ceb843126 100644
--- a/third_party/tf/tf_configure.bzl
+++ b/third_party/tf/tf_configure.bzl
@@ -41,6 +41,13 @@ def _is_windows(repository_ctx):
return True
return False
+def _is_macos(repository_ctx):
+ """Returns true if the host operating system is macOS."""
+ os_name = repository_ctx.os.name.lower()
+ if os_name.find("mac os") != -1 or os_name.find("darwin") != -1:
+ return True
+ return False
+
def _execute(
repository_ctx,
cmdline,
@@ -205,13 +212,20 @@ def _tf_pip_impl(repository_ctx):
tf_shared_library_name = repository_ctx.os.environ[_TF_SHARED_LIBRARY_NAME]
tf_shared_library_path = "%s/%s" % (tf_shared_library_dir, tf_shared_library_name)
+ if _is_windows(repository_ctx):
+ tf_shared_library_output = "_pywrap_tensorflow_internal.lib"
+ elif _is_macos(repository_ctx):
+ tf_shared_library_output = "libtensorflow_framework.dylib"
+ else:
+ tf_shared_library_output = "libtensorflow_framework.so"
+
tf_shared_library_rule = _symlink_genrule_for_dir(
repository_ctx,
None,
"",
"libtensorflow_framework_so",
[tf_shared_library_path],
- ["_pywrap_tensorflow_internal.lib" if _is_windows(repository_ctx) else "libtensorflow_framework.so"],
+ [tf_shared_library_output],
)
tf_test_log_proto_path = "%s/core/util/test_log_pb2.py" % tf_shared_library_dir
@@ -228,6 +242,7 @@ def _tf_pip_impl(repository_ctx):
_tpl(repository_ctx, "BUILD", {
"%{TF_HEADER_GENRULE}": tf_header_rule,
"%{TF_SHARED_LIBRARY_GENRULE}": tf_shared_library_rule,
+ "%{TF_SHARED_LIBRARY_OUTPUT}": tf_shared_library_output,
"%{TF_PROTO_GENRULE}": tf_proto_rule,
})