Skip to content
Draft
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
76 changes: 76 additions & 0 deletions .github/workflows/static_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,62 @@ jobs:
repository: conda-forge/micromamba-feedstock
ref: dev
path: micromamba-feedstock
# Temporary: use shared resolvo-cpp until static builds are on conda-forge.
- name: Add resolvo-cpp host dependency to feedstock recipe
run: |
python <<'PY'
from pathlib import Path

path = Path("micromamba-feedstock/recipe/meta.yaml")
text = path.read_text()
dep = " - resolvo-cpp 0.3.0\n"
if "resolvo-cpp" not in text:
needle = " - simdjson-static >=3.3.0\n"
if needle not in text:
raise SystemExit(f"Could not find anchor {needle!r} in {path}")
path.write_text(text.replace(needle, needle + dep, 1))
PY
# Temporary: ship libresolvo_cpp in the micromamba package until resolvo-cpp is static on conda-forge.
- name: Patch feedstock build.sh for resolvo DSO
run: |
python <<'PY'
from pathlib import Path

path = Path("micromamba-feedstock/recipe/build.sh")
text = path.read_text()
if "libresolvo_cpp" in text:
print(f"{path} already copies libresolvo_cpp")
else:
needle = "cmake --install build/\n\n# remove everything related to"
block = """cmake --install build/

# Temporary: resolvo-cpp is only available as a shared library until static builds are
# published on conda-forge. Ship the DSO in $PREFIX/lib so @rpath/../lib resolves when
# micromamba is used outside a full conda env (e.g. CI artifact tests).
install -d "${PREFIX}/lib"
_resolvo_copied=0
for _resolvo_lib in \\
"${BUILD_PREFIX}/lib/libresolvo_cpp.dylib" \\
"${BUILD_PREFIX}/lib/libresolvo_cpp.so" \\
"${PREFIX}/lib/libresolvo_cpp.dylib" \\
"${PREFIX}/lib/libresolvo_cpp.so"; do
if [[ -f "${_resolvo_lib}" ]]; then
cp -f "${_resolvo_lib}" "${PREFIX}/lib/"
_resolvo_copied=1
break
fi
done
if [[ "${_resolvo_copied}" -eq 0 ]]; then
echo "libresolvo_cpp not found in BUILD_PREFIX or PREFIX" >&2
exit 1
fi

# remove everything related to"""
if needle not in text:
raise SystemExit(f"Could not find anchor in {path}")
path.write_text(text.replace(needle, block, 1))
print(f"Patched {path} to copy libresolvo_cpp into the package")
PY
- name: Disable output validation
if: ${{ matrix.platform == 'osx' }}
run: |
Expand Down Expand Up @@ -141,6 +197,25 @@ jobs:
"micromamba-feedstock/build_artifacts/${{ matrix.platform }}-${{ matrix.arch }}/"micromamba-*.tar.bz2 "pkg/"
mkdir -p "${{ github.workspace }}/artifacts"
cp pkg/bin/micromamba "${{ github.workspace }}/artifacts"
# Temporary: static micromamba links shared resolvo-cpp (@rpath/../lib) until
# resolvo-cpp static libraries are published on conda-forge. Copy the DSO for
# artifact tests (the conda package only declares it as a run dependency).
mkdir -p "${{ github.workspace }}/lib"
shopt -s nullglob
_resolvo_copied=0
for _resolvo_lib in \
pkg/lib/libresolvo_cpp.* \
"${MAMBA_ROOT_PREFIX}/envs/mambabuild/lib/libresolvo_cpp."* \
"${MAMBA_ROOT_PREFIX}"/pkgs/resolvo-cpp-*/lib/libresolvo_cpp.* \
micromamba-feedstock/build_artifacts/*/_h_env*/lib/libresolvo_cpp.*; do
cp "${_resolvo_lib}" "${{ github.workspace }}/lib/"
_resolvo_copied=1
break
done
if [[ "${_resolvo_copied}" -eq 0 ]]; then
echo "libresolvo_cpp shared library not found for artifact tests" >&2
exit 1
fi

