Skip to content

Commit 37a00ad

Browse files
Rework CasADi libs detection (#61)
* Drop pybind11 submodule and update config * Update installation docs in README * Fix typo * Also set `PYBIND11_FINDPYTHON` * Oops, import from global dep * Turn `FINDPYTHON` to `OFF` * Set it back on, drop older `FindPython` mode * Revert "Set it back on, drop older `FindPython` mode" This reverts commit 37ebcd1. * Add pybind11 include dir * Pass pybind11's include dir * Rework CasADi libs detection * Lint * Update CMakeLists.txt Co-authored-by: Marc Berliner <[email protected]> * Update CMakeLists.txt Co-authored-by: Marc Berliner <[email protected]> --------- Co-authored-by: Marc Berliner <[email protected]>
1 parent 6e1ac4f commit 37a00ad

File tree

4 files changed

+89
-34
lines changed

4 files changed

+89
-34
lines changed

CMakeLists.txt

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ cmake_minimum_required(VERSION 3.13)
22
cmake_policy(SET CMP0074 NEW)
33
set(CMAKE_VERBOSE_MAKEFILE ON)
44

5-
if (DEFINED Python_EXECUTABLE)
6-
set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})
7-
endif ()
8-
95
if (DEFINED ENV{VCPKG_ROOT_DIR} AND NOT DEFINED VCPKG_ROOT_DIR)
106
set(VCPKG_ROOT_DIR "$ENV{VCPKG_ROOT_DIR}"
117
CACHE STRING "Vcpkg root directory")
@@ -95,35 +91,73 @@ if (NOT DEFINED USE_PYTHON_CASADI)
9591
set(USE_PYTHON_CASADI TRUE)
9692
endif ()
9793

94+
if (${USE_PYTHON_CASADI})
95+
execute_process(
96+
COMMAND "${PYTHON_EXECUTABLE}" -c
97+
"import os; import sysconfig; print(os.path.join(sysconfig.get_path('purelib'), 'casadi', 'cmake'))"
98+
OUTPUT_VARIABLE CASADI_DIR
99+
OUTPUT_STRIP_TRAILING_WHITESPACE)
98100

99-
execute_process(
100-
COMMAND "${PYTHON_EXECUTABLE}" -c
101-
"import os; import sysconfig; print(os.path.join(sysconfig.get_path('purelib'), 'casadi', 'cmake'))"
102-
OUTPUT_VARIABLE CASADI_DIR
103-
OUTPUT_STRIP_TRAILING_WHITESPACE)
104-
105-
if (CASADI_DIR)
106-
file(TO_CMAKE_PATH ${CASADI_DIR} CASADI_DIR)
107-
message("Found Python casadi path: ${CASADI_DIR}")
108-
else ()
109-
message(FATAL_ERROR "Did not find casadi path}")
110-
endif ()
101+
if (CASADI_DIR)
102+
file(TO_CMAKE_PATH ${CASADI_DIR} CASADI_DIR)
103+
message("Found Python casadi path: ${CASADI_DIR}")
104+
else ()
105+
message(FATAL_ERROR "Did not find casadi path")
106+
endif ()
111107

112-
if (${USE_PYTHON_CASADI})
113108
message("Trying to link against Python casadi package in ${CASADI_DIR}")
114-
find_package(casadi CONFIG PATHS ${CASADI_DIR} REQUIRED NO_DEFAULT_PATH)
109+
if (EXISTS "${CASADI_DIR}/casadiConfig.cmake" OR EXISTS "${CASADI_DIR}/casadi-config.cmake")
110+
find_package(casadi CONFIG PATHS ${CASADI_DIR} NO_DEFAULT_PATH)
111+
else ()
112+
message(WARNING "CasADi CMake config not found in ${CASADI_DIR}. Proceeding without find_package; using include and library paths discovered from the Python package.")
113+
endif ()
114+
115+
execute_process(
116+
COMMAND "${PYTHON_EXECUTABLE}" -c
117+
"import casadi; from pathlib import Path; print(Path(casadi.__file__).parent / 'include')"
118+
OUTPUT_VARIABLE CASADI_INCLUDE_DIR
119+
OUTPUT_STRIP_TRAILING_WHITESPACE)
120+
121+
if (CASADI_INCLUDE_DIR)
122+
file(TO_CMAKE_PATH ${CASADI_INCLUDE_DIR} CASADI_INCLUDE_DIR)
123+
message("Found Python CasADi include directory: ${CASADI_INCLUDE_DIR}")
124+
target_include_directories(idaklu PRIVATE ${CASADI_INCLUDE_DIR})
125+
else ()
126+
message(FATAL_ERROR "Could not find CasADi include directory")
127+
endif ()
128+
129+
execute_process(
130+
COMMAND "${PYTHON_EXECUTABLE}" -c
131+
"import casadi; from pathlib import Path; import glob; lib_dir = Path(casadi.__file__).parent; lib_files = list(lib_dir.glob('*casadi*')); print(str(lib_dir) if lib_files else '')"
132+
OUTPUT_VARIABLE CASADI_LIB_DIR
133+
OUTPUT_STRIP_TRAILING_WHITESPACE)
134+
135+
if (CASADI_LIB_DIR)
136+
file(TO_CMAKE_PATH ${CASADI_LIB_DIR} CASADI_LIB_DIR)
137+
message("Found Python CasADi library directory: ${CASADI_LIB_DIR}")
138+
target_link_directories(idaklu PRIVATE ${CASADI_LIB_DIR})
139+
140+
set_target_properties(
141+
idaklu PROPERTIES
142+
INSTALL_RPATH "${CASADI_LIB_DIR}"
143+
INSTALL_RPATH_USE_LINK_PATH TRUE
144+
)
145+
# Attempt to link the casadi library directly if found
146+
find_library(CASADI_LIBRARY NAMES casadi PATHS ${CASADI_LIB_DIR} NO_DEFAULT_PATH)
147+
if (CASADI_LIBRARY)
148+
message("Found CasADi library: ${CASADI_LIBRARY}")
149+
target_link_libraries(idaklu PRIVATE ${CASADI_LIBRARY})
150+
else ()
151+
message(WARNING "CasADi library not found in ${CASADI_LIB_DIR}. The target will rely on transitive linkage via CMake config if available.")
152+
endif ()
153+
else ()
154+
message(FATAL_ERROR "Could not find CasADi library directory")
155+
endif ()
115156
else ()
116157
message("Trying to link against any casadi package apart from the Python one")
117-
set(CMAKE_IGNORE_PATH "${CASADI_DIR}/cmake")
118158
find_package(casadi CONFIG REQUIRED)
119159
endif ()
120160

