Skip to content

Commit 5de3d43

Browse files
committed
maint: Modularize libmambapy
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
1 parent 4c24dde commit 5de3d43

File tree

11 files changed

+421
-25
lines changed

11 files changed

+421
-25
lines changed

libmambapy/CMakeLists.txt

Lines changed: 170 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,9 @@ include("../cmake/CompilerWarnings.cmake")
99

1010
project(libmambapy)
1111

12-
# Link to aggregated libmamba target (includes all components) For solver-only usage (e.g.,
13-
# conda-libmamba-solver), could link to: mamba::libmamba-common-dyn (or -static) and
14-
# mamba::libmamba-solver-dyn (or -static) instead of the full libmamba target
15-
if(NOT TARGET mamba::libmamba)
12+
# Find libmamba components
13+
if(NOT TARGET mamba::libmamba-common-dyn AND NOT TARGET mamba::libmamba-common-static)
1614
find_package(libmamba CONFIG REQUIRED)
17-
# Try to find component targets first, fall back to aggregated
18-
if(TARGET mamba::libmamba-common-dyn AND TARGET mamba::libmamba-solver-dyn)
19-
# For now, still use aggregated target for full functionality TODO: Create solver-only
20-
# bindings target for conda-libmamba-solver
21-
set(libmamba_target mamba::libmamba-dyn)
22-
elseif(TARGET mamba::libmamba-dyn)
23-
set(libmamba_target mamba::libmamba-dyn)
24-
else()
25-
set(libmamba_target mamba::libmamba)
26-
endif()
27-
else()
28-
set(libmamba_target mamba::libmamba)
2915
endif()
3016

3117
if(NOT TARGET mamba::libmamba-dyn-spdlog)
@@ -36,19 +22,90 @@ find_package(Python COMPONENTS Interpreter Development.Module)
3622
find_package(pybind11 REQUIRED)
3723
find_package(msgpack-c REQUIRED)
3824

