How to create a development environment for build123d


I am very new to Nix and NixOS since my first install 2024-03-15 19:52. I am learning how to create a development environment for build123d, a Python based CAD API. A few days have passed and the struggle continues . . . I almost have it (I think).

If you can, please review what I have done, help me get it working, and give me some suggestions. Also, I don’t know Haskell, JSON, or Nix . . . so if you can clue me into what some of the common and best practices are. Thanks for sharing your time.

Here is my work:

  • The intended goal is to create a python development shell for the CAD application build123d.

  • System Information:

$ nixos-version  
24.05pre608655.ff0dbd94265a (Uakari)

$ inxi -z
CPU: 8-Core AMD Ryzen 7 7730U with Radeon Graphics (-MT MCP-) speed/min/max: 2061/400/4546 MHz Kernel: 6.6.25 x86_64 
Up: 13h 20m Mem: 22698.6/63719.8 MiB (35.6%) Storage: 1.82 TiB (83.1% used) Procs: 466 Shell: Bash inxi: 3.3.04 
# Recommended
>>> pip install build123d


# Development
>>> python3 -m pip install --upgrade pip
>>> git clone
>>> cd build123d
>>> python3 -m pip install -e .
>>> python
>>> from build123d import *
>>> print(Solid.make_box(1,2,3).show_topology(limit_class="Face"))
  • The test should yield the results similar to:
Solid        at 0x165e75379f0, Center(0.5, 1.0, 1.5)
└── Shell    at 0x165eab056f0, Center(0.5, 1.0, 1.5)
        ├── Face at 0x165b35a3570, Center(0.0, 1.0, 1.5)
        ├── Face at 0x165e77957f0, Center(1.0, 1.0, 1.5)
        ├── Face at 0x165b3e730f0, Center(0.5, 0.0, 1.5)
        ├── Face at 0x165e8821570, Center(0.5, 2.0, 1.5)
        ├── Face at 0x165e88218f0, Center(0.5, 1.0, 0.0)
        └── Face at 0x165eb21ee70, Center(0.5, 1.0, 3.0)
  • The output from the configured shell does not match the expected result, it is instead:
$ python

Python 3.11.8 (main, Feb  6 2024, 21:21:21) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> from build123d import *

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/technicus/Projects/CAD/build123d/build123d_03/build123d/lib/python3.11/site-packages/build123d/", line 3, in <module>
    from build123d.build_common import *
  File "/home/technicus/Projects/CAD/build123d/build123d_03/build123d/lib/python3.11/site-packages/build123d/", line 57, in <module>
    from build123d.geometry import Axis, Location, Plane, Vector, VectorLike
  File "/home/technicus/Projects/CAD/build123d/build123d_03/build123d/lib/python3.11/site-packages/build123d/", line 54, in <module>
    from OCP.Bnd import Bnd_Box, Bnd_OBB
ImportError: cannot open shared object file: No such file or directory
  • It is evidently having a problem linking libraries.

  • I have tried to follow What package provides and others like it, but have had no success, considering that I am having a little trouble following how to implement any of the solutions.

Thanks for reviewing my post.


Yeah, you did get pretty close. :o)

The most immediate problem is in the shellHook of the shell-python.nix.

    # Augment the dynamic linker path
    export "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${lib-path}"

    # fixes libstdc++ issues and issues
    LD_LIBRARY_PATH = lib.makeLibraryPath [ ];

In bash, A = abc and A=abc don’t mean the same thing. (And so this trips up when bash runs the shellHook).

The shellHook is a string that gets run by bash. – However, the ${...} values within the string get interpolated before being passed to bash. So, any “nix code” (like the lib.makeLibraryPath application) should be in a ${...}.

– I see these shells include e.g. lolcat and cowsay. That’s good troubleshooting instinct. The smaller problem to focus on could’ve been “why isn’t lolcat showing up?”. Perhaps adding a few echos into the shellHook (at the start, in the middle) would’ve helped you.

The next steps involve figuring out where to pass those native dependencies that Python wants. – Reading through the code, LD_LIBRARY_PATH uses lib-path, which is defined in terms of buildInputs, which also looks at the extraBuildInputs attribute that the shell-build123d.nix calls shell-python.nix with.

Should be:

  extraBuildInputs = with pkgs; [
    # this list contains packages that you want to be available at runtime and might not be able to be installed properly via pip

I’d suggest putting those example Python commands in a script like

from build123d import *

That way, you can see if this runs by running the command:

nix-shell shell-build123d.nix --command "python"

There are a few more shared libs you need, so extraBuildInputs needs a few more things. This’d best be left as an exercise, but you’re impatient:

  extraBuildInputs = with pkgs; [
    # this list contains packages that you want to be available at runtime and might not be able to be installed properly via pip

:sparkles: WOW! THANKS!!! :sparkles:

I knew it had to be something small.
I was also expecting more libraries to be needed.

This is awesome!

My first Nix shell . . . I have been struggling a few days.
A few people were insisting that I give up and leave Nix behind.

Or . . . try different approaches, like SergeK’s response in Why is it so hard to use a Python package?.

Now, I almost understand most of what this shell is doing.
Your explanation is great, I am going to be rereading it many times!
That test suggestion is awesome too!

Thanks so much!!!

An addition aspect has come to attention involving utility of tools for build123d. Specifically CQ-Editor, which is not in the Nix packages. There is a release which I can download, but due to how Nix manages packages, the binary can not be started.

So I need to learn how to (Run non Nix executables)[Frequently Asked Questions — documentation]. There are multiple methods, I will start with trying to add a library path that only applies to CQ-Editor by using nix-ld. Source code is available, so I will also try compiling it.

This is so exciting!