<story><title>Bundling binary tools in Python wheels</title><url>https://simonwillison.net/2022/May/23/bundling-binary-tools-in-python-wheels/</url></story><parent_chain></parent_chain><comment><author>samwillis</author><text>I have just used this trick to package Node.js as a Python package [0], so you can just do:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  pip install nodejs-bin
&lt;/code&gt;&lt;/pre&gt;
to install it.&lt;p&gt;This works particularly well in combination with Python virtual environments (or docker), it will allow you to have a specific version of Node for a particular project without additional tooling. Just add &amp;quot;nodejs-bin&amp;quot; to your requirements.txt.&lt;p&gt;You can also add it as an optional dependency on another Python package. That&amp;#x27;s my plan with the full stack Python&amp;#x2F;Django&amp;#x2F;Apline.js framework I&amp;#x27;m building (Tetra[1]), that way users will be able to optional do this to setup the full project including Node.js:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  pip install tetraframework[full]
&lt;/code&gt;&lt;/pre&gt;
The framework uses esbuild, and will use PostCSS. It was either package them with the framework (including Node.js), or create a way to easily install Node.js for Python developers using the tools they are most used to.&lt;p&gt;It&amp;#x27;s brand new, I have only packed Node.js v16 so far. Once I&amp;#x27;m  happy there are no show stopping issues the plan is to release wheels for current+LTS Node.js versions as they come out.&lt;p&gt;Developer UX is my number one priority and removing the need for two toolchains is an important part of that.&lt;p&gt;[0]: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;pypi.org&amp;#x2F;project&amp;#x2F;nodejs-bin&amp;#x2F;&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;pypi.org&amp;#x2F;project&amp;#x2F;nodejs-bin&amp;#x2F;&lt;/a&gt;&lt;p&gt;[1]: &lt;a href=&quot;http:&amp;#x2F;&amp;#x2F;tetraframework.com&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;tetraframework.com&lt;/a&gt;</text></comment>
<story><title>Bundling binary tools in Python wheels</title><url>https://simonwillison.net/2022/May/23/bundling-binary-tools-in-python-wheels/</url></story><parent_chain></parent_chain><comment><author>ssl232</author><text>The Python wheel &amp;quot;ecosystem&amp;quot; is rather nice these days. You can create platform wheels and bundle in shared objects and binaries compiled for those platforms, automated by tools like auditwheel (Linux) and delocate-wheel (OSX). These tools even rewrite the wheel&amp;#x27;s manifest and update the shared object RPATH values and mangle the names to ensure they don&amp;#x27;t get clobbered by stuff in the system library path. The auditwheel tool converts a &amp;quot;linux&amp;quot; wheel into a &amp;quot;manylinux&amp;quot; wheel which is guaranteed by the spec to run on certain minimum Linux kernels.&lt;p&gt;Wheels are merely zips with a different extension, so worst case for projects where these automation tools fail you you can do it yourself. You simply need to be careful to update the manifest and make sure shared objects are loaded in the correct order.&lt;p&gt;On the user side, a `pip install` should automatically grab the relevant platform wheel from pypi.org, or, if there is not one available, fall back to trying to compile from source. With PEP 517 this all happens in a reproduceable, isolated build environment so if you manage to get it building on your CI pipeline it is likely to work on the end user&amp;#x27;s machine.&lt;p&gt;I&amp;#x27;m not sure what the state of wheels on Windows is these days. Is it possible to bundle DLLs in Windows wheels and have it &amp;quot;just work&amp;quot; the way it does for (most) Linux distros and OSX?</text></comment>