- name: Test basic commands
if: ${{ matrix.arch != 'aarch64' && matrix.arch != 'ppc64le' }}
Expand Down Expand Up @@ -186,6 +261,7 @@ jobs:
cpp-expected
nlohmann_json
simdjson-static>=3.3.0
resolvo-cpp==0.3.0
spdlog>=1.16.0
fmt>=11.1.0
yaml-cpp-static>=0.8.0
Expand Down
39 changes: 39 additions & 0 deletions cmake/modules/CheckResolvoConditions.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Detect resolvo-cpp >= 0.3.0 builds that export ConditionId / ConditionalRequirement. win-64 0.3.0
# (h0a879f1_1) predates this API; linux-64 0.3.0 (hf9e0b3e_1) includes it. Temporary until
# conda-forge republishes a consistent resolvo-cpp 0.3.0 on all platforms.

set(LIBMAMBA_RESOLVO_HAS_CONDITIONS FALSE)

find_file(
_libmamba_resolvo_dep_header
NAMES resolvo/resolvo_dependency_provider.h
PATHS ${CMAKE_PREFIX_PATH}
PATH_SUFFIXES include Library/include
NO_DEFAULT_PATH
)
if(NOT _libmamba_resolvo_dep_header)
find_file(
_libmamba_resolvo_dep_header
NAMES resolvo/resolvo_dependency_provider.h
PATH_SUFFIXES include Library/include
)
endif()

if(_libmamba_resolvo_dep_header)
file(READ "${_libmamba_resolvo_dep_header}" _libmamba_resolvo_dep_header_content)
if(_libmamba_resolvo_dep_header_content MATCHES "using cbindgen_private::ConditionId;")
set(LIBMAMBA_RESOLVO_HAS_CONDITIONS TRUE)
endif()
endif()

if(LIBMAMBA_RESOLVO_HAS_CONDITIONS)
message(STATUS "resolvo-cpp: conditional requirements API available")
else()
message(
STATUS
"resolvo-cpp: legacy API without conditional requirements (temporary platform workaround)"
)
endif()

unset(_libmamba_resolvo_dep_header)
unset(_libmamba_resolvo_dep_header_content)
40 changes: 40 additions & 0 deletions cmake/modules/FixResolvoWindows.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Temporary workaround until resolvo-cpp static libraries are published on conda-forge. resolvo-cpp
# 0.3.0 on Windows installs Library/bin/resolvo_cpp.dll and Library/lib/resolvo_cpp.lib, but
# ResolvoConfig.cmake still references the 0.2.x layout (Library/lib/resolvo_cpp.dll and
# resolvo_cpp.dll.lib).

if(NOT WIN32 OR NOT TARGET resolvo_cpp-shared)
return()
endif()

if(DEFINED ENV{LIBRARY_PREFIX})
set(_resolvo_prefix "$ENV{LIBRARY_PREFIX}")
elseif(DEFINED ENV{CONDA_PREFIX})
set(_resolvo_prefix "$ENV{CONDA_PREFIX}/Library")
else()
get_target_property(_resolvo_implib resolvo_cpp-shared IMPORTED_IMPLIB)
if(_resolvo_implib)
get_filename_component(_resolvo_prefix "${_resolvo_implib}" DIRECTORY)
get_filename_component(_resolvo_prefix "${_resolvo_prefix}" DIRECTORY)
endif()
endif()

if(NOT _resolvo_prefix)
message(WARNING "Could not determine resolvo-cpp prefix for Windows import fix")
return()
endif()

set(_resolvo_dll "${_resolvo_prefix}/bin/resolvo_cpp.dll")
set(_resolvo_lib "${_resolvo_prefix}/lib/resolvo_cpp.lib")

if(EXISTS "${_resolvo_lib}" AND EXISTS "${_resolvo_dll}")
set_target_properties(
resolvo_cpp-shared
PROPERTIES IMPORTED_IMPLIB "${_resolvo_lib}" IMPORTED_LOCATION "${_resolvo_dll}"
)
message(STATUS "Adjusted Resolvo Windows import lib to ${_resolvo_lib}")
endif()

