Skip to content

Commit

Permalink
v3: Updates for meson-f2py support
Browse files Browse the repository at this point in the history
  • Loading branch information
mathomp4 committed Nov 11, 2024
1 parent 9f8f10d commit 73e7295
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 33 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- For F2PY3 code, set CMake Policy CMP0132 if Python is 3.12+ or higher

### Deprecated

## [3.53.1] - 2024-11-07
Expand Down
12 changes: 10 additions & 2 deletions python/f2py/FindF2PY.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,22 @@ find_program(F2PY_EXECUTABLE NAMES "f2py${Python_VERSION_MAJOR}.${Python_VERSION
if(F2PY_EXECUTABLE)
# extract the version string
execute_process(COMMAND "${F2PY_EXECUTABLE}" -v
OUTPUT_VARIABLE F2PY_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE)
OUTPUT_VARIABLE F2PY_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE)
if("${F2PY_VERSION_STRING}" MATCHES "^([0-9]+)(.([0-9+]))?(.([0-9+]))?$")
set(F2PY_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(F2PY_VERSION_MINOR "${CMAKE_MATCH_3}")
set(F2PY_VERSION_PATCH "${CMAKE_MATCH_5}")
endif()

# Testing has shown that f2py3 with Python 3.12+ needs to set
# a new CMake policy, CMP0132, because f2py3 uses Meson in the
# instead of distutils.
# See https://github.com/mesonbuild/meson/issues/13882
if (F2PY_VERSION_MAJOR GREATER_EQUAL 3 AND F2PY_VERSION_MINOR GREATER_EQUAL 12)
cmake_policy(SET CMP0132 NEW)
endif ()

# Get the compiler-id and map it to compiler vendor as used by f2py.
# Currently, we only check for GNU, but this can easily be extended.
# Cache the result, so that we only need to check once.
Expand Down
89 changes: 68 additions & 21 deletions python/f2py/UseF2Py.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,32 @@ macro (add_f2py_module _name)

#message(STATUS "${_name} F2PY_Fortran_FLAGS ${F2PY_Fortran_FLAGS}")

set(_fcompiler_opts "--fcompiler=${F2PY_FCOMPILER}")
list(APPEND _fcompiler_opts "--f77exec=${CMAKE_Fortran_COMPILER}" "--f77flags='${F2PY_Fortran_FLAGS}'")
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
list(APPEND _fcompiler_opts "--f90exec=${CMAKE_Fortran_COMPILER}" "--f90flags='${F2PY_Fortran_FLAGS}'")
endif(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
# NOTE: This style of calling f2py is only for distutils. If you are using
# Python 3.12, the backend is now meson and this will not work
# so we need to test the Python version and then call the correct
# f2py

if (Python_VERSION VERSION_GREATER_EQUAL "3.12")
set(F2PY_BACKEND "meson")
else ()
set(F2PY_BACKEND "distutils")
endif ()

#message(STATUS "Using F2PY_BACKEND: ${F2PY_BACKEND}")

if (F2PY_BACKEND STREQUAL "distutils")
set(_fcompiler_opts "--fcompiler=${F2PY_FCOMPILER}")
list(APPEND _fcompiler_opts "--f77exec=${CMAKE_Fortran_COMPILER}" "--f77flags='${F2PY_Fortran_FLAGS}'")
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
list(APPEND _fcompiler_opts "--f90exec=${CMAKE_Fortran_COMPILER}" "--f90flags='${F2PY_Fortran_FLAGS}'")
endif(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
else ()
set(_fcompiler_opts "")
list(APPEND _fcompiler_opts "--f77flags='${F2PY_Fortran_FLAGS}'")
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
list(APPEND _fcompiler_opts "--f90flags='${F2PY_Fortran_FLAGS}'")
endif(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
endif ()

# Make the source filenames absolute.
set(_abs_srcs)
Expand All @@ -87,6 +108,13 @@ macro (add_f2py_module _name)
list(APPEND _abs_srcs ${_abs_src})
endforeach(_src ${add_f2py_module_SOURCES})

# Let's also get all directories that the sources are in
set(_src_inc_dirs)
foreach(_src ${_abs_srcs})
get_filename_component(_dir ${_src} DIRECTORY)
list(APPEND _src_inc_dirs ${_dir})
endforeach(_src ${_abs_srcs})

# Get a list of the include directories.
# The f2py --include_paths option, used when generating a signature file,
# needs a colon-separated list. The f2py -I option, used when compiling
Expand All @@ -103,6 +131,12 @@ macro (add_f2py_module _name)
endforeach(_dir)
string(REPLACE ";" ":" _inc_paths "${_inc_dirs}")

# We also want to include the directory where the
# sources are located as well into _inc_opts
foreach(_dir ${_src_inc_dirs})
list(APPEND _inc_opts "-I${_dir}")
endforeach(_dir)

set(_libs_opts)
foreach(_lib ${add_f2py_module_LIBRARIES})
# MAT This is hacky, but so is this whole code
Expand Down Expand Up @@ -189,8 +223,8 @@ macro (add_f2py_module _name)
continue()
endif ()
endif ()

list(APPEND _lib_opts "-l${_lib}")

endforeach()

else()
Expand Down Expand Up @@ -227,25 +261,38 @@ macro (add_f2py_module _name)

# Define the command to generate the Fortran to Python interface module. The
# output will be a shared library that can be imported by python.
if ( "${add_f2py_module_SOURCES}" MATCHES "^[^;]*\\.pyf;" )
add_custom_command(OUTPUT "${_name}${F2PY_SUFFIX}"
COMMAND ${F2PY_EXECUTABLE} ${F2PY_QUIET} -m ${_name}
--build-dir "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}"
${_fcompiler_opts} ${_inc_opts} -c ${_abs_srcs} ${REDIRECT_TO_DEV_NULL}
DEPENDS ${add_f2py_module_SOURCES}
COMMENT "[F2PY] Building Fortran to Python interface module ${_name}")
else ( "${add_f2py_module_SOURCES}" MATCHES "^[^;]*\\.pyf;" )
# We also need to set FC in the environment to the fortran compiler
#message(STATUS "add_f2py_module_SOURCES: ${add_f2py_module_SOURCES}")
#message(STATUS "_inc_opts: ${_inc_opts}")
if ( F2PY_BACKEND STREQUAL "meson")
add_custom_command(OUTPUT "${_name}${F2PY_SUFFIX}"
COMMAND ${F2PY_EXECUTABLE} ${F2PY_QUIET} -m ${_name} -h ${_name}.pyf
--build-dir "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}"
--include-paths ${_inc_paths} --overwrite-signature ${_abs_srcs} ${REDIRECT_TO_DEV_NULL}
COMMAND ${F2PY_EXECUTABLE} ${F2PY_QUIET} -m ${_name}
COMMAND ${CMAKE_COMMAND} -E env "FC=${CMAKE_Fortran_COMPILER}"
${F2PY_EXECUTABLE} ${F2PY_QUIET} -m ${_name}
--build-dir "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}"
-c "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}/${_name}.pyf"
${_fcompiler_opts} ${_inc_opts} ${_lib_opts} ${_abs_srcs} ${_lib_opts} ${_only} ${REDIRECT_TO_DEV_NULL}
${_fcompiler_opts} ${_inc_opts} ${_lib_opts} -c ${_abs_srcs} ${REDIRECT_TO_DEV_NULL}
DEPENDS ${add_f2py_module_SOURCES}
COMMENT "[F2PY] Building Fortran to Python interface module ${_name}")
endif ( "${add_f2py_module_SOURCES}" MATCHES "^[^;]*\\.pyf;" )
else ()
if ( "${add_f2py_module_SOURCES}" MATCHES "^[^;]*\\.pyf;" )
add_custom_command(OUTPUT "${_name}${F2PY_SUFFIX}"
COMMAND ${F2PY_EXECUTABLE} ${F2PY_QUIET} -m ${_name}
--build-dir "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}"
${_fcompiler_opts} ${_inc_opts} -c ${_abs_srcs} ${REDIRECT_TO_DEV_NULL}
DEPENDS ${add_f2py_module_SOURCES}
COMMENT "[F2PY] Building Fortran to Python interface module ${_name}")
else ( "${add_f2py_module_SOURCES}" MATCHES "^[^;]*\\.pyf;" )
add_custom_command(OUTPUT "${_name}${F2PY_SUFFIX}"
COMMAND ${F2PY_EXECUTABLE} ${F2PY_QUIET} -m ${_name} -h ${_name}.pyf
--build-dir "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}"
--include-paths ${_inc_paths} --overwrite-signature ${_abs_srcs} ${REDIRECT_TO_DEV_NULL}
COMMAND ${F2PY_EXECUTABLE} ${F2PY_QUIET} -m ${_name}
--build-dir "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}"
-c "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}/${_name}.pyf"
${_fcompiler_opts} ${_inc_opts} ${_lib_opts} ${_abs_srcs} ${_lib_opts} ${_only} ${REDIRECT_TO_DEV_NULL}
DEPENDS ${add_f2py_module_SOURCES}
COMMENT "[F2PY] Building Fortran to Python interface module ${_name}")
endif ( "${add_f2py_module_SOURCES}" MATCHES "^[^;]*\\.pyf;" )
endif ()



Expand Down
20 changes: 14 additions & 6 deletions python/f2py3/FindF2PY3.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,30 @@

# Path to the f2py3 executable
find_program(F2PY3_EXECUTABLE NAMES "f2py${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}"
"f2py-${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}"
"f2py${Python3_VERSION_MAJOR}"
"f2py"
)
"f2py-${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}"
"f2py${Python3_VERSION_MAJOR}"
"f2py"
)

if(F2PY3_EXECUTABLE)
# extract the version string
execute_process(COMMAND "${F2PY3_EXECUTABLE}" -v
OUTPUT_VARIABLE F2PY3_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE)
OUTPUT_VARIABLE F2PY3_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE)
if("${F2PY3_VERSION_STRING}" MATCHES "^([0-9]+)(.([0-9+]))?(.([0-9+]))?$")
set(F2PY3_VERSION_MAJOR "${CMAKE_MATCH_1}")
set(F2PY3_VERSION_MINOR "${CMAKE_MATCH_3}")
set(F2PY3_VERSION_PATCH "${CMAKE_MATCH_5}")
endif()

# Testing has shown that f2py3 with Python 3.12+ needs to set
# a new CMake policy, CMP0132, because f2py3 uses Meson in the
# instead of distutils.
# See https://github.com/mesonbuild/meson/issues/13882
if (F2PY_VERSION_MAJOR GREATER_EQUAL 3 AND F2PY_VERSION_MINOR GREATER_EQUAL 12)
cmake_policy(SET CMP0132 NEW)
endif ()

# Get the compiler-id and map it to compiler vendor as used by f2py3.
# Currently, we only check for GNU, but this can easily be extended.
# Cache the result, so that we only need to check once.
Expand Down
8 changes: 4 additions & 4 deletions python/f2py3/UseF2Py3.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ macro (add_f2py3_module _name)
# # If you really want to pass in the flags used by the rest of the model #
# # this is how. But I don't think we want to do this #
# if (CMAKE_BUILD_TYPE MATCHES Release) #
# set(F2PY3_Fortran_FLAGS ${CMAKE_Fortran_FLAGS_RELEASE}) #
# set(F2PY3_Fortran_FLAGS ${CMAKE_Fortran_FLAGS_RELEASE}) #
# elseif(CMAKE_BUILD_TYPE MATCHES Debug) #
# set(F2PY3_Fortran_FLAGS ${CMAKE_Fortran_FLAGS_DEBUG}) #
# set(F2PY3_Fortran_FLAGS ${CMAKE_Fortran_FLAGS_DEBUG}) #
# endif() #
# separate_arguments(F2PY3_Fortran_FLAGS) #
# separate_arguments(F2PY3_Fortran_FLAGS) #
###########################################################################

if (${add_f2py3_module_USE_OPENMP})
Expand Down Expand Up @@ -245,7 +245,7 @@ macro (add_f2py3_module _name)
# it to allow for this. It's possible it's not correct, but it seem to
# let things run
if(${add_f2py3_module_DOUBLE_PRECISION})
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/.f2py3_f2cmap "{'real':{'':'double'},'integer':{'':'long'},'real*8':{'':'double'},'complex':{'':'complex_double'}}")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/.f2py3_f2cmap "{'real':{'':'double'},'integer':{'':'long'},'real*8':{'':'double'},'complex':{'':'complex_double'}}")
endif()

# Debugging f2py is a lot easier if you don't quiet it, but we do not
Expand Down

0 comments on commit 73e7295

Please sign in to comment.