-
Notifications
You must be signed in to change notification settings - Fork 8
Move to toml 3 #230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
smiet
wants to merge
8
commits into
master
Choose a base branch
from
move_to_toml_3
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Move to toml 3 #230
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
ea4e518
attempt to update make for newer python
smiet 89841b1
revert little change
smiet 63bdb55
use only wrapper-generated files
smiet 5a9ca6e
merge master
smiet cb07452
Merge remote-tracking branch 'origin/master' into move_to_toml_3
smiet 9deab7c
fix build with toml and proper f90wrap intermediate file handling
smiet 553979f
fix strings that modern compilation linking caused to fail
smiet 75f74a4
two more bad strings
smiet File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,152 +1,198 @@ | ||
| list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) | ||
| find_package(PythonExtensions REQUIRED) | ||
| find_package(NumPy REQUIRED) | ||
| find_package(F2PY REQUIRED) | ||
| find_package(F90Wrap REQUIRED) | ||
|
|
||
| # Fortran preprocessing compiler | ||
| if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) | ||
| set(FPP_COMPILER fpp) | ||
| set(FPP_COMPILE_FLAGS "") | ||
| # ============================================================================= | ||
| # Python wrapper for SPEC using f90wrap and f2py | ||
| # ============================================================================= | ||
|
|
||
| # Load Python and various components | ||
| find_package(Python 3.10 REQUIRED | ||
| COMPONENTS Interpreter Development.Module NumPy | ||
| ) | ||
|
|
||
| # Get the path of the `f2py` include directory that will be needed for the library compilation | ||
| execute_process( | ||
| COMMAND "${Python_EXECUTABLE}" -c "import numpy.f2py; print(numpy.f2py.get_include())" | ||
| OUTPUT_VARIABLE F2PY_INCLUDE_DIR | ||
| OUTPUT_STRIP_TRAILING_WHITESPACE | ||
| ) | ||
| message(STATUS "f2py include dir: ${F2PY_INCLUDE_DIR}") | ||
|
|
||
| # Create the list of Fortran files to include in the Python module | ||
| # These come from src/CMakeLists.txt via fortran_src_files variable | ||
| set(spec4py_f90_src_files ${fortran_src_files}) | ||
| message(STATUS "Fortran source files for Python wrapper: ${spec4py_f90_src_files}") | ||
|
|
||
| # ============================================================================= | ||
| # Step 1: Preprocess Fortran files using the Fortran compiler preprocessor | ||
| # ============================================================================= | ||
|
|
||
| # Set preprocessor flags for each compiler | ||
| if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") | ||
| set(PP_FLAG "-cpp") | ||
| set(PP_ONLY_FLAG "-E") | ||
| elseif(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") | ||
| set(PP_FLAG "-fpp") | ||
| set(PP_ONLY_FLAG "-E") | ||
| elseif(CMAKE_Fortran_COMPILER_ID MATCHES "NVHPC|PGI") | ||
| set(PP_FLAG "-Mpreprocess") | ||
| set(PP_ONLY_FLAG "-E") | ||
| else() | ||
| set(FPP_COMPILER ${CMAKE_Fortran_COMPILER}) | ||
| set(FPP_COMPILE_FLAGS -E -cpp) | ||
| message(WARNING "Unknown Fortran compiler: preprocessing may not work") | ||
| set(PP_FLAG "-cpp") | ||
| set(PP_ONLY_FLAG "-E") | ||
| endif() | ||
|
|
||
| get_directory_property(COMP_DEFS COMPILE_DEFINITIONS) | ||
| message(STATUS "Compile definitions for preprocessor are ${COMP_DEFS}") | ||
| string(REPLACE ";" " " COMP_DEF_STR "${COMPILE_DEFINITIONS}") | ||
|
|
||
|
|
||
| function(preprocess_fortran outvar) | ||
| message(STATUS "preprocess_fortran arguments: ${outvar}, followed by ${ARGN}") | ||
| 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_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_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}") | ||
| endif() | ||
| endforeach() | ||
| # return the (preprocessed) sources | ||
| set(${outvar} "${srcs}" PARENT_SCOPE) | ||
| endfunction() | ||
|
|
||
| #message(STATUS "fortran_src_files is ${fortran_src_files}") | ||
| preprocess_fortran(fpp_files ${fortran_src_files}) | ||
| #message(STATUS "fpp_files is ${fpp_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_global_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_inputlist_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_intghs_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_msphdf5_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_newton_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_toplevel.f90 | ||
| ) | ||
|
|
||
| set(kind_map_file ${CMAKE_CURRENT_SOURCE_DIR}/kind_map) | ||
| set(python_mod_name spec_f90wrapped) | ||
| set(python_mod_file ${CMAKE_CURRENT_BINARY_DIR}/${python_mod_name}.py) | ||
|
|
||
| add_custom_target(preprocessing ALL | ||
| DEPENDS ${fpp_files} | ||
| ) | ||
|
|
||
| add_custom_command(OUTPUT ${python_mod_file} ${f90wrap_output_files} | ||
| COMMAND "${F90Wrap_EXECUTABLE}" -m "${python_mod_name}" ${fpp_files} -k "${kind_map_file}" | ||
| #IMPLICIT_DEPENDS Fortran ${fpp_files} | ||
| DEPENDS ${fpp_files} ${kind_map_file} | ||
| COMMENT "Executing F90Wrap for" ${fpp_files} | ||
| VERBATIM | ||
| # Preprocess each Fortran source file | ||
| foreach(src_file ${spec4py_f90_src_files}) | ||
| get_filename_component(basename "${src_file}" NAME_WE) | ||
| set(pp_file "${CMAKE_CURRENT_BINARY_DIR}/${basename}_fpp.F90") | ||
| list(APPEND spec4py_f90_pp_files "${pp_file}") | ||
| add_custom_command( | ||
| COMMAND ${CMAKE_Fortran_COMPILER} ${PP_FLAG} ${PP_ONLY_FLAG} ${src_file} | ||
| -o ${pp_file} | ||
| DEPENDS ${src_file} | ||
| OUTPUT ${pp_file} | ||
| COMMENT "Preprocess ${src_file} -> ${basename}_fpp.F90" | ||
| ) | ||
| endforeach() | ||
|
|
||
| message(STATUS "Preprocessed files: ${spec4py_f90_pp_files}") | ||
|
|
||
| # ============================================================================= | ||
| # Step 2: Run f90wrap to generate Fortran wrapper files | ||
| # ============================================================================= | ||
|
|
||
| # f90wrap generates wrapper files only for modules that have wrappable content. | ||
| # These are the known output files based on the SPEC source structure. | ||
| # f90wrap_toplevel.f90 contains the standalone subroutines. | ||
| set(f90wrap_output_files | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_global_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_inputlist_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_intghs_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_msphdf5_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_newton_m_fpp.f90 | ||
| ${CMAKE_CURRENT_BINARY_DIR}/f90wrap_toplevel.f90 | ||
| ) | ||
|
|
||
| #add_custom_target("${python_mod_name}_pymod" | ||
| # DEPENDS ${python_mod_file} ${f90wrap_output_files} | ||
| #) | ||
| # The module name must be "spec_f90wrapped" to be compatible with simsopt | ||
| # which imports "spec.spec_f90wrapped" | ||
| set(f90wrap_module_name "spec_f90wrapped") | ||
| set(f90wrap_python_file "${CMAKE_CURRENT_BINARY_DIR}/${f90wrap_module_name}.py") | ||
|
|
||
| set(f2py_module_name "_${python_mod_name}") | ||
| set(generated_module_file ${CMAKE_CURRENT_BINARY_DIR}/${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}") | ||
| add_custom_command( | ||
| COMMAND "${Python_EXECUTABLE}" | ||
| -m f90wrap | ||
| ${spec4py_f90_pp_files} | ||
| --mod-name "${f90wrap_module_name}" | ||
| --kind-map "${CMAKE_CURRENT_SOURCE_DIR}/kind_map" | ||
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} | ||
| DEPENDS ${spec4py_f90_pp_files} | ||
| OUTPUT ${f90wrap_output_files} ${f90wrap_python_file} | ||
| COMMENT "Generate Fortran interfaces using f90wrap" | ||
| VERBATIM | ||
| ) | ||
|
|
||
| include_directories("${NumPy_INCLUDE_DIRS}" "${F2PY_INCLUDE_DIRS}" "${CMAKE_CURRENT_BINARY_DIR}") | ||
| add_custom_target(${f2py_module_name} ALL | ||
| DEPENDS ${generated_module_file} spec ${f90wrap_output_files} | ||
| add_custom_target( | ||
| f90wrap_SPEC | ||
| DEPENDS ${f90wrap_output_files} ${f90wrap_python_file} | ||
| ) | ||
|
|
||
| # ============================================================================= | ||
| # Step 3: Run f2py-f90wrap to generate C interface code | ||
| # ============================================================================= | ||
|
|
||
| set(f2py_module_name "_${f90wrap_module_name}") | ||
| set(f2py_c_file "${CMAKE_CURRENT_BINARY_DIR}/${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} | ||
| --f90flags="-fopenmp" | ||
| -lgomp | ||
| -c | ||
| #${SCALAPACK_LIB} ${NETCDF_F} ${NETCDF_C} | ||
| ${f90wrap_output_files} | ||
| -I${CMAKE_BINARY_DIR}/build/modules/spec_modules | ||
| -I${HDF5_Fortran_INCLUDE_DIRS} | ||
| --verbose | ||
| ${CMAKE_BINARY_DIR}/build/lib/libspec.a | ||
| ${SPEC_LINK_LIB} | ||
| #IMPLICIT_DEPENDS Fortran ${f90wrap_output_files} | ||
| DEPENDS spec ${f90wrap_output_files} | ||
| COMMAND f2py-f90wrap | ||
| -m "${f2py_module_name}" | ||
| --lower | ||
| ${f90wrap_output_files} | ||
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} | ||
| #VERBATIM | ||
| COMMAND_EXPAND_LISTS | ||
| DEPENDS ${f90wrap_output_files} | ||
| OUTPUT ${f2py_c_file} | ||
| COMMENT "Generate C interfaces for Python using f2py-f90wrap" | ||
| VERBATIM | ||
| ) | ||
|
|
||
| python_extension_module(${generated_module_file}) | ||
| install(FILES ${python_mod_file} ${generated_module_file} #${CMAKE_CURRENT_SOURCE_DIR}/__init__.py | ||
| DESTINATION Utilities/python_wrapper/spec | ||
| add_custom_target( | ||
| f2py_SPEC | ||
| DEPENDS ${f2py_c_file} | ||
| ) | ||
|
|
||
| #set(PYINIT_STR "import sys\nimport os.path\nsys.path.append(os.path.dirname(__file__))\n\nfrom .spec import *\n") | ||
| #set(PYINIT_FILE ${CMAKE_CURRENT_BINARY_DIR}/__init__.py) | ||
| #FILE(WRITE ${PYINIT_FILE} ${PYINIT_STR}) | ||
| #install(FILES ${python_mod_file} ${generated_module_file} ${PYINIT_FILE} | ||
| # DESTINATION spec # Here spec is directory location | ||
| #) | ||
| #install(TARGETS xspec spec) | ||
| # LIBRARY DESTINATION ${CMAKE_INSTALL_DIR}/. | ||
| # RUNTIME DESTINATION bin | ||
| #) | ||
| # ============================================================================= | ||
| # Step 4: Build the Python extension module | ||
| # ============================================================================= | ||
|
|
||
| # Create the shared library using the generated files | ||
| add_library("${f2py_module_name}" MODULE | ||
| ${f2py_c_file} | ||
| "${F2PY_INCLUDE_DIR}/fortranobject.c" | ||
| ${f90wrap_output_files} | ||
| ) | ||
|
|
||
| # Set the library properties for Python extension | ||
| set_target_properties("${f2py_module_name}" PROPERTIES | ||
| PREFIX "" | ||
| SUFFIX ".${Python_SOABI}.so" | ||
| C_VISIBILITY_PRESET hidden | ||
| Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules | ||
| ) | ||
|
|
||
| # Tell CMake that the source files are generated | ||
| set_source_files_properties( | ||
| ${f2py_c_file} | ||
| ${f90wrap_output_files} | ||
| PROPERTIES GENERATED TRUE | ||
| ) | ||
|
|
||
| target_include_directories("${f2py_module_name}" PRIVATE | ||
| ${F2PY_INCLUDE_DIR} | ||
| ${Python_NumPy_INCLUDE_DIRS} | ||
| ${Python_INCLUDE_DIRS} | ||
| ${CMAKE_BINARY_DIR}/src | ||
| ${CMAKE_Fortran_MODULE_DIRECTORY}/spec_modules | ||
| ) | ||
|
|
||
| # Compile options for the wrapper Fortran files | ||
| target_compile_options("${f2py_module_name}" PRIVATE | ||
| $<$<COMPILE_LANGUAGE:Fortran>:-cpp> | ||
| $<$<AND:$<COMPILE_LANGUAGE:Fortran>,$<Fortran_COMPILER_ID:GNU>>:-ffree-line-length-none> | ||
| $<$<AND:$<COMPILE_LANGUAGE:Fortran>,$<Fortran_COMPILER_ID:GNU>>:-fdefault-real-8> | ||
| $<$<AND:$<COMPILE_LANGUAGE:Fortran>,$<Fortran_COMPILER_ID:GNU>>:-fPIC> | ||
| ) | ||
|
|
||
| target_link_libraries("${f2py_module_name}" PRIVATE | ||
| Python::NumPy | ||
| spec | ||
| ${SPEC_LINK_LIB} | ||
| ) | ||
|
|
||
| # Ensure proper build order | ||
| add_dependencies("${f2py_module_name}" f90wrap_SPEC f2py_SPEC spec) | ||
|
|
||
| # ============================================================================= | ||
| # Step 5: Installation | ||
| # ============================================================================= | ||
|
|
||
| # The package name is "spec" and the wrapper module inside is "spec_f90wrapped" | ||
| # This matches what simsopt expects: "import spec.spec_f90wrapped" | ||
| set(spec_package_name "spec") | ||
|
|
||
| # Install the existing spec package files from the source directory | ||
| install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/spec/" | ||
| DESTINATION "${spec_package_name}" | ||
| COMPONENT python_wrapper | ||
| FILES_MATCHING PATTERN "*.py" | ||
| ) | ||
|
|
||
| # Install the generated Python wrapper file (spec_f90wrapped.py) | ||
| install(FILES "${f90wrap_python_file}" | ||
| DESTINATION "${spec_package_name}" | ||
| COMPONENT python_wrapper | ||
| ) | ||
|
|
||
| # Install the shared library into the spec package | ||
| install(TARGETS "${f2py_module_name}" | ||
| LIBRARY DESTINATION "${spec_package_name}" | ||
| COMPONENT python_wrapper | ||
| ) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure setting a version here is a good idea?