diff --git a/FindF2PY.cmake b/FindF2PY.cmake new file mode 100644 index 00000000..588b460b --- /dev/null +++ b/FindF2PY.cmake @@ -0,0 +1,75 @@ +# MAT This code is based, loosely, on the FindF2PY.cmake file from scikit +#.rst: +# +# The purpose of the F2PY –Fortran to Python interface generator– project is to provide a +# connection between Python and Fortran languages. +# +# F2PY is a Python package (with a command line tool f2py and a module f2py2e) that facilitates +# creating/building Python C/API extension modules that make it possible to call Fortran 77/90/95 +# external subroutines and Fortran 90/95 module subroutines as well as C functions; to access Fortran +# 77 COMMON blocks and Fortran 90/95 module data, including allocatable arrays from Python. +# +# For more information on the F2PY project, see http://www.f2py.com/. +# +# The following variables are defined: +# +# :: +# +# F2PY_EXECUTABLE - absolute path to the F2PY executable +# +# :: +# +# F2PY_VERSION_STRING - the version of F2PY found +# F2PY_VERSION_MAJOR - the F2PY major version +# F2PY_VERSION_MINOR - the F2PY minor version +# F2PY_VERSION_PATCH - the F2PY patch version +# +# +# .. note:: +# +# By default, the module finds the F2PY program associated with the installed NumPy package. +# + +# Path to the f2py executable +find_package(Python COMPONENTS Interpreter) + +find_program(F2PY_EXECUTABLE NAMES "f2py${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}" + "f2py-${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}" + "f2py${Python_VERSION_MAJOR}" + "f2py" + ) + +if(F2PY_EXECUTABLE) + # extract the version string + execute_process(COMMAND "${F2PY_EXECUTABLE}" -v + 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() + + # Now we need to test if we can actually use f2py and what its suffix is + + include(try_f2py_compile) + try_f2py_compile( + ${CMAKE_CURRENT_LIST_DIR}/check_compiler_support/test.F90 + DETECT_F2PY_SUFFIX + ) + +endif () + +# handle the QUIET and REQUIRED arguments and set F2PY_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(F2PY + REQUIRED_VARS F2PY_EXECUTABLE F2PY_SUFFIX + VERSION_VAR F2PY_VERSION_STRING + ) + +mark_as_advanced(F2PY_EXECUTABLE F2PY_SUFFIX) + +if (F2PY_FOUND) + include(UseF2Py) +endif () diff --git a/UseF2Py.cmake b/UseF2Py.cmake index 8cfa4cee..fa3570c5 100644 --- a/UseF2Py.cmake +++ b/UseF2Py.cmake @@ -19,29 +19,6 @@ # | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | # +-----------------------------------------------------------------------------+ -find_package(PythonInterp REQUIRED) - -if (NOT F2PY_SUFFIX) - execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX') or sysconfig.get_config_var('SO'))" - OUTPUT_VARIABLE PYTHON_EXT_SUFFIX - RESULT_VARIABLE FOUND_PYTHON_EXT_SUFFIX - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT FOUND_PYTHON_EXT_SUFFIX EQUAL 0) - set (F2PY_SUFFIX "" CACHE STRING "Suffix added by F2Py to the module name to get the output file name." ) - message(FATAL_ERROR "Unable to determine file extension of compiled Python modules - specify it with F2PY_SUFFIX") - endif (NOT FOUND_PYTHON_EXT_SUFFIX EQUAL 0) - - set (F2PY_SUFFIX "${PYTHON_EXT_SUFFIX}" CACHE INTERNAL "f2py suffix") - message(STATUS "Setting F2PY_SUFFIX to ${F2PY_SUFFIX}") -endif (NOT F2PY_SUFFIX) - -## Path to the f2py executable -find_program(F2PY_EXECUTABLE NAMES "f2py${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" - "f2py-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" - "f2py${PYTHON_VERSION_MAJOR}" - "f2py" - REQUIRED) - ## ----------------------------------------------------------------------------- ## Macro to generate a Python interface module from one or more Fortran sources ## @@ -153,18 +130,18 @@ macro (add_f2py_module _name) add_custom_command(OUTPUT "${_name}${F2PY_SUFFIX}" COMMAND ${F2PY_EXECUTABLE} --quiet -m ${_name} --build-dir "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}" - ${_fcompiler_opts} ${_inc_opts} -c ${_abs_srcs} + ${_fcompiler_opts} ${_inc_opts} -c ${_abs_srcs} &> /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} --quiet -m ${_name} -h ${_name}.pyf --build-dir "${CMAKE_CURRENT_BINARY_DIR}/f2py-${_name}" - --include-paths ${_inc_paths} --overwrite-signature ${_abs_srcs} + --include-paths ${_inc_paths} --overwrite-signature ${_abs_srcs} &> /dev/null COMMAND ${F2PY_EXECUTABLE} --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} + ${_fcompiler_opts} ${_inc_opts} ${_lib_opts} ${_abs_srcs} ${_lib_opts} &> /dev/null DEPENDS ${add_f2py_module_SOURCES} COMMENT "[F2PY] Building Fortran to Python interface module ${_name}") endif ( "${add_f2py_module_SOURCES}" MATCHES "^[^;]*\\.pyf;" ) diff --git a/check_compiler_support/test.F90 b/check_compiler_support/test.F90 new file mode 100644 index 00000000..3f06e44f --- /dev/null +++ b/check_compiler_support/test.F90 @@ -0,0 +1,3 @@ +subroutine test + real x +end subroutine test diff --git a/check_compiler_support/try_f2py_compile.cmake b/check_compiler_support/try_f2py_compile.cmake new file mode 100644 index 00000000..6ef41773 --- /dev/null +++ b/check_compiler_support/try_f2py_compile.cmake @@ -0,0 +1,39 @@ +# Used to determine whether compiler is able to compile and/or run a +# given snippet of source. Useful for compiler bug workarounds and +# unsupported features. + +macro (try_f2py_compile file var) + + if (NOT CMAKE_REQUIRED_QUIET) + message (STATUS "Performing Test ${var}") + endif () + + set( _f2py_check_bindir "${CMAKE_BINARY_DIR}/f2py_tmp") + file(MAKE_DIRECTORY ${_f2py_check_bindir}) + + execute_process( + COMMAND ${F2PY_EXECUTABLE} -m test_ -c ${file} + WORKING_DIRECTORY ${_f2py_check_bindir} + RESULT_VARIABLE result + OUTPUT_QUIET + ERROR_QUIET + ) + + if (result EQUAL 0) + file(GLOB F2PY_TEST_OUTPUT_FILE ${_f2py_check_bindir}/*.so) + + get_filename_component(F2PY_FOUND_EXTENSION ${F2PY_TEST_OUTPUT_FILE} EXT) + + set(F2PY_SUFFIX ${F2PY_FOUND_EXTENSION} CACHE STRING "f2py suffix") + message(STATUS "Setting F2PY_SUFFIX to ${F2PY_SUFFIX}") + if (NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${var}: SUCCESS") + endif () + else () + if (NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${var}: FAILURE") + endif () + message(WARNING "Test f2py compile using ${F2PY_EXECUTABLE} failed. F2PY modules will not be built. This usually indicates an incomplete Python/numpy installation.") + endif () + +endmacro (try_f2py_compile) diff --git a/esma.cmake b/esma.cmake index 66546d71..5ee96eeb 100644 --- a/esma.cmake +++ b/esma.cmake @@ -27,10 +27,20 @@ include (esma_generate_automatic_code) include (esma_create_stub_component) include (esma_fortran_generator_list) +find_package(ImageMagick) +if (NOT ImageMagick_FOUND) + message(STATUS "NOTE: ImageMagick was not found. This will prevent using LaTeX and some postprocessing utilities from running, but does not affect the build") +endif () + find_package(LATEX) -# These are all the bits of LaTeX that UseLatex needs. As it's confusing how LATEX_FOUND from -# find_package(LATEX) is set, we test all the bits that UseLatex requires -if (LATEX_FOUND AND LATEX_PDFLATEX_FOUND AND LATEX_BIBTEX_FOUND AND LATEX_MAKEINDEX_FOUND) +# These are all the bits of LaTeX that UseLatex needs. As it's confusing +# how LATEX_FOUND from find_package(LATEX) is set, we test all the bits +# that UseLatex requires +# +# Also, UseLatex assumes ImageMagick is installed. While this is always +# nice (and technically required to generate plots with GEOS plotting +# utilities, it's not necessary to *build* +if (LATEX_FOUND AND LATEX_PDFLATEX_FOUND AND LATEX_BIBTEX_FOUND AND LATEX_MAKEINDEX_FOUND AND ImageMagick_FOUND) # If they are all found, set LATEX_FOUND to TRUE... set (LATEX_FOUND TRUE) @@ -94,3 +104,5 @@ macro (esma) endmacro () find_package(GitInfo) + +find_package(F2PY)