Skip to content

Commit

Permalink
Updated build for VMEC that works with numpy 2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mbkumar committed Oct 22, 2024
1 parent e6c82b9 commit 3c6d5d7
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 127 deletions.
3 changes: 3 additions & 0 deletions Sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,6 @@ get_target_property(VMEC_LINK_LIB vmec LINK_LIBRARIES)
message(STATUS "vmec linked libraries are ${VMEC_LINK_LIB}")
set(VMEC_LINK_LIB ${VMEC_LINK_LIB} PARENT_SCOPE)

install(TARGETS xvmec RUNTIME DESTINATION bin)
install(TARGETS vmec RUNTIME DESTINATION lib)

3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ requires = [
"scikit-build",
"cmake",
"ninja",
"numpy>=2.0.0; python_version > '3.8'",
"numpy<2.0.0; python_version <= '3.8'",
"numpy",
"f90wrap"
]
222 changes: 97 additions & 125 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
#cmake_minimum_required(VERSION 3.17)

#project(cylinder VERSION 1.0 LANGUAGES C CXX Fortran)
#list(APPEND CMAKE_MODULE_PATH "/home/mbkumar/anaconda3/envs/testv/lib/python3.8/site-packages/skbuild/resources/cmake")
#list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

#list(APPEND CMAKE_MODULE_PATH /u/bmedasan/.conda/envs/stlopt_v/lib/python3.8/site-packages/skbuild/resources/cmake)
find_package(PythonExtensions REQUIRED)
find_package(NumPy REQUIRED)
find_package(F2PY REQUIRED)
set(Python_FIND_STRATEGY LOCATION)
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module NumPy)
find_program(F2PY_EXECUTABLE NAMES f2py${PYTHON_VERSION_MAJOR} f2py)
find_package(F90Wrap REQUIRED)
#if(NOT APPLE)
# set(CMAKE_INSTALL_RPATH $ORIGIN)
#endif()
find_package(PythonExtensions REQUIRED)

execute_process(
COMMAND "${PYTHON_EXECUTABLE}"
-c "import numpy; print(numpy.get_include())"
OUTPUT_VARIABLE NumPy_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# F2PY headers
execute_process(
COMMAND "${PYTHON_EXECUTABLE}"
-c "import numpy.f2py; print(numpy.f2py.get_include())"
OUTPUT_VARIABLE F2PY_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "Python headers are at ${PYTHON_INCLUDE_DIRS}")
message(STATUS "NumPy headers are at ${NumPy_INCLUDE_DIRS}")
message(STATUS "F2PY headers are at ${F2PY_INCLUDE_DIRS}")

# Fortran preprocessing compiler
if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel)
set(FPP_COMPILER fpp)
set(FPP_COMPILER fpp)
set(FPP_COMPILE_FLAGS "")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL GNU)
set(FPP_COMPILER gfortran)
set(FPP_COMPILER gfortran)
set(FPP_COMPILE_FLAGS "-E -cpp")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL Cray)
set(FPP_COMPILER ftn)
set(FPP_COMPILER ftn)
set(FPP_COMPILE_FLAGS "-e Z")
endif()

