Cross-platform way to inspect Python installation

Hi!

Was working with cmake and was looking for a way to make it find Python just by providing general python installation path to PATH, instead of providing each component explicitly (e.g. PYTHON_LIBRARY=…, PYTHON_INCLUDE_DIR=…) and cmake has an issue in this regard - they’re either relying on explicit paths for each component or they to locate python3.xx-config and by examing it, cmake can figure out that headers are located in include/python3.13 and lib file for this installation is python3.13

Though they have sort of a bug that they focus on python3.xx-config and possible xx values are hardcoded in cmake files, so older versions of cmake couldn’t find newer version of Python, but either way, python3.xx-config wouldn’t be available on Windows, so technically cmake wouldn’t always be able to figure all components just from one base Python path.

Probably the easiest way would be to ask python executable, but it’s not always available since for build all you typically need is just headers / headers+libraries in MSVC.

Are there any alternative solutions to this that would work cross-platform?

Just found out about build-details.json, but for example Python 3.14 Windows installation doesn’t have it. And for build I was making on Linux, the file is located in python-3.14.0/lib/python3.14/build-details.json, so its path will be varying for each python version, which is probably not ideal for consistency.

1 Like

The Python sysconfig module has the answers. I know you said you don’t actually need to find the Python executable to build against Python headers/lib, but I’d say it’s worth exploring. We use that in SCons (a different build tool) when the build requests SWIG support and doing so made things much more reliable than the previous way.

It’ll be added as soon as it’s ready.[1] So check in the install root if it’s there, and if not then use whatever fallback code you probably already have.

Hmm… it was supposed to be in sys.prefix, but I guess that doesn’t make a ton of sense with a generic name (outside of Windows, where the prefix is always Python specific). I expect on Windows it’ll be in sys.prefix (the path listed by py list -f=prefix <version> or as InstallDir for a PEP 514 registration).

For Windows, you can very safely assume that “base path + \Include” and “base path + \libs” will be fine for the foreseeable future. It’s a bit harder to guess things like the ABI suffix (though Include\patchlevel.h can be parsed for the runtime version), but there’s definitely no need to run the executable.


  1. The initial implementation didn’t support relocatable installs, and so wasn’t any use for Windows. There’ll be a new implementation at some point, when it gets written… ↩︎

1 Like

build_details.json is intended to be the information you need from sysconfig without having to run the interpreter (which is important for cross-compilation and relocatable installs). So your answer is correct, but it’s also in the process of being replaced for scenarios such as building extensions.

By the time repackagers of Python have patched and reconfigured and compiled in weird ways and diced it up into -minimal/-dev/-doc/libpython packages, sysconfig provides less mileage than expected. If you wanted to know if libpython.so is available for example, it should be as simple as checking sysconfig.get_config_var("Py_ENABLE_SHARED") on Linux but Debian will say it is available even when the user needs to install a separate package to get it. And then Conda has the opposite problem – claiming that libpython.so is not available even when it is.

Possibly the variables you’re after are more predictable but don’t be too surprised if this falls over every time it encounters a new distribution of Python.

Actually, thinking about it more, build-details.json could really resolve this if user would provide not the general python installation path, but path to build-details.jsondir (though on Unix they will need to adjust it on each Python version change) and then it’s trivial to check whether the .json exists there and figure libs, includes, executables, version, etc.

Though really wish name was a little less generic - e.g. python-build-details.json. Searching a bit couldn’t find any other package using the exact same name, so maybe there are no collisions currently and it’s 99.999% safe to search it using PATH.