Draft

This is a draft and very much a work in progress. I’ll post it to the OpenSCAD mailing list once it’s done.

OpenSCAD is an amazing piece of open-source software. I assume you’re already familiar with it if you’re reading this, but if not go check it out.

While it bills itself as “The Programmer’s Solid 3D CAD Modeller,” it’s missing a major piece of the puzzle for today’s programmers: a package manager. I firmly believe that the lack of a solid package manager is holding back the OpenSCAD ecosystem in a big way.

Yes, there’s MCAD and a variety of free models linked on GitHub and Thingiverse. MCAD is great, but without a versioning mechanism, there’s really no way to improve the library in ways that break backwards compatibility. Ad hoc distribution via Thingiverse allows code to be shared, but that’s a long way from modern package management like RubyGems or PyPI.

With a proper package manager, it’s not hard to imagine an ecosystem where one can import a modules full of generators and vitamins that you combine together into your finished product. Many users already do this to some degree, anyway, and a package manager would only simplify the process.

There would also be a lot of value in publishing and iterating on common modules, rather than having every user blaze their own trail. There doesn’t seem to be as much “best practice” knowledge about OpenSCAD as there is about other languages, and I think a lot of that comes from the lack of “library code” being collaborated on. The central package registry would be a tremendous learning resource for improving how we use OpenSCAD.

So what does it need to look like?

Historically, there have been several discussions about a package manager for OpenSCAD, with a couple prototypes even started. From these discussions, I’ve gleaned a rough list of requirements.

  • Not Required - users who want to use OpenSCAD like they always have should be able to do so.
  • Central repository - there should be a central package repository/registry to download packages from, so that users have a single place to go to find packages.
  • Allow private repositories - long-term, we should support users running a private registry either as a proxy or to host private packages.
  • Doesn’t require OpenSCAD modifications - given the history of these efforts and limited developer resources for OpenSCAD, any package manager needs to work with the current OpenSCAD, without modification.
  • Built on existing tools - we should build on top of an existing package management system rather than start from scratch. This lowers the amount of new code we’ll need to maintain, lowers the barrier to minimum viable product, and should help us avoid a lot of growing pains. Since a package manager requires hosting infrastructure, there will be security concerns, and largely offloading these to an “upstream” package manager will absolve us from much of those headaches.
  • Supports versioned packages - supporting versions on both packages and dependencies is critical to allowing packages to be improved and support breaking changes. Packages should probably be built to follow SemVer, and the package manager should provide rich enough semantics to resolve compatible package versions with that in mind.

Proposal

I propose that we build a package system on top of the existing RubyGems ecosystem. OpenSCAD libraries can be packaged as RubyGems and then used by OpenSCAD with a minimum amount of tooling.

For a simple example, say we want to create a new project that uses scad_bundle. From the terminal, execute scad_bundle init which will create a new file, Gemfile. To add a couple libraries to our Gemfile we’ll add to it, so it looks like:

source "https://rubygems.org"

gem "openscad_layout"
gem "openscad_constants"

We’ll then run scad_bundle install to install those libraries.

Once your bundle is installed, simply run scad_bundle openscad to start OpenSCAD. scad_bundle will set your $OPENSCADPATH to include all of the libraries so that OpenSCAD can use them.

TODO: document more of this.

Why RubyGems?

Pretty simple, really: it’s a mature package manager that’s ready to go without any more effort

TODO: better explain this.

Downsides

Obviously, the need to have a working Ruby installation to use RubyGems as a package manager is a downside to this approach. However, the Ruby ecosystem is very mature at this point, and we’re using only the most vanilla aspects of it. This little slice of Ruby is easily as platform-agnostic as OpenSCAD itself.

Future Enhancements

There are various improvements to this system that could be tackled later.

  • While the initial prototype publishes OpenSCAD modules directly to RubyGems.org, we could run our own, separate repository just for OpenSCAD modules. RubyGems provides all the tooling to run your own gem server, and we could just use it. This would allow for a better community identity and have a dedicated site, but would require us to own and manage the infrastructure.
  • Rather than listing our dependencies in Gemfile, we could List them in a SCADfile (or similar) to make it obvious they are OpenSCAD files, not Ruby code.
  • OpenSCAD could be modified to look for a Gemfile in the directory (or parent directory) of the file you’re working on, so that we don’t need to run the scad_bundle wrapper to manipulate environment variables and start OpenSCAD.
  • Add some concept of a “private module” and “private function” to OpenSCAD so that a library can define modules and functions for internal use that are not accessible to users of the library. This would allow library designers to control the size of the public API their library exports.
  • Add namespace support to OpenSCAD to provide better isolation between libraries. Until then, name prefixing can be used.
  • Add a mechanism for libraries to specify a minimum version of OpenSCAD required to use the library.