Expand All @@ -37,38 +45,36 @@ function(preprocess_fortran outvar)
foreach(f ${ARGN})
# is it a Fortran file?
if(f MATCHES "\\.[Ff](9[05])?")
message(STATUS "Got fortran file: ${f}")
# construct output filename
if(NOT IS_ABSOLUTE "${f}")
get_filename_component(f "${f}" ABSOLUTE)
endif()
file(RELATIVE_PATH r "${CMAKE_CURRENT_SOURCE_DIR}" "${f}")
get_filename_component(e "${r}" EXT)
get_filename_component(n "${r}" NAME_WE)
get_filename_component(p "${r}" PATH)
set(of "${CMAKE_CURRENT_BINARY_DIR}/${n}_fpp${e}")
message(STATUS "Output name: ${of}")
# preprocess the thing
if (CMAKE_Fortran_COMPILER_ID STREQUAL Intel)
add_custom_command(OUTPUT "${of}"
#COMMAND ${FPP_EXE} ${incflags} "${defflags}" "${f}" "${of}"
#COMMAND ${CMAKE_Fortran_COMPILER} -E -cpp "${f}" -o "${of}"
COMMAND ${FPP_COMPILER} ${FPP_COMPILE_FLAGS} ${COMP_DEF_STR} "${f}" "${of}"
IMPLICIT_DEPENDS Fortran "${f}"
COMMENT "Preprocessing ${f}"
VERBATIM
)
else()
add_custom_command(OUTPUT "${of}"
COMMAND ${FPP_COMPILER} ${FPP_COMPILE_FLAGS} ${COMP_DEF_STR} "${f}" -o "${of}"
IMPLICIT_DEPENDS Fortran "${f}"
COMMENT "Preprocessing ${f}"
VERBATIM
)
endif()
list(APPEND srcs "${of}")
#else()
# list(APPEND srcs "${f}")
message(STATUS "Got fortran file: ${f}")
# construct output filename
if(NOT IS_ABSOLUTE "${f}")
get_filename_component(f "${f}" ABSOLUTE)
endif()
file(RELATIVE_PATH r "${CMAKE_CURRENT_SOURCE_DIR}" "${f}")
get_filename_component(e "${r}" EXT)
get_filename_component(n "${r}" NAME_WE)
get_filename_component(p "${r}" PATH)
set(of "${CMAKE_CURRENT_BINARY_DIR}/${n}_fpp${e}")
message(STATUS "Output name: ${of}")
# preprocess the thing
if (CMAKE_Fortran_COMPILER_ID STREQUAL Intel)
add_custom_command(OUTPUT "${of}"
#COMMAND ${FPP_EXE} ${incflags} "${defflags}" "${f}" "${of}"
#COMMAND ${CMAKE_Fortran_COMPILER} -E -cpp "${f}" -o "${of}"
COMMAND ${FPP_COMPILER} ${FPP_COMPILE_FLAGS} ${COMP_DEF_STR} "${f}" "${of}"
IMPLICIT_DEPENDS Fortran "${f}"
COMMENT "Preprocessing ${f}"
VERBATIM
)
else()
add_custom_command(OUTPUT "${of}"
COMMAND ${FPP_COMPILER} ${FPP_COMPILE_FLAGS} ${COMP_DEF_STR} "${f}" -o "${of}"
IMPLICIT_DEPENDS Fortran "${f}"
COMMENT "Preprocessing ${f}"
VERBATIM
)
endif()
list(APPEND srcs "${of}")
endif()
endforeach()
# return the (preprocessed) sources
Expand All @@ -85,46 +91,14 @@ message(STATUS "fortran_src_files is ${fortran_src_files}")
preprocess_fortran(fpp_files ${fortran_src_files})
message(STATUS "fpp_files is ${fpp_files}")

#add_library(cyl_lib SHARED ${fpp_files})

#function(f90wrap_outputs outvar)
# message(STATUS "process f90 files with f90wrap")
# set(srcs)
# foreach(f ${ARGN})
# # is it a Fortran file?
# if(f MATCHES "\\.[Ff](9[05])?")
# message(STATUS "Got fortran file: ${f}")
# # construct output filename
# if(NOT IS_ABSOLUTE "${f}")
# get_filename_component(f "${f}" ABSOLUTE)
# endif()
# file(RELATIVE_PATH r "${CMAKE_CURRENT_BINARY_DIR}" "${f}")
# get_filename_component(e "${r}" EXT)
# get_filename_component(n "${r}" NAME_WE)
# get_filename_component(p "${r}" PATH)
# set(of "${CMAKE_CURRENT_BINARY_DIR}/f90wrap_${n}${e}")
# message(STATUS "Output name: ${of}")

# list(APPEND srcs "${of}")
# #else()
# # list(APPEND srcs "${f}")
# endif()
# endforeach()
# # return the (preprocesysed) sources
# set(${outvar} "${srcs}" PARENT_SCOPE)
#endfunction()

#f90wrap_outputs(f90wrap_output_files ${fpp_files})
#f90wrap_outputs(f90wrap_output_files ${fortran_src_files})

# ----------------------------------------------------------------------------
# NOTE: There is no way to identify the f90wrap---.f90 files ahead of running f90wrap
# NOTE: The files produced have no one->one relation with the source files.
# NOTE: So giving the names of f90wrap_---.f90 files manually
#-----------------------------------------------------------------------------
set(f90wrap_output_files ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_toplevel.f90
${CMAKE_CURRENT_BINARY_DIR}/f90wrap_read_wout_mod.f90
${CMAKE_CURRENT_BINARY_DIR}/f90wrap_vmec_input.f90
${CMAKE_CURRENT_BINARY_DIR}/f90wrap_read_wout_mod.f90
${CMAKE_CURRENT_BINARY_DIR}/f90wrap_vmec_input.f90
)

set(kind_map_file ${CMAKE_CURRENT_SOURCE_DIR}/kind_map)
Expand All @@ -138,64 +112,62 @@ add_custom_command(OUTPUT ${python_mod_file} ${f90wrap_output_files}
COMMENT "Executing F90Wrap for" ${fortran_src_files}
VERBATIM
)
#execute_process(
# COMMAND ${F90Wrap_EXECUTABLE} -m ${python_mod_name} ${fortran_src_files} -k ${kind_map_file}
# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
#)
#FILE(GLOB f90wrap_output_files ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_*.f*)

