To enable binary extension modules in one layer to find dynamically linked libraries (like CUDA libraries) provided by a different layer, venvstacks implements a symlink and wrapper mechanism on Linux and macOS:
- Symlink Generation: During environment building, all shared object files that are not Python extension modules are symlinked into a
share/venv/dynlib folder within the built environment. - Runtime Wrapper: The symlink to the base environment's Python runtime is replaced with a wrapper script. This script ensures that the
share/venv/dynlib folders of all linked layers are added to the shared object loading path (LD_LIBRARY_PATH on Linux, DYLD_LIBRARY_PATH on macOS) before the Python runtime is invoked.
Note: Library path entries are appended to existing entries, so existing environment variables still take precedence.
Handling Conflicts: If multiple packages in the same layer provide dynamic libraries with the same name, a BuildEnvError is raised. You can resolve this using the dynlib_exclude option in your layer definition.
# Example of resolving a dynamic library conflict in a layer definition
layer_definition = {
"name": "my-layer",
"dynlib_exclude": ["libpng16.*"]
}
# Using path matching to be more specific
layer_definition_specific = {
"name": "my-layer",
"dynlib_exclude": ["PIL/**/libpng16.*"]
}
# Disabling all dynamic library symlinks for a layer
layer_definition_none = {
"name": "my-layer",
"dynlib_exclude": ["*"]
}