25+
# Set variables for component CMakeLists.txt files
26+
set(LIBMAMBAPY_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bindings)
27+
set(LIBMAMBAPY_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
28+
29+
# Build component bindings
30+
# ========================
31+
# Build order: common → solver (mirrors libmamba component order)
32+
33+
# Include component CMakeLists.txt files
34+
add_subdirectory(common)
35+
add_subdirectory(solver)
36+
37+
# Determine linkage type from libmamba components
38+
if(TARGET mamba::libmamba-common-dyn)
39+
set(BUILD_SHARED_BINDINGS ON)
40+
set(BUILD_STATIC_BINDINGS OFF)
41+
elseif(TARGET mamba::libmamba-common-static)
42+
set(BUILD_SHARED_BINDINGS OFF)
43+
set(BUILD_STATIC_BINDINGS ON)
44+
else()
45+
message(FATAL_ERROR "Neither libmamba-common-dyn nor libmamba-common-static found")
46+
endif()
47+
48+
# Create component binding targets
49+
if(BUILD_SHARED_BINDINGS)
50+
libmambapy_common_create_target(libmambapy-common SHARED)
51+
libmambapy_solver_create_target(libmambapy-solver SHARED)
52+
endif()
53+
54+
if(BUILD_STATIC_BINDINGS)
55+
libmambapy_common_create_target(libmambapy-common-static STATIC)
56+
libmambapy_solver_create_target(libmambapy-solver-static STATIC)
57+
endif()
58+
59+
# Create aggregated bindings module for backward compatibility
60+
# ============================================================
61+
# This module includes legacy.cpp and re-exports component modules
62+
63+
# Determine which libmamba target to use for aggregated module
64+
if(BUILD_SHARED_BINDINGS)
65+
if(TARGET mamba::libmamba-dyn)
66+
set(libmamba_target mamba::libmamba-dyn)
67+
else()
68+
# Fall back to component targets
69+
set(
70+
libmamba_target
71+
mamba::libmamba-common-dyn
72+
mamba::libmamba-solver-dyn
73+
mamba::libmamba-network-dyn
74+
mamba::libmamba-archive-dyn
75+
)
76+
endif()
77+
else()
78+
if(TARGET mamba::libmamba-static)
79+
set(libmamba_target mamba::libmamba-static)
80+
else()
81+
# Fall back to component targets
82+
set(
83+
libmamba_target
84+
mamba::libmamba-common-static
85+
mamba::libmamba-solver-static
86+
mamba::libmamba-network-static
87+
mamba::libmamba-archive-static
88+
)
89+
endif()
90+
endif()
91+
92+
# Create aggregated bindings module for backward compatibility This module includes all bindings and
93+
# maintains the same API as before
3994
pybind11_add_module(
4095
bindings
4196
bindings/longpath.manifest
4297
# Entry point to all submodules
4398
bindings/bindings.cpp
4499
# All bindings used to live in a global module
45100
bindings/legacy.cpp
46-
# Submodules
101+
# Component bindings (included for backward compatibility) Note: Component modules are separate
102+
# optional modules
47103
bindings/utils.cpp
48104
bindings/specs.cpp
49105
bindings/solver.cpp
50106
bindings/solver_libsolv.cpp
51107
)
108+
52109
# TODO: remove when `SubdirData::cache_path()` is removed
53110
if(
54111
CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
@@ -68,6 +125,11 @@ mamba_target_add_compile_warnings(bindings WARNING_AS_ERROR ${MAMBA_WARNING_AS_E
68125
target_link_libraries(
69126
bindings PRIVATE pybind11::pybind11 ${libmamba_target} mamba::libmamba-dyn-spdlog msgpack-c
70127
)
128+
# Note: Component modules (libmambapy-common, libmambapy-solver) are separate Python extension
129+
# modules and cannot be linked to the aggregated bindings module. They are optional and can be
130+
# imported independently. The aggregated bindings module includes all source files for backward
131+
# compatibility.
132+
71133
target_compile_features(bindings PUBLIC cxx_std_20)
72134
set_target_properties(
73135
bindings
@@ -78,15 +140,32 @@ set_target_properties(
78140
)
79141

80142
# Installation
143+
# ============
81144

82145
if(SKBUILD)
146+
# Install all component modules and aggregated module
83147
install(TARGETS bindings DESTINATION libmambapy)
148+
if(BUILD_SHARED_BINDINGS)
149+
if(TARGET libmambapy-common)
150+
install(TARGETS libmambapy-common DESTINATION libmambapy)
151+
endif()
152+
if(TARGET libmambapy-solver)
153+
install(TARGETS libmambapy-solver DESTINATION libmambapy)
154+
endif()
155+
else()
156+
if(TARGET libmambapy-common-static)
157+
install(TARGETS libmambapy-common-static DESTINATION libmambapy)
158+
endif()
159+
if(TARGET libmambapy-solver-static)
160+
install(TARGETS libmambapy-solver-static DESTINATION libmambapy)
161+
endif()
162+
endif()
84163
else()
85164
# WARNING: this default should probably not be used for installation but only for local
86165
# development and testing. Proper installation should be controlled externally by a Python
87166
# packager tool
88167

89-
# Build bindings in a self-contain libmambapy/ folder inside the build tree
168+
# Build bindings in a self-contained libmambapy/ folder inside the build tree
90169
set_target_properties(
91170
bindings PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/libmambapy"
92171
)
@@ -107,16 +186,89 @@ else()
107186
)
108187
add_dependencies(bindings libmambapy_copy_files)
109188

189+
# Also copy component module directories (if they exist) These are included in the main
190+
# copy_directory command above, so no separate commands needed
191+
192+
# Set output directories for component modules to be in the same location as bindings
193+
if(BUILD_SHARED_BINDINGS)
194+
if(TARGET libmambapy-common)
195+
set_target_properties(
196+
libmambapy-common
197+
PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/libmambapy"
198+
)
199+
add_dependencies(libmambapy-common libmambapy_copy_files)
200+
endif()
201+
if(TARGET libmambapy-solver)
202+
set_target_properties(
203+
libmambapy-solver
204+
PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/libmambapy"
205+
)
206+
add_dependencies(libmambapy-solver libmambapy_copy_files)
207+
endif()
208+
else()
209+
if(TARGET libmambapy-common-static)
210+
set_target_properties(
211+
libmambapy-common-static
212+
PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/libmambapy"
213+
)
214+
add_dependencies(libmambapy-common-static libmambapy_copy_files)
215+
endif()
216+
if(TARGET libmambapy-solver-static)
217+
set_target_properties(
218+
libmambapy-solver-static
219+
PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/libmambapy"
220+
)
221+
add_dependencies(libmambapy-solver-static libmambapy_copy_files)
222+
endif()
223+
endif()
224+
110225
set(
111226
MAMBA_INSTALL_PYTHON_EXT_LIBDIR
112227
"lib"
113228
CACHE PATH "Installation directory for Python extension"
114229
)
115230

231+
# Install all targets
116232
install(
117233
TARGETS bindings
118234
EXCLUDE_FROM_ALL
119235
COMPONENT Mamba_Python_Extension
120236
DESTINATION ${MAMBA_INSTALL_PYTHON_EXT_LIBDIR}
121237
)
238+
239+
if(BUILD_SHARED_BINDINGS)
240+
if(TARGET libmambapy-common)
241+
install(
242+
TARGETS libmambapy-common
243+
EXCLUDE_FROM_ALL
244+
COMPONENT Mamba_Python_Extension
245+
DESTINATION ${MAMBA_INSTALL_PYTHON_EXT_LIBDIR}
246+
)
247+
endif()
248+
if(TARGET libmambapy-solver)
249+
install(
250+
TARGETS libmambapy-solver
251+
EXCLUDE_FROM_ALL
252+
COMPONENT Mamba_Python_Extension
253+
DESTINATION ${MAMBA_INSTALL_PYTHON_EXT_LIBDIR}
254+
)
255+
endif()
256+
else()
257+
if(TARGET libmambapy-common-static)
258+
install(
259+
TARGETS libmambapy-common-static
260+
EXCLUDE_FROM_ALL
261+
COMPONENT Mamba_Python_Extension
262+
DESTINATION ${MAMBA_INSTALL_PYTHON_EXT_LIBDIR}
263+
)
264+
endif()
265+
if(TARGET libmambapy-solver-static)
266+
install(
267+
TARGETS libmambapy-solver-static
268+
EXCLUDE_FROM_ALL
269+
COMPONENT Mamba_Python_Extension
270+
DESTINATION ${MAMBA_INSTALL_PYTHON_EXT_LIBDIR}
271+
)
272+
endif()
273+
endif()
122274
endif()

libmambapy/common/CMakeLists.txt

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Copyright (c) 2019, QuantStack and Mamba Contributors
2+
#
3+
# Distributed under the terms of the BSD 3-Clause License.
4+
#
5+
# The full license is in the file LICENSE, distributed with this software.
6+
7+
# Common component bindings - specs and utils These variables should be set by the parent
8+
# CMakeLists.txt
9+
if(NOT DEFINED LIBMAMBAPY_SOURCE_DIR)
10+
set(LIBMAMBAPY_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../bindings)
11+
endif()
12+
if(NOT DEFINED LIBMAMBAPY_BINARY_DIR)
13+
set(LIBMAMBAPY_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
14+
endif()
15+
16+
# Capture the directory containing this CMakeLists.txt file Use CMAKE_CURRENT_LIST_DIR which is set
17+
# when this file is processed
18+
set(
19+
LIBMAMBAPY_COMMON_DIR
20+
"${CMAKE_CURRENT_LIST_DIR}"
21+
CACHE INTERNAL "Directory containing common CMakeLists.txt"
22+
)
23+
24+
# Create the common bindings target
25+
macro(libmambapy_common_create_target target_name linkage)
26+
string(TOUPPER "${linkage}" linkage_upper)
27+
if(NOT ${linkage_upper} MATCHES "^(SHARED|STATIC)$")
28+
message(FATAL_ERROR "Invalid library linkage: ${linkage}")
29+
endif()
30+
31+
# Determine libmamba component target names
32+
if(${linkage_upper} STREQUAL "SHARED")
33+
set(common_target libmamba-common-dyn)
34+
else()
35+
set(common_target libmamba-common-static)
36+
endif()
37+
38+
# Create pybind11 module for common bindings This creates a separate Python extension module
39+
# (libmambapy_common) that can be imported independently. The aggregated bindings module will
40+
# also include these bindings for backward compatibility.
41+
pybind11_add_module(
42+
${target_name}
43+
${LIBMAMBAPY_COMMON_DIR}/bindings_common.cpp
44+
${LIBMAMBAPY_SOURCE_DIR}/specs.cpp
45+
${LIBMAMBAPY_SOURCE_DIR}/utils.cpp
46+
)
47+
48+
target_include_directories(
49+
${target_name} PRIVATE ${LIBMAMBAPY_SOURCE_DIR} ${LIBMAMBAPY_COMMON_DIR}/..
50+
)
51+
52+
mamba_target_add_compile_warnings(${target_name} WARNING_AS_ERROR ${MAMBA_WARNING_AS_ERROR})
53+
54+
# Link to libmamba-common component
55+
if(TARGET mamba::${common_target})
56+
target_link_libraries(${target_name} PRIVATE mamba::${common_target})
57+
else()
58+
message(FATAL_ERROR "libmamba-common must be built before libmambapy-common")
59+
endif()
60+
61+
target_link_libraries(${target_name} PRIVATE pybind11::pybind11)
62+
63+
target_compile_features(${target_name} PUBLIC cxx_std_20)
64+
set_target_properties(
65+
${target_name}
66+
PROPERTIES
67+
CXX_STANDARD 20
68+
CXX_STANDARD_REQUIRED YES
69+
CXX_EXTENSIONS NO
70+
)
71+
72+
# Output directory will be set by parent CMakeLists.txt
73+
74+
list(APPEND libmambapy_common_targets ${target_name})
75+
add_library(mamba::${target_name} ALIAS ${target_name})
76+
endmacro()
77+
78+
set(libmambapy_common_targets "")
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) 2019, QuantStack and Mamba Contributors
2+
//
3+
// Distributed under the terms of the BSD 3-Clause License.
4+
//
5+
// The full license is in the file LICENSE, distributed with this software.
6+
7+
#include "../bindings/bindings.hpp"
8+
9+
PYBIND11_MODULE(libmambapy_common, m)
10+
{
11+
// Create submodules matching the aggregated module structure
12+
mambapy::bind_submodule_utils(m.def_submodule("utils"));
13+
mambapy::bind_submodule_specs(m.def_submodule("specs"));
14+
}

0 commit comments

Comments
 (0)