diff --git a/src/core/opamStd.mli b/src/core/opamStd.mli index 4864d618397..5354ae10695 100644 --- a/src/core/opamStd.mli +++ b/src/core/opamStd.mli @@ -413,7 +413,29 @@ module Env : sig (** {3 Environment variable handling} *) - (** Environment variable names *) + (** Environment variable names. Windows has complicated semantics for + environment variables. The retrieval functions are case insensitive, but + it's "legal" for the environment block to contain entries which differ + only by case. If environment variables are set entirely using CRT or Win32 + API functions, then there isn't usually a problem, the issue arises when + creating a program where the environment block is instead passed. In this + model, it's very easy to end up with two bindings in the same block. When + dealing with Windows programs, this will mostly be transparent, but it's a + problem with Cygwin which actively allows "duplicate" entries which differ + by case only and implements Posix semantics on top of this. The problem is + constantly with us thanks to the use of PATH on Unix, and Path on Windows! + opam tries to ensure that environment variables are looked up according to + the OS semantics (so case insensitively on Windows) and OpamEnv goes to + some trouble to ensure that updates to environment variables are case + preserving (i.e. PATH+=foo gets transformed to Path+=foo if Path exists + in the environment block). + + Key to this is not accidentally treating environment variable names as + strings, without using the appropriate comparison functions. Name.t + represents environment variable names as private strings, providing + comparison operators to handle them, and still allowing the possibility + to coerce them to strings. + *) module Name : sig include ABSTRACT with type t = private string