121-
set_target_properties(
122-
idaklu PROPERTIES
123-
INSTALL_RPATH "${CASADI_DIR}"
124-
INSTALL_RPATH_USE_LINK_PATH TRUE
125-
)
126-
127161
# openmp
128162
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
129163
execute_process(

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pip install .
4242
Linux installs may vary based on the distribution, however, the basic build can
4343
be performed with the following commands:
4444
```bash
45-
sudo apt-get install libopenblas-dev gcc make g++ build-essential
45+
sudo apt-get install libopenblas-dev gcc gfortran make g++ build-essential
4646
git submodules update --init --recursive
4747
pip install cmake casadi setuptools wheel "pybind11[global]"
4848
python install_KLU_Sundials.py

SuiteSparse

Submodule SuiteSparse updated 5983 files

setup.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
"" if system() == "Windows" else str(Path(__file__).parent.resolve() / ".idaklu")
1717
)
1818

19+
INCLUDE_DIRS = [str(Path(default_lib_dir) / "include"), pybind11.get_include()]
20+
21+
USE_PYTHON_CASADI = False if system() == "Windows" else True
22+
1923
# ---------- set environment variables for vcpkg on Windows ----------------------------
2024

2125

@@ -33,6 +37,23 @@ def set_vcpkg_environment_variables():
3337
)
3438

3539

40+
# ---------- find Python CasADi's include dirs (for Linux and macOS) -------------------
41+
42+
43+
def get_casadi_python_include_dir():
44+
import casadi
45+
46+
casadi_path = Path(casadi.__file__).parent
47+
include_dir = casadi_path / "include"
48+
assert include_dir.exists(), f"CasADi include directory not found at {include_dir}"
49+
return str(include_dir)
50+
51+
52+
if USE_PYTHON_CASADI:
53+
casadi_include = get_casadi_python_include_dir()
54+
INCLUDE_DIRS.append(casadi_include)
55+
print(f"Adding CasADi include directory: {casadi_include}")
56+
3657
# ---------- CMakeBuild class (custom build_ext for IDAKLU target) ---------------------
3758

3859

@@ -86,11 +107,6 @@ def run(self):
86107
# Build in parallel wherever possible
87108
os.environ["CMAKE_BUILD_PARALLEL_LEVEL"] = str(cpu_count())
88109

89-
if system() == "Windows":
90-
use_python_casadi = False
91-
else:
92-
use_python_casadi = True
93-
94110
build_type = os.getenv("PYBAMM_CPP_BUILD_TYPE", "Release")
95111
idaklu_expr_casadi = os.getenv("PYBAMM_IDAKLU_EXPR_CASADI", "ON")
96112

@@ -99,7 +115,7 @@ def run(self):
99115
cmake_args = [
100116
f"-DCMAKE_BUILD_TYPE={build_type}",
101117
f"-DPYTHON_EXECUTABLE={sys.executable}",
102-
"-DUSE_PYTHON_CASADI={}".format("TRUE" if use_python_casadi else "FALSE"),
118+
"-DUSE_PYTHON_CASADI={}".format("TRUE" if USE_PYTHON_CASADI else "FALSE"),
103119
f"-DPYBAMM_IDAKLU_EXPR_CASADI={idaklu_expr_casadi}",
104120
f"-Dpybind11_DIR={pybind11_cmake_dir}",
105121
]
@@ -110,6 +126,11 @@ def run(self):
110126
if self.sundials_root:
111127
cmake_args.append(f"-DSUNDIALS_ROOT={os.path.abspath(self.sundials_root)}")
112128

129+
if USE_PYTHON_CASADI:
130+
casadi_include = get_casadi_python_include_dir()
131+
cmake_args.append(f"-DCASADI_INCLUDE_DIR={casadi_include}")
132+
print(f"Adding CasADi include directory to CMake: {casadi_include}")
133+
113134
build_dir = self.get_build_directory()
114135
if not os.path.exists(build_dir):
115136
os.makedirs(build_dir)
@@ -272,7 +293,7 @@ def run(self):
272293
"src/pybammsolvers/idaklu_source/Options.cpp",
273294
"src/pybammsolvers/idaklu.cpp",
274295
],
275-
include_dirs=[str(Path(default_lib_dir) / "include"), pybind11.get_include()],
296+
include_dirs=INCLUDE_DIRS,
276297
)
277298
]
278299

0 commit comments

Comments
 (0)