From fb4debbf1b664fa7411e494b053a6b705adb2efa Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 16 May 2023 12:07:16 -0400 Subject: [PATCH 01/19] Use stable Python C API for building Rust extension This commit tweaks the rust extension code to start using the PyO3 abi3 flag to build binaries that are compatible with all python versions, not just a single release. Previously, we were building against the version specific C API and that resulted in needing abinary file for each supported python version on each supported platform/architecture. By using the abi3 feature flag and marking the wheels as being built with the limited api we can reduce our packaging overhead to just having one wheel file per supported platform/architecture. The only real code change needed here was to update the memory marginalization function. PyO3's abi3 feature is incompatible with returning a big int object from rust (the C API they use for that conversion isn't part of the stable C API). So this commit updates the function to convert to create a python int manually using the PyO3 api where that was being done before. Co-authored-by: Jake Lishman --- crates/accelerate/Cargo.toml | 2 +- .../accelerate/src/results/marginalization.rs | 19 ++++++------------- crates/qasm2/Cargo.toml | 2 +- setup.py | 3 ++- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/crates/accelerate/Cargo.toml b/crates/accelerate/Cargo.toml index 7f057196b6a0..774767484571 100644 --- a/crates/accelerate/Cargo.toml +++ b/crates/accelerate/Cargo.toml @@ -26,7 +26,7 @@ rustworkx-core = "0.12" # can be done in the workspace and inherited once we hit Rust 1.64. [dependencies.pyo3] version = "0.18.3" -features = ["extension-module", "hashbrown", "indexmap", "num-complex", "num-bigint"] +features = ["extension-module", "hashbrown", "indexmap", "num-complex", "num-bigint", "abi3"] [dependencies.ndarray] version = "^0.15.6" diff --git a/crates/accelerate/src/results/marginalization.rs b/crates/accelerate/src/results/marginalization.rs index f71511f0e1b6..d0935e74ad7c 100644 --- a/crates/accelerate/src/results/marginalization.rs +++ b/crates/accelerate/src/results/marginalization.rs @@ -152,19 +152,12 @@ pub fn marginal_memory( .collect() }; if return_int { - if out_mem.len() < parallel_threshold || !run_in_parallel { - Ok(out_mem - .iter() - .map(|x| BigUint::parse_bytes(x.as_bytes(), 2).unwrap()) - .collect::>() - .to_object(py)) - } else { - Ok(out_mem - .par_iter() - .map(|x| BigUint::parse_bytes(x.as_bytes(), 2).unwrap()) - .collect::>() - .to_object(py)) - } + let int_pyobject = py.import("builtins")?.getattr("int")?; + Ok(out_mem + .iter() + .map(|x| int_pyobject.call1((x, 2u8)).unwrap()) + .collect::>() + .to_object(py)) } else { Ok(out_mem.to_object(py)) } diff --git a/crates/qasm2/Cargo.toml b/crates/qasm2/Cargo.toml index 67b567ea1121..04cd75a8f315 100644 --- a/crates/qasm2/Cargo.toml +++ b/crates/qasm2/Cargo.toml @@ -13,4 +13,4 @@ crate-type = ["cdylib"] [dependencies] hashbrown = "0.13.2" -pyo3 = { version = "0.18.3", features = ["extension-module"] } +pyo3 = { version = "0.18.3", features = ["extension-module", "abi3"] } diff --git a/setup.py b/setup.py index 352df8669fe8..f283cb3a4831 100755 --- a/setup.py +++ b/setup.py @@ -108,9 +108,10 @@ "crates/accelerate/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, + py_limited_api=True ), RustExtension( - "qiskit._qasm2", "crates/qasm2/Cargo.toml", binding=Binding.PyO3, debug=rust_debug + "qiskit._qasm2", "crates/qasm2/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, py_limited_api=True ), ], zip_safe=False, From d1e88b3721a0a02ecbc582098ec16873d2a09124 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 16 May 2023 12:37:53 -0400 Subject: [PATCH 02/19] Set minimum version on abi3 flag to Python 3.8 --- crates/accelerate/Cargo.toml | 2 +- crates/qasm2/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/accelerate/Cargo.toml b/crates/accelerate/Cargo.toml index 774767484571..c63620897c03 100644 --- a/crates/accelerate/Cargo.toml +++ b/crates/accelerate/Cargo.toml @@ -26,7 +26,7 @@ rustworkx-core = "0.12" # can be done in the workspace and inherited once we hit Rust 1.64. [dependencies.pyo3] version = "0.18.3" -features = ["extension-module", "hashbrown", "indexmap", "num-complex", "num-bigint", "abi3"] +features = ["extension-module", "hashbrown", "indexmap", "num-complex", "num-bigint", "abi3-py38"] [dependencies.ndarray] version = "^0.15.6" diff --git a/crates/qasm2/Cargo.toml b/crates/qasm2/Cargo.toml index 04cd75a8f315..9d09e44659ac 100644 --- a/crates/qasm2/Cargo.toml +++ b/crates/qasm2/Cargo.toml @@ -13,4 +13,4 @@ crate-type = ["cdylib"] [dependencies] hashbrown = "0.13.2" -pyo3 = { version = "0.18.3", features = ["extension-module", "abi3"] } +pyo3 = { version = "0.18.3", features = ["extension-module", "abi3-py38"] } From 6422de71642b534c83bbb390ea9087af086d057a Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 16 May 2023 12:38:58 -0400 Subject: [PATCH 03/19] Fix lint --- setup.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index f283cb3a4831..56ea509c6736 100755 --- a/setup.py +++ b/setup.py @@ -108,10 +108,14 @@ "crates/accelerate/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, - py_limited_api=True + py_limited_api=True, ), RustExtension( - "qiskit._qasm2", "crates/qasm2/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, py_limited_api=True + "qiskit._qasm2", + "crates/qasm2/Cargo.toml", + binding=Binding.PyO3, + debug=rust_debug, + py_limited_api=True, ), ], zip_safe=False, From 0cbe1409106f9736391971fe2860d918cd943165 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 16 May 2023 12:45:28 -0400 Subject: [PATCH 04/19] Use py_limited_api="auto" on RustExtension According to the docs for the setuptools-rust RustExtension class: https://setuptools-rust.readthedocs.io/en/latest/reference.html#setuptools_rust.RustExtension The best setting to use for the py_limited_api argument is `"auto"` as this will use the setting in the PyO3 module to determine the correct value to set. This commit updates the setup.py to follow the recommendation in the docs. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 56ea509c6736..b8f0574e5776 100755 --- a/setup.py +++ b/setup.py @@ -108,14 +108,14 @@ "crates/accelerate/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, - py_limited_api=True, + py_limited_api="auto", ), RustExtension( "qiskit._qasm2", "crates/qasm2/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, - py_limited_api=True, + py_limited_api="auto", ), ], zip_safe=False, From 7e5b027ba1a052f89babd345babfb1177cd5e19c Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 16 May 2023 14:09:15 -0400 Subject: [PATCH 05/19] Update handling of phase input to expval rust calls The pauli_expval module in Rust that Statevector and DensityMatrix leverage when computing defines the input type of the phase argument as Complex64. Previously, the quantum info code in the Statevector and DensityMatrix classes were passing in a 1 element ndarray for this parameter. When using the the version specific Python C API in pyo3 it would convert the single element array to a scalar value. However when using abi3 this handling was not done (or was not done correctly) and this caused the tests to fail. This commit updates the quantum info module to pass the phase as a complex value instead of a 1 element numpy array to bypass this behavior change in PyO3 when using abi3. Co-authored-by: Jake Lishman --- qiskit/quantum_info/states/densitymatrix.py | 1 + qiskit/quantum_info/states/statevector.py | 1 + 2 files changed, 2 insertions(+) diff --git a/qiskit/quantum_info/states/densitymatrix.py b/qiskit/quantum_info/states/densitymatrix.py index 124a382f01d1..8ed356327c45 100644 --- a/qiskit/quantum_info/states/densitymatrix.py +++ b/qiskit/quantum_info/states/densitymatrix.py @@ -382,6 +382,7 @@ def _expectation_value_pauli(self, pauli, qargs=None): x_max = qubits[pauli.x][-1] y_phase = (-1j) ** pauli._count_y() + y_phase = y_phase[0] return pauli_phase * density_expval_pauli_with_x( data, self.num_qubits, z_mask, x_mask, y_phase, x_max ) diff --git a/qiskit/quantum_info/states/statevector.py b/qiskit/quantum_info/states/statevector.py index 5c63a6628379..639f147b1e71 100644 --- a/qiskit/quantum_info/states/statevector.py +++ b/qiskit/quantum_info/states/statevector.py @@ -476,6 +476,7 @@ def _expectation_value_pauli(self, pauli, qargs=None): x_max = qubits[pauli.x][-1] y_phase = (-1j) ** pauli._count_y() + y_phase = y_phase[0] return pauli_phase * expval_pauli_with_x( self.data, self.num_qubits, z_mask, x_mask, y_phase, x_max From 4429cbea6ed9d1870cded555cbb5f09aadb86a99 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 16 May 2023 17:28:04 -0400 Subject: [PATCH 06/19] Set py_limited_api explicitly to True --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index b8f0574e5776..56ea509c6736 100755 --- a/setup.py +++ b/setup.py @@ -108,14 +108,14 @@ "crates/accelerate/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, - py_limited_api="auto", + py_limited_api=True, ), RustExtension( "qiskit._qasm2", "crates/qasm2/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, - py_limited_api="auto", + py_limited_api=True, ), ], zip_safe=False, From 8ca24cf1e4044e28dd96335d04b9b344d1019c60 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 10:07:01 -0400 Subject: [PATCH 07/19] DNM: Test cibuildwheel works with abi3 --- .azure/wheels.yml | 7 --- .github/workflows/wheels.yml | 26 +------- azure-pipelines.yml | 113 ++++++++++++++++------------------- 3 files changed, 55 insertions(+), 91 deletions(-) diff --git a/.azure/wheels.yml b/.azure/wheels.yml index 5b106747fd2d..8ddf4cf124a6 100644 --- a/.azure/wheels.yml +++ b/.azure/wheels.yml @@ -26,15 +26,8 @@ jobs: set -e python -m pip install --upgrade pip python -m pip install cibuildwheel==2.11.2 - python -m pip install -U twine cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'wheelhouse'} condition: succeededOrFailed() - - - bash: | - twine upload wheelhouse/* - env: - TWINE_USERNAME: "qiskit" - TWINE_PASSWORD: $(TWINE_PASSWORD) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 7b7bebc33e0a..e240057605dc 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -1,9 +1,8 @@ --- name: Wheel Builds on: - push: - tags: - - '*' + pull_request: + branches: ['main'] jobs: build_wheels_s390x: name: Build wheels on s390x @@ -31,13 +30,6 @@ jobs: - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl - - name: Install twine - run: python -m pip install twine - - name: Upload to PyPI - run: twine upload ./wheelhouse/*.whl - env: - TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} - TWINE_USERNAME: qiskit build_wheels_ppc64le: name: Build wheels on ppc64le runs-on: ${{ matrix.os }} @@ -64,13 +56,6 @@ jobs: - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl - - name: Install twine - run: python -m pip install twine - - name: Upload to PyPI - run: twine upload ./wheelhouse/*.whl - env: - TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} - TWINE_USERNAME: qiskit build_wheels_aarch64: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -96,10 +81,3 @@ jobs: - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl - - name: Install twine - run: python -m pip install twine - - name: Upload to PyPI - run: twine upload ./wheelhouse/*.whl - env: - TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} - TWINE_USERNAME: qiskit diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 91aee4bd562e..1c720a312321 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -126,6 +126,59 @@ stages: repositoryName: ${{ variables['Build.Repository.Name'] }} id: 7864 comment: Nightly test job failed at commit $(Build.SourceVersion). View the logs at $(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId). + # Push to a tag. The triggering tags are set in the triggers at the top of + # this file. + - ${{ if or(eq(variables['Build.Reason'], 'PullRequest'), contains(variables['Build.SourceBranch'], 'gh-readonly-queue')) }}: + - stage: "Deploy" + jobs: + - template: ".azure/wheels.yml" + parameters: + jobName: "linux" + pool: {vmImage: 'ubuntu-latest'} + + - template: ".azure/wheels.yml" + parameters: + jobName: "macos" + pool: {vmImage: 'macOS-11'} + + - template: ".azure/wheels.yml" + parameters: + jobName: "macos_arm" + pool: {vmImage: 'macOS-11'} + env: + CIBW_BEFORE_ALL: rustup target add aarch64-apple-darwin + CIBW_ARCHS_MACOS: arm64 universal2 + CIBW_ENVIRONMENT: >- + CARGO_BUILD_TARGET="aarch64-apple-darwin" + PYO3_CROSS_LIB_DIR="/Library/Frameworks/Python.framework/Versions/$(python -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')/lib/python$(python -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')" + + - template: ".azure/wheels.yml" + parameters: + jobName: "windows" + pool: {vmImage: 'windows-latest'} + setupPython: + - ${{ each version in parameters.supportedPythonVersions }}: + - task: UsePythonVersion@0 + inputs: + versionSpec: ${{ version }} + architecture: x86 + - task: UsePythonVersion@0 + inputs: + versionSpec: ${{ version }} + architecture: x64 + + - job: 'sdist' + pool: {vmImage: 'ubuntu-latest'} + steps: + - task: UsePythonVersion@0 + - bash: | + set -e + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools_rust + python setup.py sdist + - task: PublishBuildArtifacts@1 + inputs: {pathtoPublish: 'dist'} + condition: succeededOrFailed() # Full PR suite. This also needs to apply to the merge queue, which appears # as a push event. The queue won't get cron triggered because the schedule @@ -202,63 +255,3 @@ stages: testRust: true testQPY: true testImages: true - - # Push to a tag. The triggering tags are set in the triggers at the top of - # this file. - - ${{ if and(eq(variables['Build.Reason'], 'IndividualCI'), startsWith(variables['Build.SourceBranch'], 'refs/tags/')) }}: - - stage: "Deploy" - jobs: - - template: ".azure/wheels.yml" - parameters: - jobName: "linux" - pool: {vmImage: 'ubuntu-latest'} - - - template: ".azure/wheels.yml" - parameters: - jobName: "macos" - pool: {vmImage: 'macOS-11'} - - - template: ".azure/wheels.yml" - parameters: - jobName: "macos_arm" - pool: {vmImage: 'macOS-11'} - env: - CIBW_BEFORE_ALL: rustup target add aarch64-apple-darwin - CIBW_ARCHS_MACOS: arm64 universal2 - CIBW_ENVIRONMENT: >- - CARGO_BUILD_TARGET="aarch64-apple-darwin" - PYO3_CROSS_LIB_DIR="/Library/Frameworks/Python.framework/Versions/$(python -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')/lib/python$(python -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')" - - - template: ".azure/wheels.yml" - parameters: - jobName: "windows" - pool: {vmImage: 'windows-latest'} - setupPython: - - ${{ each version in parameters.supportedPythonVersions }}: - - task: UsePythonVersion@0 - inputs: - versionSpec: ${{ version }} - architecture: x86 - - task: UsePythonVersion@0 - inputs: - versionSpec: ${{ version }} - architecture: x64 - - - job: 'sdist' - pool: {vmImage: 'ubuntu-latest'} - steps: - - task: UsePythonVersion@0 - - bash: | - set -e - python -m pip install --upgrade pip - python -m pip install --upgrade setuptools_rust - python setup.py sdist - - task: PublishBuildArtifacts@1 - inputs: {pathtoPublish: 'dist'} - condition: succeededOrFailed() - - bash: | - python -m pip install --upgrade twine - twine upload dist/* - env: - TWINE_USERNAME: "qiskit" - TWINE_PASSWORD: $(TWINE_PASSWORD) From ee728139c4640ffa4eea730c019c1129cc754d33 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 10:24:49 -0400 Subject: [PATCH 08/19] Add abi3audit to cibuildwheel repair step --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 53b83021584a..c5e3328d8c9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,13 @@ environment = 'RUSTUP_TOOLCHAIN="stable"' [tool.cibuildwheel.linux] before-all = "yum install -y wget && {package}/tools/install_rust.sh" environment = 'PATH="$PATH:$HOME/.cargo/bin" CARGO_NET_GIT_FETCH_WITH_CLI="true" RUSTUP_TOOLCHAIN="stable"' +repair-wheel-command = "auditwheel repair -w {dest_dir} {wheel} && pipx run abi3audit --strict --report {wheel}" + +[tool.cibuildwheel.macos] +repair-wheel-command = "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} && pipx run abi3audit --strict --report {wheel}" + +[tool.cibuildwheel.windows] +repair-wheel-command = "pipx run abi3audit --strict --report {wheel}" [tool.ruff] select = [ From cd986c0d550b52b76f9da18334d1827489f35a67 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 11:21:55 -0400 Subject: [PATCH 09/19] Force setuptools to use abi3 tag --- setup.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/setup.py b/setup.py index 56ea509c6736..f4a02b6fcbaa 100755 --- a/setup.py +++ b/setup.py @@ -16,6 +16,16 @@ import re from setuptools import setup, find_packages from setuptools_rust import Binding, RustExtension +from wheel.bdist_wheel import bdist_wheel + + +class bdist_wheel_abi3(bdist_wheel): + def get_tag(self): + python, abi, plat = super().get_tag() + if python.startswith("cp"): + # on CPython, our wheels are abi3 and compatible back to 3.8 + return "cp38", "abi3", plat + return python, abi, plat with open("requirements.txt") as f: @@ -118,6 +128,7 @@ py_limited_api=True, ), ], + cmdclass={"bdist_wheel": bdist_wheel_abi3}, zip_safe=False, entry_points={ "qiskit.unitary_synthesis": [ From e3de73a9436d0d63dd0da980a904e34d0dbe1679 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 11:43:53 -0400 Subject: [PATCH 10/19] Add wheel to sdist build --- .azure/wheels.yml | 2 +- .github/workflows/wheels.yml | 6 +++--- azure-pipelines.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.azure/wheels.yml b/.azure/wheels.yml index 8ddf4cf124a6..6ccfded143a4 100644 --- a/.azure/wheels.yml +++ b/.azure/wheels.yml @@ -25,7 +25,7 @@ jobs: - bash: | set -e python -m pip install --upgrade pip - python -m pip install cibuildwheel==2.11.2 + python -m pip install cibuildwheel==2.13.0 cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index e240057605dc..9d0dd076de4b 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -23,7 +23,7 @@ jobs: with: platforms: all - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_ARCHS_LINUX: s390x CIBW_TEST_SKIP: "cp*" @@ -49,7 +49,7 @@ jobs: with: platforms: all - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_ARCHS_LINUX: ppc64le CIBW_TEST_SKIP: "cp*" @@ -75,7 +75,7 @@ jobs: with: platforms: all - name: Build wheels - uses: pypa/cibuildwheel@v2.11.2 + uses: pypa/cibuildwheel@v2.13.0 env: CIBW_ARCHS_LINUX: aarch64 - uses: actions/upload-artifact@v3 diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1c720a312321..95737168a8a1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -174,7 +174,7 @@ stages: - bash: | set -e python -m pip install --upgrade pip - python -m pip install --upgrade setuptools_rust + python -m pip install --upgrade setuptools_rust wheel python setup.py sdist - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'dist'} From 8dc009b9b6e360973aee2b02af0e6012cbc98c71 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 12:28:00 -0400 Subject: [PATCH 11/19] Workaround abiaudit3 not moving wheels and windows not having a default repair command --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c5e3328d8c9b..9a9663779a56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ repair-wheel-command = "auditwheel repair -w {dest_dir} {wheel} && pipx run abi3 repair-wheel-command = "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} && pipx run abi3audit --strict --report {wheel}" [tool.cibuildwheel.windows] -repair-wheel-command = "pipx run abi3audit --strict --report {wheel}" +repair-wheel-command = "cp {wheel} {dest_dir}/. && pipx run abi3audit --strict --report {wheel}" [tool.ruff] select = [ From 1d8f6f170a08ceed895f251c9390a16eabc4d68b Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 12:44:49 -0400 Subject: [PATCH 12/19] Add source of setup.py hack --- setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.py b/setup.py index f4a02b6fcbaa..48f5b68e6961 100755 --- a/setup.py +++ b/setup.py @@ -19,6 +19,8 @@ from wheel.bdist_wheel import bdist_wheel +# Taken from https://github.com/joerick/python-abi3-package-sample/blob/5273fc5446a14cbb422a0c2c09635d968b77ec53/setup.py +# to get abi3 tagged reliably class bdist_wheel_abi3(bdist_wheel): def get_tag(self): python, abi, plat = super().get_tag() From 0b0c030b6b79fdc5008d2ca7c059fe073f2d2ede Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 12:48:20 -0400 Subject: [PATCH 13/19] Add comment about pending pyo3 abi3 bigint support --- crates/accelerate/src/results/marginalization.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/accelerate/src/results/marginalization.rs b/crates/accelerate/src/results/marginalization.rs index d0935e74ad7c..08e1b42e287e 100644 --- a/crates/accelerate/src/results/marginalization.rs +++ b/crates/accelerate/src/results/marginalization.rs @@ -152,6 +152,18 @@ pub fn marginal_memory( .collect() }; if return_int { + // Replace with: + // + // .iter() + // .map(|x| BigUint::parse_bytes(x.as_bytes(), 2).unwrap()) + // .collect::>() + // .to_object(py)) + // + // (also this can be done in parallel, see + // https://github.com/Qiskit/qiskit-terra/pull/10120 for more + // details) + // + // After PyO3/pyo3#3198 is included in a pyo3 release. let int_pyobject = py.import("builtins")?.getattr("int")?; Ok(out_mem .iter() From d23e60cbbe678e36011902a7b197d5ea0c4aaf55 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 12:50:18 -0400 Subject: [PATCH 14/19] Revert "DNM: Test cibuildwheel works with abi3" This reverts commit 8ca24cf1e4044e28dd96335d04b9b344d1019c60. --- .azure/wheels.yml | 7 +++ .github/workflows/wheels.yml | 26 +++++++- azure-pipelines.yml | 113 +++++++++++++++++++---------------- 3 files changed, 91 insertions(+), 55 deletions(-) diff --git a/.azure/wheels.yml b/.azure/wheels.yml index 6ccfded143a4..fa8ecd17a051 100644 --- a/.azure/wheels.yml +++ b/.azure/wheels.yml @@ -26,8 +26,15 @@ jobs: set -e python -m pip install --upgrade pip python -m pip install cibuildwheel==2.13.0 + python -m pip install -U twine cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'wheelhouse'} condition: succeededOrFailed() + + - bash: | + twine upload wheelhouse/* + env: + TWINE_USERNAME: "qiskit" + TWINE_PASSWORD: $(TWINE_PASSWORD) diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 9d0dd076de4b..8a7e22bb9c82 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -1,8 +1,9 @@ --- name: Wheel Builds on: - pull_request: - branches: ['main'] + push: + tags: + - '*' jobs: build_wheels_s390x: name: Build wheels on s390x @@ -30,6 +31,13 @@ jobs: - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl + - name: Install twine + run: python -m pip install twine + - name: Upload to PyPI + run: twine upload ./wheelhouse/*.whl + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit build_wheels_ppc64le: name: Build wheels on ppc64le runs-on: ${{ matrix.os }} @@ -56,6 +64,13 @@ jobs: - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl + - name: Install twine + run: python -m pip install twine + - name: Upload to PyPI + run: twine upload ./wheelhouse/*.whl + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit build_wheels_aarch64: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -81,3 +96,10 @@ jobs: - uses: actions/upload-artifact@v3 with: path: ./wheelhouse/*.whl + - name: Install twine + run: python -m pip install twine + - name: Upload to PyPI + run: twine upload ./wheelhouse/*.whl + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 95737168a8a1..91aee4bd562e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -126,59 +126,6 @@ stages: repositoryName: ${{ variables['Build.Repository.Name'] }} id: 7864 comment: Nightly test job failed at commit $(Build.SourceVersion). View the logs at $(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId). - # Push to a tag. The triggering tags are set in the triggers at the top of - # this file. - - ${{ if or(eq(variables['Build.Reason'], 'PullRequest'), contains(variables['Build.SourceBranch'], 'gh-readonly-queue')) }}: - - stage: "Deploy" - jobs: - - template: ".azure/wheels.yml" - parameters: - jobName: "linux" - pool: {vmImage: 'ubuntu-latest'} - - - template: ".azure/wheels.yml" - parameters: - jobName: "macos" - pool: {vmImage: 'macOS-11'} - - - template: ".azure/wheels.yml" - parameters: - jobName: "macos_arm" - pool: {vmImage: 'macOS-11'} - env: - CIBW_BEFORE_ALL: rustup target add aarch64-apple-darwin - CIBW_ARCHS_MACOS: arm64 universal2 - CIBW_ENVIRONMENT: >- - CARGO_BUILD_TARGET="aarch64-apple-darwin" - PYO3_CROSS_LIB_DIR="/Library/Frameworks/Python.framework/Versions/$(python -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')/lib/python$(python -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')" - - - template: ".azure/wheels.yml" - parameters: - jobName: "windows" - pool: {vmImage: 'windows-latest'} - setupPython: - - ${{ each version in parameters.supportedPythonVersions }}: - - task: UsePythonVersion@0 - inputs: - versionSpec: ${{ version }} - architecture: x86 - - task: UsePythonVersion@0 - inputs: - versionSpec: ${{ version }} - architecture: x64 - - - job: 'sdist' - pool: {vmImage: 'ubuntu-latest'} - steps: - - task: UsePythonVersion@0 - - bash: | - set -e - python -m pip install --upgrade pip - python -m pip install --upgrade setuptools_rust wheel - python setup.py sdist - - task: PublishBuildArtifacts@1 - inputs: {pathtoPublish: 'dist'} - condition: succeededOrFailed() # Full PR suite. This also needs to apply to the merge queue, which appears # as a push event. The queue won't get cron triggered because the schedule @@ -255,3 +202,63 @@ stages: testRust: true testQPY: true testImages: true + + # Push to a tag. The triggering tags are set in the triggers at the top of + # this file. + - ${{ if and(eq(variables['Build.Reason'], 'IndividualCI'), startsWith(variables['Build.SourceBranch'], 'refs/tags/')) }}: + - stage: "Deploy" + jobs: + - template: ".azure/wheels.yml" + parameters: + jobName: "linux" + pool: {vmImage: 'ubuntu-latest'} + + - template: ".azure/wheels.yml" + parameters: + jobName: "macos" + pool: {vmImage: 'macOS-11'} + + - template: ".azure/wheels.yml" + parameters: + jobName: "macos_arm" + pool: {vmImage: 'macOS-11'} + env: + CIBW_BEFORE_ALL: rustup target add aarch64-apple-darwin + CIBW_ARCHS_MACOS: arm64 universal2 + CIBW_ENVIRONMENT: >- + CARGO_BUILD_TARGET="aarch64-apple-darwin" + PYO3_CROSS_LIB_DIR="/Library/Frameworks/Python.framework/Versions/$(python -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')/lib/python$(python -c 'import sys; print(str(sys.version_info[0])+"."+str(sys.version_info[1]))')" + + - template: ".azure/wheels.yml" + parameters: + jobName: "windows" + pool: {vmImage: 'windows-latest'} + setupPython: + - ${{ each version in parameters.supportedPythonVersions }}: + - task: UsePythonVersion@0 + inputs: + versionSpec: ${{ version }} + architecture: x86 + - task: UsePythonVersion@0 + inputs: + versionSpec: ${{ version }} + architecture: x64 + + - job: 'sdist' + pool: {vmImage: 'ubuntu-latest'} + steps: + - task: UsePythonVersion@0 + - bash: | + set -e + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools_rust + python setup.py sdist + - task: PublishBuildArtifacts@1 + inputs: {pathtoPublish: 'dist'} + condition: succeededOrFailed() + - bash: | + python -m pip install --upgrade twine + twine upload dist/* + env: + TWINE_USERNAME: "qiskit" + TWINE_PASSWORD: $(TWINE_PASSWORD) From 402ec292a59c697bd3531380fd6cfee1d33f0883 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 12:56:59 -0400 Subject: [PATCH 15/19] Add release note --- releasenotes/notes/use-abi3-4a935e0557d3833b.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 releasenotes/notes/use-abi3-4a935e0557d3833b.yaml diff --git a/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml b/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml new file mode 100644 index 000000000000..5281841e1918 --- /dev/null +++ b/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml @@ -0,0 +1,14 @@ +--- +upgrade: + - | + By default Qiskit builds it's compiled extensions using the + `Python Stable ABI `__ + with support back to Python 3.8. This means that moving forward there + will be a single precompiled wheels that are shipped on release that + works with all of Qiskit's supported Python versions. Previously, + the compiled extensions were built using the version specific API and + would only work with a single Python version. This change was made + to reduce the number of package files we need to build and publish in each + release. When building Qiskit from source there should be no changes + necessary to the build process except that the default tags in the output + filenames will be different to reflect the use of the limited API. From deee6b01e4f8676d0f86bf8e893dcc846f4f1455 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 2 Jun 2023 15:05:02 -0400 Subject: [PATCH 16/19] Simplify setting abi3 tag in built wheels --- setup.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/setup.py b/setup.py index 48f5b68e6961..ec0420f70691 100755 --- a/setup.py +++ b/setup.py @@ -16,18 +16,6 @@ import re from setuptools import setup, find_packages from setuptools_rust import Binding, RustExtension -from wheel.bdist_wheel import bdist_wheel - - -# Taken from https://github.com/joerick/python-abi3-package-sample/blob/5273fc5446a14cbb422a0c2c09635d968b77ec53/setup.py -# to get abi3 tagged reliably -class bdist_wheel_abi3(bdist_wheel): - def get_tag(self): - python, abi, plat = super().get_tag() - if python.startswith("cp"): - # on CPython, our wheels are abi3 and compatible back to 3.8 - return "cp38", "abi3", plat - return python, abi, plat with open("requirements.txt") as f: @@ -120,17 +108,15 @@ def get_tag(self): "crates/accelerate/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, - py_limited_api=True, ), RustExtension( "qiskit._qasm2", "crates/qasm2/Cargo.toml", binding=Binding.PyO3, debug=rust_debug, - py_limited_api=True, ), ], - cmdclass={"bdist_wheel": bdist_wheel_abi3}, + options={"bdist_wheel": {"py_limited_api": "cp38"}}, zip_safe=False, entry_points={ "qiskit.unitary_synthesis": [ From 948cce85800470bbfde26d9818b6762f71d35761 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 5 Jun 2023 12:27:31 -0400 Subject: [PATCH 17/19] Update releasenotes/notes/use-abi3-4a935e0557d3833b.yaml Co-authored-by: Jake Lishman --- releasenotes/notes/use-abi3-4a935e0557d3833b.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml b/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml index 5281841e1918..d9a9309cc986 100644 --- a/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml +++ b/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml @@ -1,7 +1,7 @@ --- upgrade: - | - By default Qiskit builds it's compiled extensions using the + By default Qiskit builds its compiled extensions using the `Python Stable ABI `__ with support back to Python 3.8. This means that moving forward there will be a single precompiled wheels that are shipped on release that From 6257bdd2e749368eba8a95f8612ed556b2c13580 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 5 Jun 2023 12:35:17 -0400 Subject: [PATCH 18/19] Update release note --- releasenotes/notes/use-abi3-4a935e0557d3833b.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml b/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml index d9a9309cc986..865137ddd661 100644 --- a/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml +++ b/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml @@ -3,11 +3,14 @@ upgrade: - | By default Qiskit builds its compiled extensions using the `Python Stable ABI `__ - with support back to Python 3.8. This means that moving forward there + with support back to the oldest version of Python supported by Qiskit + (currently 3.8). This means that moving forward there will be a single precompiled wheels that are shipped on release that - works with all of Qiskit's supported Python versions. Previously, - the compiled extensions were built using the version specific API and - would only work with a single Python version. This change was made + works with all of Qiskit's supported Python versions. There isn't any + expected runtime performance difference using the limited API so it is + enabled by default for all builds now. + Previously, the compiled extensions were built using the version specific API and + would only work with a single Python version. . This change was made to reduce the number of package files we need to build and publish in each release. When building Qiskit from source there should be no changes necessary to the build process except that the default tags in the output From 7a83c7984a807e290aa82b5a2f67aa2fb3b1ca2c Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Mon, 5 Jun 2023 17:56:42 +0100 Subject: [PATCH 19/19] Update releasenotes/notes/use-abi3-4a935e0557d3833b.yaml --- releasenotes/notes/use-abi3-4a935e0557d3833b.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml b/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml index 865137ddd661..db946ded97ef 100644 --- a/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml +++ b/releasenotes/notes/use-abi3-4a935e0557d3833b.yaml @@ -10,7 +10,7 @@ upgrade: expected runtime performance difference using the limited API so it is enabled by default for all builds now. Previously, the compiled extensions were built using the version specific API and - would only work with a single Python version. . This change was made + would only work with a single Python version. This change was made to reduce the number of package files we need to build and publish in each release. When building Qiskit from source there should be no changes necessary to the build process except that the default tags in the output