unset(_resolvo_prefix)
unset(_resolvo_dll)
unset(_resolvo_lib)
1 change: 1 addition & 0 deletions dev/environment-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies:
- libarchive>=3.8 lgpl_*
- libcurl >=7.86
- libsodium
- resolvo-cpp==0.3.0
- libsolv >=0.7.18
- libmsgpack-c
- nlohmann_json
Expand Down
1 change: 1 addition & 0 deletions dev/environment-micromamba-static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies:
- simdjson-static >=3.3.0
- spdlog >=1.16.0
- fmt >=11.1.0
- resolvo-cpp==0.3.0
- libsolv-static >=0.7.24
- yaml-cpp-static >=0.8.0
- reproc-static >=14.2.4.post0
Expand Down
1 change: 1 addition & 0 deletions dev/micromamba_windows_allowed_dlls.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ api-ms-win-crt-utility-l1-1-0.dll UCRT (ucrt) UCRT forwarder: utility routines (
MSVCP140.dll MSVC runtime (vc14_runtime) Microsoft C++ standard library runtime (/MD builds).
VCRUNTIME140.dll MSVC runtime (vc14_runtime) Microsoft C runtime helpers (exceptions, EH scaffolding).
VCRUNTIME140_1.dll MSVC runtime (vc14_runtime) Additional MSVC C++ exception-handling support on x64.
resolvo_cpp.dll resolvo-cpp (conda-forge) Temporary: shared resolvo C++ bindings until resolvo-cpp static libraries are published on conda-forge.
30 changes: 26 additions & 4 deletions libmamba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ set(
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/repo_info.cpp
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/solver.cpp
${LIBMAMBA_SOURCE_DIR}/solver/libsolv/unsolvable.cpp
# Solver resolvo implementation
${LIBMAMBA_SOURCE_DIR}/solver/resolvo/database.cpp
${LIBMAMBA_SOURCE_DIR}/solver/resolvo/solver.cpp
# Artifacts validation
${LIBMAMBA_SOURCE_DIR}/validation/errors.cpp
${LIBMAMBA_SOURCE_DIR}/validation/keys.cpp
Expand Down Expand Up @@ -355,12 +358,18 @@ set(
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/problems_graph.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/request.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/solution.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/database.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/database_utils.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/solver_factory.hpp
# Solver libsolv implementation
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/database.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/parameters.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/repo_info.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/solver.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/libsolv/unsolvable.hpp
# Solver resolvo implementation
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/resolvo/database.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/solver/resolvo/solver.hpp
# Artifacts validation
${LIBMAMBA_INCLUDE_DIR}/mamba/validation/errors.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/validation/keys.hpp
Expand Down Expand Up @@ -447,6 +456,9 @@ find_package(yaml-cpp CONFIG REQUIRED)
find_package(reproc CONFIG REQUIRED)
find_package(reproc++ CONFIG REQUIRED)
find_package(Libsolv MODULE REQUIRED)
find_package(Resolvo CONFIG REQUIRED)
include(FixResolvoWindows)
include(CheckResolvoConditions)
find_package(msgpack-c CONFIG REQUIRED)
add_subdirectory(ext/solv-cpp)

Expand Down Expand Up @@ -496,14 +508,15 @@ macro(libmamba_create_target target_name linkage output_name)

target_link_libraries(
${target_name}
PUBLIC fmt::fmt-header-only yaml-cpp::yaml-cpp ${MSGPACK_TARGET}
PUBLIC
fmt::fmt-header-only yaml-cpp::yaml-cpp ${MSGPACK_TARGET} simdjson::simdjson_static
PRIVATE
reproc
reproc++
simdjson::simdjson_static
solv::libsolv_static
solv::libsolvext_static
solv::cpp
Resolvo::Resolvo
)

if(UNIX)
Expand Down Expand Up @@ -675,19 +688,24 @@ macro(libmamba_create_target target_name linkage output_name)
target_link_libraries(
${target_name}
PUBLIC
${LIBSOLV_LIBRARIES} ${LIBSOLVEXT_LIBRARIES} yaml-cpp::yaml-cpp fmt::fmt msgpack-c
${LIBSOLV_LIBRARIES}
${LIBSOLVEXT_LIBRARIES}
yaml-cpp::yaml-cpp
fmt::fmt
msgpack-c
simdjson::simdjson
PRIVATE
${LibArchive_LIBRARIES}
${CURL_LIBRARIES}
${OPENSSL_LIBRARIES}
BZip2::BZip2
reproc
reproc++
simdjson::simdjson
zstd::libzstd_shared
solv::libsolv
solv::libsolvext
solv::cpp
Resolvo::Resolvo
)
# CMake 3.17 provides a LibArchive::LibArchive target that could be used instead of
# LIBRARIES/INCLUDE_DIRS
Expand Down Expand Up @@ -736,6 +754,10 @@ macro(libmamba_create_target target_name linkage output_name)
target_link_libraries(${target_name} PUBLIC Threads::Threads)
endif()

if(LIBMAMBA_RESOLVO_HAS_CONDITIONS)
target_compile_definitions(${target_name} PUBLIC LIBMAMBA_RESOLVO_HAS_CONDITIONS)
endif()

list(APPEND libmamba_targets ${target_name})
add_library(mamba::${target_name} ALIAS ${target_name})
endmacro()
Expand Down
1 change: 1 addition & 0 deletions libmamba/include/mamba/core/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ namespace mamba
// Configurable
bool mamba_repodata_parsing = true;
bool experimental_matchspec_parsing = false;
bool experimental_resolvo_solver = false;
bool debug = false;
bool use_uv = false;

Expand Down
62 changes: 62 additions & 0 deletions libmamba/include/mamba/solver/database.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) 2026, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifndef MAMBA_SOLVER_DATABASE_HPP
#define MAMBA_SOLVER_DATABASE_HPP

#include <string>
#include <variant>
#include <vector>

#include "mamba/fs/filesystem.hpp"
#include "mamba/specs/channel.hpp"
#include "mamba/specs/match_spec.hpp"
#include "mamba/specs/package_info.hpp"

namespace mamba::solver
{
class Database
{
public:

virtual ~Database() = default;

virtual void add_repo_from_repodata_json(
const fs::u8path& filename,
const std::string& repo_url,
const std::string& channel_id,
bool verify_artifacts = false
) = 0;

virtual void add_repo_from_packages(
const std::vector<specs::PackageInfo>& packages,
const std::string& repo_name,
bool pip_as_python_dependency = false
) = 0;

virtual void set_installed_repo(const std::string& repo_name) = 0;

virtual bool has_package(const specs::MatchSpec& spec) = 0;
};

namespace libsolv
{
class Database;
}

namespace resolvo
{
class Database;
}

using DatabaseVariant = std::variant<libsolv::Database, resolvo::Database>;

// Remove or comment out the inline database_has_package function if DatabaseVariant is not
// visible or causes errors inline auto database_has_package(DatabaseVariant& database, const
// specs::MatchSpec& spec) -> bool;
}

#endif // MAMBA_SOLVER_DATABASE_HPP
24 changes: 24 additions & 0 deletions libmamba/include/mamba/solver/database_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef MAMBA_SOLVER_DATABASE_UTILS_HPP
#define MAMBA_SOLVER_DATABASE_UTILS_HPP

#include <stdexcept>

#include "mamba/solver/database.hpp"

namespace mamba::solver
{
inline bool database_has_package(DatabaseVariant& database, const specs::MatchSpec& spec)
{
if (auto* libsolv_db = std::get_if<libsolv::Database>(&database))
{
return libsolv_db->has_package(spec);
}
else if (auto* resolvo_db = std::get_if<resolvo::Database>(&database))
{
return resolvo_db->has_package(spec);
}
throw std::runtime_error("Invalid database variant");
}
}

#endif // MAMBA_SOLVER_DATABASE_UTILS_HPP
Loading
Loading