Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions libmamba/include/mamba/core/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ namespace mamba

std::vector<std::string> pinned_packages = {};

// Keys are virtual package names without the `__` prefix (e.g. "cuda", "glibc").
// Names with a `__` prefix are also accepted and normalized on lookup.
// Environment variables `CONDA_OVERRIDE_<NAME>` take precedence over this map.
std::map<std::string, std::string> override_virtual_packages = {};

bool use_only_tar_bz2 = false;

bool repodata_use_zst = true;
Expand Down
24 changes: 19 additions & 5 deletions libmamba/include/mamba/core/virtual_packages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,31 @@
#ifndef MAMBA_CORE_VIRTUAL_PACKAGES_HPP
#define MAMBA_CORE_VIRTUAL_PACKAGES_HPP

#include <map>
#include <optional>
#include <string>
#include <string_view>
#include <vector>

#include "mamba/specs/package_info.hpp"

namespace mamba
{
class Context;

std::vector<specs::PackageInfo> get_virtual_packages(const std::string& platform);
std::vector<specs::PackageInfo> get_virtual_packages(
const std::string& platform,
const std::map<std::string, std::string>& override_virtual_packages = {}
);

namespace detail
{
std::string cuda_version();
/** Resolve a virtual-package override: `CONDA_OVERRIDE_<NAME>` then config map. */
[[nodiscard]] auto get_virtual_package_override(
std::string_view name,
const std::map<std::string, std::string>& overrides
) -> std::optional<std::string>;

std::string
cuda_version(const std::map<std::string, std::string>& override_virtual_packages = {});

auto make_virtual_package(
std::string name,
Expand All @@ -29,7 +40,10 @@ namespace mamba
std::string build_string = ""
) -> specs::PackageInfo;

std::vector<specs::PackageInfo> dist_packages(const std::string& platform);
std::vector<specs::PackageInfo> dist_packages(
const std::string& platform,
const std::map<std::string, std::string>& override_virtual_packages = {}
);
}
}

Expand Down
20 changes: 20 additions & 0 deletions libmamba/src/api/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,26 @@ namespace mamba


