Skip to content

Commit

Permalink
Turn to scikit-build-core
Browse files Browse the repository at this point in the history
Proof-of-concept to support Python 3.12
Supports parallel build
  • Loading branch information
jschueller committed May 15, 2024
1 parent 44af32d commit a62a218
Show file tree
Hide file tree
Showing 2 changed files with 237 additions and 0 deletions.
220 changes: 220 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
cmake_minimum_required (VERSION 3.17)
project (Assimulo LANGUAGES C)

option(ENABLE_FORTRAN "build Fortran modules" ON)
if (ENABLE_FORTRAN)
enable_language(Fortran)
endif ()

find_package (Python COMPONENTS Interpreter Development.Module NumPy REQUIRED)

find_package(LAPACK)

find_package (SUNDIALS CONFIG)
if (SUNDIALS_FOUND)
message(STATUS "Found SUNDIALS: ${SUNDIALS_DIR} (found version \"${SUNDIALS_VERSION}\")")
endif ()

set (cython_clones)

# copy /src tree into CMAKE_BINARY_DIR/assimulo
file (GLOB_RECURSE cython_sources src/*.pyx src/*.pxd src/*.py)
foreach (file ${cython_sources})
if (EXISTS ${file})
file (RELATIVE_PATH rel_file "${CMAKE_SOURCE_DIR}/src" "${file}")
get_filename_component (rel_path ${rel_file} PATH)
file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/assimulo/${rel_path})
set (cython_clone ${CMAKE_BINARY_DIR}/assimulo/${rel_file})
add_custom_command (OUTPUT ${cython_clone}
COMMENT "Copying ${file}"
COMMAND ${CMAKE_COMMAND} -E copy ${file} ${cython_clone}
DEPENDS ${file}
)
list (APPEND cython_clones ${cython_clone})
endif ()
endforeach ()

# copy /thirdparty tree into CMAKE_BINARY_DIR
file (GLOB_RECURSE cython_sources thirdparty/*.pyx thirdparty/*.pxd thirdparty/*.py)
foreach (file ${cython_sources})
if (EXISTS ${file})
file (RELATIVE_PATH rel_file "${CMAKE_SOURCE_DIR}/thirdparty" "${file}")
get_filename_component (rel_path ${rel_file} PATH)
file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/thirdparty/${rel_path})
set (cython_clone ${CMAKE_BINARY_DIR}/thirdparty/${rel_file})
add_custom_command (OUTPUT ${cython_clone}
COMMENT "Copying ${file}"
COMMAND ${CMAKE_COMMAND} -E copy ${file} ${cython_clone}
DEPENDS ${file}
)
list (APPEND cython_clones ${cython_clone})
endif ()
endforeach ()

macro(assimulo_add_cython_module pyx_file destination)
get_filename_component(name "${pyx_file}" NAME_WE)
get_filename_component(subdir "${pyx_file}" DIRECTORY)
add_custom_command(
OUTPUT ${name}.c
COMMENT "Making ${name}.c from ${name}.pyx"
COMMAND Python::Interpreter -m cython -o ${name}.c --3str --fast-fail
-I ${CMAKE_CURRENT_SOURCE_DIR}/src
-I ${CMAKE_CURRENT_SOURCE_DIR}/src/lib
${CMAKE_CURRENT_BINARY_DIR}/${pyx_file}
DEPENDS ${cython_clones} VERBATIM)

python_add_library(${name} MODULE ${name}.c WITH_SOABI)
target_include_directories(${name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/${subdir})
target_link_libraries(${name} PRIVATE Python::NumPy)
target_compile_definitions(${name} PRIVATE NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION)
install(TARGETS ${name} DESTINATION ${destination})
endmacro()

assimulo_add_cython_module(assimulo/explicit_ode.pyx assimulo)
target_sources(explicit_ode PRIVATE src/ode_event_locator.c assimulo)
assimulo_add_cython_module(assimulo/algebraic.pyx assimulo)
assimulo_add_cython_module(assimulo/implicit_ode.pyx assimulo)
assimulo_add_cython_module(assimulo/ode.pyx assimulo)
assimulo_add_cython_module(assimulo/problem.pyx assimulo)
assimulo_add_cython_module(assimulo/special_systems.pyx assimulo)
assimulo_add_cython_module(assimulo/support.pyx assimulo)
assimulo_add_cython_module(assimulo/solvers/euler.pyx assimulo/solvers)
#if (SUNDIALS_FOUND)
# assimulo_add_cython_module(solvers/sundials.pyx)
#endif ()
assimulo_add_cython_module(thirdparty/radau5/radau5ode.pyx assimulo/lib)
target_sources(radau5ode PRIVATE thirdparty/radau5/radau5.c thirdparty/radau5/radau5_io.c)
install(TARGETS radau5ode DESTINATION assimulo/lib)

if (ENABLE_FORTRAN)

find_program(F2PY_EXECUTABLE NAMES f2py REQUIRED)

if (NOT DEFINED F2PY_INCLUDE_DIR)
execute_process(COMMAND ${Python_EXECUTABLE} -c "from numpy import f2py; print(f2py.get_include())"
OUTPUT_VARIABLE F2PY_INCLUDE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
message(STATUS "Using f2py include dir: ${F2PY_INCLUDE_DIR}")

# object library with common f2py symbols
add_library(fortranobject OBJECT ${F2PY_INCLUDE_DIR}/fortranobject.c)
target_link_libraries(fortranobject PUBLIC Python::NumPy)
target_include_directories(fortranobject PUBLIC ${F2PY_INCLUDE_DIR})
set_target_properties(fortranobject PROPERTIES POSITION_INDEPENDENT_CODE TRUE)

macro(assimulo_add_fortran_module name pyf_file)
cmake_parse_arguments(FMOD "" "" "SOURCES" ${ARGN})
add_custom_command(
OUTPUT ${name}module.c
COMMENT "Making ${name}module.c, ${name}-f2pywrappers.f from ${pyf_file}"
COMMAND ${F2PY_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${pyf_file}
DEPENDS ${pyf_file} VERBATIM)

python_add_library(${name} MODULE ${FMOD_SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/${name}module.c
${CMAKE_CURRENT_BINARY_DIR}/${name}-f2pywrappers.f
WITH_SOABI)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${name}module.c ${CMAKE_CURRENT_BINARY_DIR}/${name}-f2pywrappers.f PROPERTIES GENERATED TRUE)

target_link_libraries(${name} PRIVATE fortranobject)
install(TARGETS ${name} DESTINATION assimulo/lib)
endmacro(assimulo_add_fortran_module)

assimulo_add_fortran_module(dopri5 thirdparty/hairer/dopri5.pyf
SOURCES thirdparty/hairer/dopri5.f)

assimulo_add_fortran_module(rodas thirdparty/hairer/rodas_decsol.pyf
SOURCES thirdparty/hairer/rodas_decsol.f)

assimulo_add_fortran_module(radau5 thirdparty/hairer/radau_decsol.pyf
SOURCES thirdparty/hairer/radau_decsol.f)
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
target_compile_options(radau5 PRIVATE $<$<COMPILE_LANGUAGE:Fortran>:-fallow-argument-mismatch>)
endif ()

assimulo_add_fortran_module(radar5 thirdparty/hairer/radar5.pyf
SOURCES
thirdparty/hairer/contr5.f90
thirdparty/hairer/radar5_int.f90
thirdparty/hairer/radar5.f90
thirdparty/hairer/dontr5.f90
thirdparty/hairer/decsol.f90
thirdparty/hairer/dc_decdel.f90)
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
target_compile_options(radar5 PRIVATE $<$<COMPILE_LANGUAGE:Fortran>:-fallow-argument-mismatch>)
endif ()

assimulo_add_fortran_module(odepack thirdparty/odepack/odepack.pyf
SOURCES
thirdparty/odepack/opkdmain.f
thirdparty/odepack/opkda1.f
thirdparty/odepack/opkda2.f
thirdparty/odepack/odepack_aux.f90)
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
target_compile_options(odepack PRIVATE $<$<COMPILE_LANGUAGE:Fortran>:-fallow-argument-mismatch>)
endif ()

assimulo_add_fortran_module(odassl thirdparty/odassl/odassl.pyf
SOURCES
thirdparty/odassl/odassl.f
thirdparty/odassl/odastp.f
thirdparty/odassl/odacor.f
thirdparty/odassl/odajac.f
thirdparty/odassl/d1mach.f
thirdparty/odassl/daxpy.f
thirdparty/odassl/ddanrm.f
thirdparty/odassl/ddatrp.f
thirdparty/odassl/ddot.f
thirdparty/odassl/ddwats.f
thirdparty/odassl/dgefa.f
thirdparty/odassl/dgesl.f
thirdparty/odassl/dscal.f
thirdparty/odassl/idamax.f
thirdparty/odassl/xerrwv.f)
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
target_compile_options(odassl PRIVATE $<$<COMPILE_LANGUAGE:Fortran>:-fdefault-double-8 -fdefault-real-8>)
endif ()

assimulo_add_fortran_module(dasp3dp thirdparty/dasp3/dasp3dp.pyf
SOURCES
thirdparty/dasp3/DASP3.f
thirdparty/dasp3/ANORM.f
thirdparty/dasp3/CTRACT.f
thirdparty/dasp3/DECOMP.f
thirdparty/dasp3/HMAX.f
thirdparty/dasp3/INIVAL.f
thirdparty/dasp3/JACEST.f
thirdparty/dasp3/PDERIV.f
thirdparty/dasp3/PREPOL.f
thirdparty/dasp3/SOLVE.f
thirdparty/dasp3/SPAPAT.f)

if (LAPACK_FOUND)
assimulo_add_fortran_module(glimda thirdparty/glimda/glimda_complete.pyf
SOURCES
thirdparty/glimda/glimda_complete.f)
if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
target_compile_options(glimda PRIVATE $<$<COMPILE_LANGUAGE:Fortran>:-fallow-argument-mismatch>)
endif ()
target_link_libraries(glimda PRIVATE ${LAPACK_LIBRARIES})
endif ()
endif ()

install(FILES src/__init__.py
src/exception.py
src/problem_algebraic.py
DESTINATION assimulo)
install(FILES src/lib/__init__.py
src/lib/radau_core.py
DESTINATION assimulo/lib)
install(FILES src/solvers/__init__.py
src/solvers/dasp3.py
src/solvers/glimda.py
src/solvers/odassl.py
src/solvers/odepack.py
src/solvers/radar5.py
src/solvers/radau5.py
src/solvers/rosenbrock.py
src/solvers/runge_kutta.py
DESTINATION assimulo/solvers)
17 changes: 17 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[project]
name = "assimulo"
version = "3.5.0"
dependencies = [
"scipy",
"cython",
]

[build-system]
requires = ["scikit-build-core"]
build-backend = "scikit_build_core.build"

[tool.scikit-build]
logging.level = "DEBUG"

[tool.scikit-build.cmake.define]
CMAKE_VERBOSE_MAKEFILE = "ON"

0 comments on commit a62a218

Please sign in to comment.