add_custom_target("${python_mod_name}_pymod"
DEPENDS ${python_mod_file} ${f90wrap_output_files}
DEPENDS ${python_mod_file} ${f90wrap_output_files}
)

#file(GLOB f90wrap_output_files CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/f90wrap_*.f90")
set(f2py_module_name "_${python_mod_name}")
set(generated_module_file ${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_name}${PYTHON_EXTENSION_MODULE_SUFFIX})
set(generated_module_file ${CMAKE_BINARY_DIR}/build/lib/${f2py_module_name}${PYTHON_EXTENSION_MODULE_SUFFIX})
message(STATUS "Python exten suffix expansion: ${PYTHON_EXTENSION_MODULE_SUFFIX}")
message(STATUS "f90_wrap_output_files: " ${f90wrap_output_files})
message(STATUS "f2py_module_name: ${f2py_module_name}")
message(STATUS "generated_module_name: ${generated_module_file}")

#set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
#set(CMAKE_SKIP_BUILD_PATH FALSE)
#set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}")
#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
include_directories("${NumPy_INCLUDE_DIRS}" "${F2PY_INCLUDE_DIRS}" "${CMAKE_CURRENT_BINARY_DIR}")
add_custom_target(${f2py_module_name} ALL
#DEPENDS ${generated_module_file} ${python_mod_name} cyl_lib ${f90wrap_output_files}
add_custom_target(${f2py_module_name_ct} ALL
DEPENDS ${generated_module_file} vmec ${f90wrap_output_files}
)

set(f2py_module_c "${f2py_module_name}module.c")
add_custom_command(
OUTPUT ${generated_module_file}
COMMAND ${F2PY_EXECUTABLE}
-m ${f2py_module_name}
--build-dir ${CMAKE_CURRENT_BINARY_DIR}
--f90exec=${CMAKE_Fortran_COMPILER}
--f77exec=${CMAKE_Fortran_COMPILER}
-c
#${SCALAPACK_LIB} ${NETCDF_F} ${NETCDF_C}
${f90wrap_output_files}
-I${CMAKE_BINARY_DIR}/build/modules/vmec
--verbose
${CMAKE_BINARY_DIR}/build/lib/libvmec.a
${VMEC_LINK_LIB}
#IMPLICIT_DEPENDS Fortran ${f90wrap_output_files}
DEPENDS vmec ${f90wrap_output_files}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
#VERBATIM
COMMAND_EXPAND_LISTS
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_c}" # "${CMAKE_CURRENT_BINARY_DIR}/${f2py_f90_wrapper}"
COMMAND ${F2PY_EXECUTABLE}
-m "${f2py_module_name}"
--build-dir ${CMAKE_CURRENT_BINARY_DIR}
--lower # Important
"${f90wrap_output_files}"
DEPENDS ${fortran_src_files} ${f2py_module_name_ct} # Fortran source
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND_EXPAND_LISTS
)

python_extension_module(${generated_module_file})

install(FILES ${python_mod_file} ${generated_module_file} #${CMAKE_CURRENT_SOURCE_DIR}/__init__.py
DESTINATION python/vmec
add_library(${f2py_module_name} MODULE
"${f2py_module_name}module.c"
"${F2PY_INCLUDE_DIRS}/fortranobject.c"
${f90wrap_output_files}
# ${f2py_f90_wrapper}
)
install(TARGETS xvmec vmec)
# LIBRARY DESTINATION ${CMAKE_INSTALL_DIR}/.
# RUNTIME DESTINATION bin
#)
target_include_directories(${f2py_module_name} PUBLIC
${F2PY_INCLUDE_DIRS}
${NumPy_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}/build/modules/vmec)
target_link_libraries(${f2py_module_name} vmec)
set_target_properties(${f2py_module_name} PROPERTIES SUFFIX "${PYTHON_EXTENSION_MODULE_SUFFIX}")
set_target_properties(${f2py_module_name} PROPERTIES PREFIX "")

# Linker fixes
if (UNIX)
if (APPLE)
set_target_properties(${f2py_module_name} PROPERTIES
LINK_FLAGS '-Wl,-dylib,-undefined,dynamic_lookup')
else()
set_target_properties(${f2py_module_name} PROPERTIES
LINK_FLAGS '-Wl,--allow-shlib-undefined')
endif()
endif()

install(FILES ${python_mod_file} # ${generated_module_file} #${CMAKE_CURRENT_SOURCE_DIR}/__init__.py
DESTINATION python/vmec
)
install(TARGETS ${f2py_module_name} DESTINATION python/vmec)

0 comments on commit 3c6d5d7

Please sign in to comment.