CEP 28 - Customizable system DLL linkage checks for Windows
Title | Customizable system DLL linkage checks for Windows |
Status | Accepted |
Author(s) | Isuru Fernando <ifernando@openteams.com> |
Created | Aug 04, 2025 |
Updated | Oct 02, 2025 |
Discussion | https://github.com/conda/ceps/pull/128 |
Implementation | N/A |
Abstract
In conda build tools like conda-build
or rattler-build
there are postprocessing
checks to see that any executable/shared library built links to a set of
dynamic shared objects (DSOs) that satisfy some constraints. These constraints
are important to make sure that the built conda package works everywhere.
While conda build tools allow the user on Linux/macOS to customize the set of system DSOs, it is not so on Windows. This CEP aims to provide conda build tools users with a way to customize the system DSOs on Windows.
Motivation
Diving into Linux, in order for a package to work in another user's environment,
we require certain constraints on the DSOs. For example, we require a minimum version
of the GLIBC-provided libc.so.6
, libm.so.6
, etc libraries on the user system
as these are not provided by conda packages. We do require any non-system DSO to be
in the environment in a place where the dynamic loader will search,
i.e. on the rpath
of the executable/shared library that requires the DSO.
The constraints for the DSOs currently in conda build tools are:
For Linux,
-
If the DSO was in the specified host environment locations (
$PREFIX/<rpath>
, where<rpath>
entries are listed inbuild/rpath
), the DSO has to be installed as well; either as part of the same package or one of its dependencies. -
If the DSO was in a sysroot (
$BUILD_PREFIX/*/sysroot
), then these are system libraries and are allowed. These DSOs usually come fromsysroot_<subdir>
conda packages.
For macOS,
-
If the DSO was in the specified host environment locations (
$PREFIX/<rpath>
, where<rpath>
entries are listed inbuild/rpath
), the DSO has to be installed as well; either as part of the same package or one of its dependencies. -
If the DSO was in
CONDA_BUILD_SYSROOT
(the macOS SDK location), then these are system libraries and are allowed.
For Windows,
-
If the DSO was in the specified host environment locations (
$PREFIX/Scripts
,$PREFIX/Library/bin
, etc), the DSO has to be installed as well; either as part of the same package or one of its dependencies. -
If the DSO was in
CONDA_BUILD_SYSROOT
(this is unset in most scenarios), then these are system libraries and are allowed. -
If the DSO was in
C:\Windows\System32
, then these are system libraries and are allowed. -
If the DSO was in the
DEFAULT_WIN_WHITELIST
location defined by the build tool, then these are system libraries and are allowed.DEFAULT_WIN_WHITELIST
is a hardcoded constant inconda-build
andrattler-build
.
Note that for Linux and macOS, the user has a way of controlling which system
DSOs are allowed. On Linux, a user can modify the sysroot_linux-*
package
and on macOS, the user can specify a custom macOS SDK using CONDA_BUILD_SYSROOT
.
However, the user has no way of controlling which system DSOs are allowed
on Windows.
Need for customizability of allowed Windows system libraries
A user of conda build tools might need to customize the set of system DLLs.
An example from Linux is the removal of libnsl
from glibc
.
In this case, newer versions of glibc
dropped libnsl
and made it a separate package,
therefore conda-forge dropped it from sysroot_linux-*
packages to make sure
when new conda packages link to the libnsl
system library, the build tool will
warn or error out.
An example for Windows can be found in this issue: Warn when linking to debug VC runtimes.
In this case, the CI machines provide debug VC (Visual Studio) runtime DLLs and are
considered system DLLs by conda build tools, but these debug DLLs
are not always found in user systems. Also, linking to these debug DLLs
are not desirable and therefore should not be shipped it the corresponding
conda package (e.g. vc14_runtime
). Therefore we need a way to tell the build tool
which DLLs are allowed and which are not.
Specification
This CEP proposes a mechanism to control the allowed system DLLs on Windows.
When a JSON file provided by a conda package in host
or build
exists in
any of the following locations we use those list of files:
-
<BUILD_PREFIX>/etc/conda-build/dsolists.d/<conda-package-name>.json
-
<PREFIX>/etc/conda-build/dsolists.d/<conda-package-name>.json
The JSON file format is:
{
"version": 1,
"allow": [str],
"deny": [str],
"subdir": str
}
Here version
is for the version of the DSO list JSON schema and will always
be present for these files. The build tools should check the version and
validate that the version
is a known and supported version and error out
if not. This CEP specifies version=1
only and subsequent CEPs can revise
this format by changing the version
key.
The elements of the two lists allow
and deny
supports standard POSIX
globbing syntax; i.e., the following is allowed:
{
"version": 1,
"allow": [
"C:/Windows/System32/*.dll",
"**/R.dll",
],
"deny": [
"**/ucrtbased.dll",
],
"subdir": "win-64",
}
Note that forward slashes are used for path separation and only absolute paths
are allowed. Paths starting with **
are considered to be absolute paths.
These rules should be enforced by the build tool.
When no allow list is available among all the JSON files, but only deny lists are
available, a default C:/Windows/System32/*.dll
glob is assumed.
When no deny list is available among all the JSON files, but only allow lists are
available, an empty deny list is assumed. When neither are available,
conda build tools should fall back to the current method (as of August 2025).
When both allow lists and deny lists are available, allow lists among all the JSON files are processed first and then deny lists are processed.
Conclusion
In this CEP, we propose a method to allow users of conda build tools to control the allowed system DLLs on Windows, bringing it to feature parity with Linux and macOS.
Copyright
All CEPs are explicitly CC0 1.0 Universal.