gumyr/build123d

How to install build123d on Apple Silicon macs (M1, M2, M3) with pip (and without conda / mamba)

Opened this issue · 4 comments

Problem Description

Currently, build123d cannot be installed on Apple Silicon macs, because it depends on cadquery-ocp, which is not available on PyPi (pip) for Apple Silicon.

Work is being done on getting it added:

The officially recommended workaround is to install conda or mambaforge where cadquery-ocp is available and then install build123d in that environment.

But managing multiple python packaging systems is difficult, error prone and annoying to use.

Fortunately, there is now a way to install cadquery-ocp and build123d on Apple Silicon macs without conda or mambaforge

Workaround

CadQuery makes the Apple Silicon packages available on their github release page. They just haven't been added to pip yet, due to the high storage requirements.

But you can install them directly from GitHub. You just have to match the package wheel URL to your python installation.

# Find out your python version
python --version

# For python 3.12:
pip install "https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp312-cp312-macosx_11_0_arm64.whl"

# For python 3.11:
pip install "https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp311-cp311-macosx_11_0_arm64.whl"

# For python 3.10:
pip install "https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp310-cp310-macosx_11_0_arm64.whl"

# For python 3.9:
pip install "https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp39-cp39-macosx_11_0_arm64.whl"

# Finally, install build123d:
pip install build123d

If you get an error like ERROR: cadquery_ocp-7.7.2-cp39-cp39-macosx_11_0_arm64.whl is not a supported wheel on this platform., it means that you selected the wrong URL for your python version.

To test if it worked, you can run python3 and then enter...

from build123d import *
print(Solid.make_box(1,2,3).show_topology(limit_class="Face"))

It should output the topology and no errors.

Logs

To help this issue be more discoverable on search engines, here are the potential errors that could be solved by this workaround:

❯ pip install build123d
Collecting build123d
  Using cached build123d-0.5.0-py3-none-any.whl.metadata (3.8 kB)
INFO: pip is looking at multiple versions of build123d to determine which version is compatible with other requirements. This could take a while.
  Downloading build123d-0.4.0-py3-none-any.whl.metadata (3.8 kB)
  Downloading build123d-0.3.0-py3-none-any.whl.metadata (3.8 kB)
  Downloading build123d-0.2.0-py3-none-any.whl.metadata (3.8 kB)
  Downloading build123d-0.1.1-py3-none-any.whl.metadata (3.6 kB)
ERROR: Cannot install build123d==0.1.1, build123d==0.2.0, build123d==0.3.0, build123d==0.4.0 and build123d==0.5.0 because these package versions have conflicting dependencies.

The conflict is caused by:
    build123d 0.5.0 depends on cadquery-ocp>=7.7.0
    build123d 0.4.0 depends on cadquery-ocp>=7.7.0
    build123d 0.3.0 depends on cadquery-ocp>=7.7.0
    build123d 0.2.0 depends on cadquery-ocp>=7.7.0
    build123d 0.1.1 depends on cadquery-ocp~=7.7.1

To fix this you could try to:
1. loosen the range of package versions you've specified
2. remove package versions to allow pip attempt to solve the dependency conflict

ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts

or

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/user_name/.pyenv/versions/3.10.0/lib/python3.10/site-packages/build123d/__init__.py", line 3, in <module>
    from build123d.build_common import *
  File "/Users/user_name/.pyenv/versions/3.10.0/lib/python3.10/site-packages/build123d/build_common.py", line 57, in <module>
    from build123d.geometry import Axis, Location, Plane, Vector, VectorLike
  File "/Users/user_name/.pyenv/versions/3.10.0/lib/python3.10/site-packages/build123d/geometry.py", line 54, in <module>
    from OCP.Bnd import Bnd_Box, Bnd_OBB
ModuleNotFoundError: No module named 'OCP'

And if you want to share your scripts on pypi or github you can use a setup.py like the one below. It will automatically install the Apple Silicon wheel from github instead of pypi on ARM macs.

Your users will be able to install it using pipx for example:

pipx install git+https://github.com/your-name/your_script

setup.py

import platform
import sys

from setuptools import setup, find_packages


# build123d require cadquery_ocp, but it's currently not available for arm
# macOS on pypi. But it is available as a wheel on github. This function
# installs the correct version on Apple Silicon systems
def gen_cadquery_ocp_requirement(system=None, machine=None):
    if system is None:
        system = platform.system()
    if machine is None:
        machine = platform.machine()

    python_version = f'cp{sys.version_info.major}{sys.version_info.minor}'

    requirement_str = 'cadquery-ocp'
    if system == 'Darwin' and machine == 'arm64':
        requirement_str = (
            f'cadquery-ocp @ https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-{python_version}-{python_version}-macosx_11_0_arm64.whl'
        )

    return requirement_str


setup(
    name='your_script',
    version='0.1',
    packages=find_packages(),
    install_requires=[
        gen_cadquery_ocp_requirement(),
        'build123d',
        'ocp_vscode',
    ],
    entry_points={
        'console_scripts': [
            'your_script=your_script:main',
        ],
    },
)

And it's actually possible with a pyproject.toml too:

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
version = "1.0"
name = "tp_extension_builder"

requires-python = ">=3.9"
dependencies = [
    # Regular dependencies
    "build123d",

    # build123d require cadquery_ocp, but it's currently not available for arm
    # macOS on pypi. But it is available as a wheel on github. This config
    # specifies the correct version on Apple Silicon systems depending on the
    # used python version
    'cadquery-ocp @ https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp39-cp39-macosx_11_0_arm64.whl ; platform_system == "Darwin" and platform_machine == "arm64" and python_version == "3.9"',
    'cadquery-ocp @ https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp310-cp310-macosx_11_0_arm64.whl ; platform_system == "Darwin" and platform_machine == "arm64" and python_version == "3.10"',
    'cadquery-ocp @ https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp311-cp311-macosx_11_0_arm64.whl ; platform_system == "Darwin" and platform_machine == "arm64" and python_version == "3.11"',
    'cadquery-ocp @ https://github.com/CadQuery/ocp-build-system/releases/download/7.7.2.0/cadquery_ocp-7.7.2-cp312-cp312-macosx_11_0_arm64.whl ; platform_system == "Darwin" and platform_machine == "arm64" and python_version == "3.12"',
]

Thanks for your efforts here. Personally, I don't have a Mac with Apple Silicon so I can't really contribute towards an install solution for this computer type. My understanding is that a pypi project can't contain content that's downloaded from GitHub so if I understand correctly this solution would have to be a separately downloaded install script - is that correct?

Ah, sorry about that. I haven’t been publishing my scripts to pypi and wasn’t aware of that limitation.

So, that means we do have to wait until cadquery-ocp uploads the wheels to pypi :)