// Solver
insert(Configurable("override_virtual_packages", &m_context.override_virtual_packages)
.group("Solver")
.set_rc_configurable()
.description("Override values for virtual packages")
.long_description(unindent(R"(
A dictionary of virtual package overrides. Keys are virtual package names
without the leading `__` (e.g. `cuda`, `glibc`, `archspec`), though names
with `__` are also accepted. Values override the detected version (or the
build string for `archspec`).

Environment variables of the form `CONDA_OVERRIDE_<NAME>` take precedence
over this setting.

Example:
override_virtual_packages:
cuda: "12.8"
glibc: "2.17"
archspec: "x86_64_v3"
)")));

insert(Configurable("channel_priority", &m_context.channel_priority)
.group("Solver")
.set_rc_configurable()
Expand Down
2 changes: 1 addition & 1 deletion libmamba/src/api/info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ namespace mamba
items.push_back({ "populated config files", sources });

std::vector<std::string> virtual_pkgs;
for (auto pkg : get_virtual_packages(ctx.platform))
for (auto pkg : get_virtual_packages(ctx.platform, ctx.override_virtual_packages))
{
virtual_pkgs.push_back(util::concat(pkg.name, "=", pkg.version, "=", pkg.build_string));
}
Expand Down
5 changes: 4 additions & 1 deletion libmamba/src/core/package_database_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,10 @@ namespace mamba
"installed",
solver::libsolv::PipAsPythonDependency::No
);
database.add_virtual_packages(repo, get_virtual_packages(ctx.platform));
database.add_virtual_packages(
repo,
get_virtual_packages(ctx.platform, ctx.override_virtual_packages)
);
database.internalize_repo(repo);
database.set_installed_repo(repo);
return repo;
Expand Down
92 changes: 63 additions & 29 deletions libmamba/src/core/virtual_packages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,35 @@ namespace mamba
{
namespace detail
{
std::string glibc_version()
auto get_virtual_package_override(
std::string_view name,
const std::map<std::string, std::string>& overrides
) -> std::optional<std::string>
{
auto override_version = util::get_env("CONDA_OVERRIDE_GLIBC");
if (override_version)
// Environment variables take precedence over config (conda-compatible).
if (auto env_override = util::get_env("CONDA_OVERRIDE_" + util::to_upper(name)))
{
return override_version.value();
return env_override;
}

for (const auto& [key, value] : overrides)
{
const auto normalized = util::starts_with(key, "__")
? std::string_view(key).substr(2)
: std::string_view(key);
if (normalized == name)
{
return value;
}
}
return std::nullopt;
}

std::string glibc_version(const std::map<std::string, std::string>& overrides)
{
if (auto override_version = get_virtual_package_override("glibc", overrides))
{
return std::move(override_version).value();
}

if (!util::on_linux)
Expand All @@ -57,16 +80,14 @@ namespace mamba
return std::string(util::strip(version, "glibc "));
}

std::string cuda_version()
std::string cuda_version(const std::map<std::string, std::string>& overrides)
{
LOG_DEBUG << "Loading CUDA virtual package";

auto override_version = util::get_env("CONDA_OVERRIDE_CUDA");
if (override_version)
if (auto override_version = get_virtual_package_override("cuda", overrides))
{
LOG_DEBUG << "CUDA version set by `CONDA_OVERRIDE_CUDA`: "
<< override_version.value();
return override_version.value();
LOG_DEBUG << "CUDA version set by override: " << override_version.value();
return std::move(override_version).value();
}

std::string cuda_version;
Expand Down Expand Up @@ -305,12 +326,13 @@ namespace mamba
return "x86_64";
}

std::string get_archspec(const std::string& arch)
std::string
get_archspec(const std::string& arch, const std::map<std::string, std::string>& overrides)
{
auto override_version = util::get_env("CONDA_OVERRIDE_ARCHSPEC");
if (override_version)
// For archspec, the override applies to the build string (conda-compatible).
if (auto override_build = get_virtual_package_override("archspec", overrides))
{
return override_version.value();
return std::move(override_build).value();
}

if (arch == "64")
Expand All @@ -327,34 +349,41 @@ namespace mamba
}
}

[[nodiscard]] auto overridable_linux_version() -> tl::expected<std::string, util::OSError>
[[nodiscard]] auto
overridable_linux_version(const std::map<std::string, std::string>& overrides)
-> tl::expected<std::string, util::OSError>
{
if (auto override_version = util::get_env("CONDA_OVERRIDE_LINUX"))
if (auto override_version = get_virtual_package_override("linux", overrides))
{
return { std::move(override_version).value() };
}
return util::linux_version();
}

[[nodiscard]] auto overridable_osx_version() -> tl::expected<std::string, util::OSError>
[[nodiscard]] auto
overridable_osx_version(const std::map<std::string, std::string>& overrides)
-> tl::expected<std::string, util::OSError>
{
if (auto override_version = util::get_env("CONDA_OVERRIDE_OSX"))
if (auto override_version = get_virtual_package_override("osx", overrides))
{
return { std::move(override_version).value() };
}
return util::osx_version();
}

[[nodiscard]] auto overridable_windows_version() -> tl::expected<std::string, util::OSError>
[[nodiscard]] auto
overridable_windows_version(const std::map<std::string, std::string>& overrides)
-> tl::expected<std::string, util::OSError>
{
if (auto override_version = util::get_env("CONDA_OVERRIDE_WIN"))
if (auto override_version = get_virtual_package_override("win", overrides))
{
return { std::move(override_version).value() };
}
return util::windows_version();
}

std::vector<specs::PackageInfo> dist_packages(const std::string& platform)
std::vector<specs::PackageInfo>
dist_packages(const std::string& platform, const std::map<std::string, std::string>& overrides)
{
LOG_DEBUG << "Loading distribution virtual packages";

Expand All @@ -371,7 +400,7 @@ namespace mamba

if (os == "win")
{
auto result = overridable_windows_version();
auto result = overridable_windows_version(overrides);
if (result)
{
res.push_back(make_virtual_package("__win", platform, std::move(result).value()));
Expand All @@ -390,7 +419,7 @@ namespace mamba
{
res.push_back(make_virtual_package("__unix", platform));

auto result = overridable_linux_version();
auto result = overridable_linux_version(overrides);
if (result)
{
res.push_back(make_virtual_package("__linux", platform, std::move(result).value()));
Expand All @@ -404,7 +433,7 @@ namespace mamba
LOG_DEBUG << std::move(result).error().message;
}

std::string libc_ver = detail::glibc_version();
std::string libc_ver = detail::glibc_version(overrides);
if (!libc_ver.empty())
{
res.push_back(make_virtual_package("__glibc", platform, libc_ver));
Expand All @@ -419,7 +448,7 @@ namespace mamba
{
res.push_back(make_virtual_package("__unix", platform));

auto result = overridable_osx_version();
auto result = overridable_osx_version(overrides);
if (result)
{
res.push_back(make_virtual_package("__osx", platform, std::move(result).value()));
Expand Down Expand Up @@ -452,18 +481,23 @@ namespace mamba
res.push_back(make_virtual_package("__unix", platform));
}

res.push_back(make_virtual_package("__archspec", platform, "1", get_archspec(arch)));
res.push_back(
make_virtual_package("__archspec", platform, "1", get_archspec(arch, overrides))
);

return res;
}
}

std::vector<specs::PackageInfo> get_virtual_packages(const std::string& platform)
std::vector<specs::PackageInfo> get_virtual_packages(
const std::string& platform,
const std::map<std::string, std::string>& override_virtual_packages
)
{
LOG_DEBUG << "Loading virtual packages";
auto res = detail::dist_packages(platform);
auto res = detail::dist_packages(platform, override_virtual_packages);

auto cuda_ver = detail::cuda_version();
auto cuda_ver = detail::cuda_version(override_virtual_packages);
if (!cuda_ver.empty())
{
res.push_back(detail::make_virtual_package("__cuda", platform, cuda_ver));
Expand Down
17 changes: 17 additions & 0 deletions libmamba/tests/src/core/test_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,23 @@ namespace mamba
REQUIRE(config.dump() == "proxy_servers:\n http: foo\n https: bar");
}

TEST_CASE_METHOD(Configuration, "override_virtual_packages")
{
std::string rc = unindent(R"(
override_virtual_packages:
cuda: "13.1"
glibc: "2.15"
archspec: "x86_64_v4")");
load_test_config(rc);
auto& actual = config.at("override_virtual_packages")
.value<std::map<std::string, std::string>>();
std::map<std::string, std::string> expected = { { "cuda", "13.1" },
{ "glibc", "2.15" },
{ "archspec", "x86_64_v4" } };
REQUIRE(actual == expected);
REQUIRE(ctx.override_virtual_packages == expected);
}

TEST_CASE_METHOD(Configuration, "platform")
{
mambatests::ScopedContextChange context_change{ ctx };
Expand Down
Loading
Loading