Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion .github/workflows/ci-nightly-build-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
34 changes: 30 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
52 changes: 42 additions & 10 deletions configure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
)

Expand Down Expand Up @@ -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}"
Expand All @@ -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.
Expand Down
8 changes: 5 additions & 3 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -105,7 +105,9 @@ Download and install `bazel` version 6.5.0:
</pre>
<!-- common_typos_enable -->

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:

<!-- common_typos_disable -->
<pre class="devsite-click-to-copy">
Expand Down
11 changes: 6 additions & 5 deletions release/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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.
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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.

Expand Down
93 changes: 67 additions & 26 deletions release/build_distribution.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 <<EOF > "${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 <<EOF > "${build_script}"
#!/bin/bash
set -o errexit
cd /tfq
Expand Down Expand Up @@ -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/
Loading
Loading