Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 16, 2025

Conda-forge builds z3-solver for 5 Python versions (3.10-3.14), currently rebuilding the Python-version-independent libz3 library each time. This wastes 3-5 hours rebuilding identical C++ code.

Changes

New CMake option Z3_BUILD_LIBZ3_CORE (default ON):

  • When OFF, skips building libz3 and links Python bindings to pre-installed library
  • Uses find_library() to locate existing libz3 and creates imported CMake target
  • Automatically disables executable/test builds to avoid install failures

Modified build logic:

  • src/api/python/CMakeLists.txt: Detects imported vs regular libz3 target, adjusts source paths and dependencies accordingly
  • CMakeLists.txt: Conditionally exports Z3_EXPORTED_TARGETS only when building libz3 to prevent CMake errors

Documentation: Added usage example to README-CMake.md

Usage

# Build libz3 once
cmake -DZ3_BUILD_LIBZ3_SHARED=ON -DCMAKE_INSTALL_PREFIX=$PREFIX ..
make install

# Build Python bindings for each Python version (fast, no C++ compilation)
cmake -DZ3_BUILD_LIBZ3_CORE=OFF \
      -DZ3_BUILD_PYTHON_BINDINGS=ON \
      -DCMAKE_INSTALL_PREFIX=$PREFIX \
      -DPython3_EXECUTABLE=/path/to/python3.X \
      ..
make install

Reduces conda-forge build time from 3-5h to ~1h.

Original prompt

This section details on the original issue you should resolve

<issue_title>BLD: provide CMake option to install only python bindings</issue_title>
<issue_description>Hi!

I help run conda-forge, a big packaging ecosystem for python and many more languages. For almost a year, we've providing z3 as a package that can be installed also through conda install -c conda-forge z3-solver.

Conda as a paradigm is strictly more powerful than what PyPI and wheels can offer, namely, we can package native C/C++/Fortran libraries and binaries for linux/osx/win just as well as python libraries.

Unsurprisingly, the C++ library underlying z3-solver is independent of the python version being used. This is a very common pattern, and we like to package things in a way that reduces vendoring and other redundancies; in other words, there's a python-independent libz3, which z3-solver can then depend on, and everything works fine.

However, there's a limitation in building the package at the moment; due to the very bespoke python scripts/mk_make.py setup, I've preferred to go with the CMake-based builds; the problem with this is just that we're very inefficiently building the library portion 6 times, rather than once, namely (indentation indicates dependence):

  • libz3 - necessary ✅
    • z3-solver (py3.10) - rebuilds library, discards it because it matches what libz3 provides ❌
    • z3-solver (py3.11) - rebuilds library, discards it because it matches what libz3 provides ❌
    • z3-solver (py3.12) - rebuilds library, discards it because it matches what libz3 provides ❌
    • z3-solver (py3.13) - rebuilds library, discards it because it matches what libz3 provides ❌
    • z3-solver (py3.14) - rebuilds library, discards it because it matches what libz3 provides ❌

If there was an easy way to install just the python bindings on top of an already-installed libz3 (everything for us is happens in one central but relocatable $PREFIX), that would allow us to cut this down to building the library once, and then do only very quick installs for the python bindings. This would cut the build time from 3-5h down to ~1h.

I have enough experience with this that I could probably hack something together (and we do test our packages before publishing), but then it would be me who has to maintain it, and I was hoping that this is a reasonable request that the project would be willing to accommodate. 😅🙃 </issue_description>

Comments on the Issue (you are @copilot in this section)

@NikolajBjorner is this for updating cmakefiles.txt or setup.py? Either way, you can add a PR. Not sure what maintenance overhead you refer to: I can't maintain other packages outside of z3prover. If the package managers change and their use in z3 bit-rots beyond simple repair I disable them (for example, I don't upload nuget packages any longer because of enterprise signing obstacles and changed requirements for readme files). @NikolajBjorner I don't have competence or bandwidth to dig into cmake details. You are welcome to add a PR, I can assign this to copilot too and see what it comes up with.

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 3 commits November 16, 2025 18:16
Introduce Z3_BUILD_LIBZ3_CORE option (default ON) to control whether libz3 is built.
When set to OFF with Z3_BUILD_PYTHON_BINDINGS=ON, only Python bindings are built
using a pre-installed libz3 library. This is useful for package managers like
conda-forge to avoid rebuilding libz3 for each Python version.

Changes:
- Add Z3_BUILD_LIBZ3_CORE option in src/CMakeLists.txt
- When OFF, find and use pre-installed libz3 as imported target
- Update Python bindings CMakeLists.txt to handle both built and imported libz3
- Add documentation in README-CMake.md with usage examples

Co-authored-by: NikolajBjorner <[email protected]>
Conditionally export Z3_EXPORTED_TARGETS only when Z3_BUILD_LIBZ3_CORE=ON
to avoid errors when building Python bindings without building libz3.

Co-authored-by: NikolajBjorner <[email protected]>
When Z3_BUILD_LIBZ3_CORE=OFF, automatically disable Z3_BUILD_EXECUTABLE
and Z3_BUILD_TEST_EXECUTABLES to avoid build/install errors.

Co-authored-by: NikolajBjorner <[email protected]>
Copilot AI changed the title [WIP] Add CMake option to install only Python bindings BLD: Add CMake option to build Python bindings without rebuilding libz3 Nov 16, 2025
Copilot AI requested a review from NikolajBjorner November 16, 2025 18:48
Copilot finished work on behalf of NikolajBjorner November 16, 2025 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BLD: provide CMake option to install only python bindings

2 participants