From 81cf4d72eb23238bbfefe98de7819926c97956aa Mon Sep 17 00:00:00 2001 From: Balthasar Reuter Date: Fri, 6 Oct 2023 15:37:38 +0100 Subject: [PATCH 1/3] Fix imports and pass inline_members to SCCBase --- scripts/loki_transform.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/loki_transform.py b/scripts/loki_transform.py index 3dd062219..b4afe4c57 100644 --- a/scripts/loki_transform.py +++ b/scripts/loki_transform.py @@ -17,7 +17,7 @@ from loki import ( Sourcefile, Transformation, Scheduler, SchedulerConfig, SubroutineItem, - Frontend, as_tuple, set_excepthook, auto_post_mortem_debugger, flatten, info, + Frontend, as_tuple, set_excepthook, auto_post_mortem_debugger, info, GlobalVarImportItem ) @@ -28,6 +28,7 @@ ) # pylint: disable=wrong-import-order +from transformations.argument_shape import ArgumentArrayShapeAnalysis, ExplicitArgumentArrayShapeTransformation from transformations.data_offload import DataOffloadTransformation, GlobalVarOffloadTransformation from transformations.derived_types import DerivedTypeArgumentsTransformation from transformations.utility_routines import DrHookTransformation, RemoveCallsTransformation @@ -206,7 +207,7 @@ def convert( if mode in ['scc', 'scc-hoist', 'scc-stack']: # Apply the basic SCC transformation set scheduler.process( SCCBaseTransformation( - horizontal=horizontal, directive=directive + horizontal=horizontal, directive=directive, inline_members=inline_members )) scheduler.process( SCCDevectorTransformation( horizontal=horizontal, trim_vector_sections=trim_vector_sections From 7ea6ad959b2dac5ce3d4d7f978ffce8a4949ecf4 Mon Sep 17 00:00:00 2001 From: Balthasar Reuter Date: Fri, 6 Oct 2023 17:32:03 +0100 Subject: [PATCH 2/3] CMake refactoring: Deprecate loki_transform_convert --- cmake/loki_transform.cmake | 946 +++++++++++------------------ cmake/loki_transform_helpers.cmake | 230 +++++++ scripts/loki_transform.py | 18 +- 3 files changed, 587 insertions(+), 607 deletions(-) create mode 100644 cmake/loki_transform_helpers.cmake diff --git a/cmake/loki_transform.cmake b/cmake/loki_transform.cmake index 9bae94f2f..ed107973f 100644 --- a/cmake/loki_transform.cmake +++ b/cmake/loki_transform.cmake @@ -5,188 +5,32 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -macro( _loki_transform_parse_args _func_name ) - - if( _PAR_UNPARSED_ARGUMENTS ) - ecbuild_critical( "Unknown keywords given to ${_func_name}(): \"${_PAR_UNPARSED_ARGUMENTS}\"" ) - endif() - - if( _PAR_DIRECTIVE ) - list( APPEND _ARGS --directive ${_PAR_DIRECTIVE} ) - endif() - - if( NOT _PAR_FRONTEND ) - ecbuild_critical( "No FRONTEND specified for ${_func_name}()" ) - endif() - list( APPEND _ARGS --frontend ${_PAR_FRONTEND} ) - - if( _PAR_HEADER ) - if ( _PAR_HEADERS ) - ecbuild_critical( "Both HEADERS and HEADER given to ${_func_name}(): Please use HEADERS only" ) - else() - ecbuild_warn( "${_func_name}(): HEADER is deprecated, please use HEADERS" ) - set( _PAR_HEADERS ${_PAR_HEADER} ) - endif() - endif() - - if( _PAR_HEADERS ) - foreach( _HEADER ${_PAR_HEADERS} ) - list( APPEND _ARGS --header ${_HEADER} ) - endforeach() - endif() - - if( _PAR_INCLUDE ) - if ( _PAR_INCLUDES ) - ecbuild_critical( "Both INCLUDES and INCLUDE given to ${_func_name}(): Please use INCLUDES only" ) - else() - ecbuild_warn( "${_func_name}(): INCLUDE is deprecated, please use INCLUDES" ) - set( _PAR_INCLUDES ${_PAR_INCLUDE} ) - endif() - endif() - - if( _PAR_INCLUDES ) - foreach( _INCLUDE ${_PAR_INCLUDES} ) - list( APPEND _ARGS --include ${_INCLUDE} ) - endforeach() - endif() - -endmacro() - -############################################################################## - -macro( _loki_transform_env_setup ) - - # The full path of the loki-transform.py executable - get_target_property( _LOKI_TRANSFORM_EXECUTABLE loki-transform.py IMPORTED_LOCATION ) - - set( _LOKI_TRANSFORM_ENV ) - set( _LOKI_TRANSFORM_PATH ) - - if( TARGET clawfc AND ${_PAR_FRONTEND} STREQUAL "omni" ) - # Ugly hack but I don't have a better solution: We need to add F_FRONT - # (which is installed in the same directory as clawfc) to the PATH, if - # OMNI is used as a frontend. Hence we have to update the environment in the below - # add_custom_command calls to loki-transform.py. - get_target_property( _CLAWFC_EXECUTABLE clawfc IMPORTED_LOCATION ) - get_filename_component( _CLAWFC_LOCATION ${_CLAWFC_EXECUTABLE} DIRECTORY ) - list( APPEND _LOKI_TRANSFORM_PATH ${_CLAWFC_LOCATION} ) - endif() - - if( _PAR_OUTPATH AND (${_PAR_FRONTEND} STREQUAL "omni" OR ${_PAR_FRONTEND} STREQUAL "ofp") ) - # With pre-processing, we may end up having a race condition on the preprocessed - # source files in parallel builds. Ensuring we use the outpath of the call to Loki - # should ensure in most cases that parallel builds write to different directories - # Note: this does not affect Fparser as we don't have to write preprocessed files - # to disk there - list( APPEND _LOKI_TRANSFORM_ENV LOKI_TMP_DIR=${_PAR_OUTPATH} ) - endif() - - if( _LOKI_TRANSFORM_ENV OR _LOKI_TRANSFORM_PATH ) - if( TARGET loki-transform.py ) - # Unfortunately, an environment update breaks the CMake feature of recognizing - # the executable in add_custom_command as a previously declared target, which would - # enable choosing the correct path automatically. Therefore, we have to insert also - # loki-transform.py into the PATH variable. - get_filename_component( _LOKI_TRANSFORM_LOCATION ${_LOKI_TRANSFORM_EXECUTABLE} DIRECTORY ) - list( APPEND _LOKI_TRANSFORM_PATH ${_LOKI_TRANSFORM_LOCATION} ) - endif() - - # Join all declared paths - string( REPLACE ";" ":" _LOKI_TRANSFORM_PATH "${_LOKI_TRANSFORM_PATH}" ) - list( APPEND _LOKI_TRANSFORM_ENV PATH=${_LOKI_TRANSFORM_PATH}:$ENV{PATH} ) - - # Run loki-transform.py via the CMake ENV wrapper - set( _LOKI_TRANSFORM ${CMAKE_COMMAND} -E env ${_LOKI_TRANSFORM_ENV} loki-transform.py ) - - # Also, now it breaks the dependency chain and we have to declare manual dependencies on - # loki-transform.py... - set( _LOKI_TRANSFORM_DEPENDENCY loki-transform.py ) - else() - # This is how it is meant to be: We can rely on CMake's ability to set the correct - # path of loki-transform.py if it was declared as an executable before (otherwise it - # will assume it has been already on the path when CMake was called - set( _LOKI_TRANSFORM loki-transform.py ) - set( _LOKI_TRANSFORM_DEPENDENCY "" ) - endif() - -endmacro() - -############################################################################## - -macro( _loki_transform_parse_convert_args _func_name ) - - _loki_transform_parse_args( ${_func_name} ) - - if( NOT _PAR_OUTPUT ) - ecbuild_critical( "No OUTPUT specified for ${_func_name}()" ) - endif() - - if( NOT _PAR_DEPENDS ) - ecbuild_critical( "No DEPENDS specified for ${_func_name}()" ) - endif() - - if( _PAR_CPP ) - list( APPEND _ARGS --cpp ) - endif() - - if( _PAR_OUTPATH ) - file( MAKE_DIRECTORY ${_PAR_OUTPATH} ) - list( APPEND _ARGS --out-path ${_PAR_OUTPATH} ) - endif() - - if( _PAR_DEFINE ) - if ( _PAR_DEFINITIONS ) - ecbuild_critical( "Both DEFINITIONS and DEFINE given to ${_func_name}(): Please use DEFINITIONS only" ) - else() - ecbuild_warn( "${_func_name}(): DEFINE is deprecated, please use DEFINITIONS" ) - set( _PAR_DEFINITIONS ${_PAR_DEFINE} ) - endif() - endif() - - if( _PAR_DEFINITIONS ) - foreach( _DEFINE ${_PAR_DEFINITIONS} ) - list( APPEND _ARGS --define ${_DEFINE} ) - endforeach() - endif() - - if( _PAR_XMOD ) - foreach( _XMOD ${_PAR_XMOD} ) - file( MAKE_DIRECTORY ${XMOD_DIR} ) - list( APPEND _ARGS --xmod ${_XMOD} ) - endforeach() - endif() - -endmacro() +include( loki_transform_helpers ) ############################################################################## # .rst: # -# loki_transform_convert -# ====================== +# loki_transform +# ============== # -# Apply Loki transformation in convert mode.:: +# Invoke loki-transform.py using the given options.:: # -# loki_transform_convert( +# loki_transform( +# COMMAND # OUTPUT [ ...] # DEPENDS [ ...] # MODE -# FRONTEND -# [CPP] +# CONFIG # [DIRECTIVE ] -# [CONFIG ] -# [PATH ] -# [OUTPATH ] -# [INCLUDES [ ...]] +# [CPP] +# [FRONTEND ] +# [INLINE_MEMBERS] +# [BUILDDIR ] +# [SOURCES [ ...]] # [HEADERS [ ...]] -# [DEFINITIONS [ ...]] -# [OMNI_INCLUDE [ ...]] -# [XMOD [ ...]] -# [REMOVE_OPENMP] [DATA_OFFLOAD] [GLOBAL_VAR_OFFLOAD] -# [TRIM_VECTOR_SECTIONS] [REMOVE_DERIVED_ARGS] -# [INLINE_MEMBERS] [DERIVE_ARGUMENT_ARRAY_SHAPE] # ) # -# Call ``loki-transform.py convert ...`` with the provided arguments. +# Call ``loki-transform.py ...`` with the provided arguments. # See ``loki-transform.py`` for a description of all options. # # Options @@ -198,320 +42,59 @@ endmacro() # ############################################################################## -function( loki_transform_convert ) +function( loki_transform ) - set( - options CPP DATA_OFFLOAD REMOVE_OPENMP ASSUME_DEVICEPTR GLOBAL_VAR_OFFLOAD - TRIM_VECTOR_SECTIONS REMOVE_DERIVED_ARGS INLINE_MEMBERS + set( options + CPP DATA_OFFLOAD REMOVE_OPENMP ASSUME_DEVICEPTR TRIM_VECTOR_SECTIONS GLOBAL_VAR_OFFLOAD + REMOVE_DERIVED_ARGS INLINE_MEMBERS DERIVE_ARGUMENT_ARRAY_SHAPE ) - set( oneValueArgs MODE DIRECTIVE FRONTEND CONFIG PATH OUTPATH ) - set( multiValueArgs OUTPUT DEPENDS INCLUDES INCLUDE HEADERS HEADER DEFINITIONS DEFINE OMNI_INCLUDE XMOD ) - - cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - - set( _ARGS ) - - if( NOT _PAR_MODE ) - ecbuild_critical( "No MODE specified for ${_func_name}()" ) - endif() - list( APPEND _ARGS --mode ${_PAR_MODE} ) - - _loki_transform_parse_convert_args( loki_transform_convert ) - - if( _PAR_CONFIG ) - list( APPEND _ARGS --config ${_PAR_CONFIG} ) - endif() - - if( _PAR_PATH ) - list( APPEND _ARGS --path ${_PAR_PATH} ) - endif() - - if( _PAR_OMNI_INCLUDE ) - foreach( _OMNI_INCLUDE ${_PAR_OMNI_INCLUDE} ) - list( APPEND _ARGS --omni-include ${_OMNI_INCLUDE} ) - endforeach() - endif() - - if( ${_PAR_DATA_OFFLOAD} ) - list( APPEND _ARGS --data-offload ) - endif() - - if( ${_PAR_REMOVE_OPENMP} ) - list( APPEND _ARGS --remove-openmp ) - endif() - - if( ${_PAR_ASSUME_DEVICEPTR} ) - list( APPEND _ARGS --assume-deviceptr ) - endif() - - if( ${_PAR_GLOBAL_VAR_OFFLOAD} ) - list( APPEND _ARGS --global-var-offload ) - endif() - - if( ${_PAR_TRIM_VECTOR_SECTIONS} ) - list( APPEND _ARGS --trim-vector-sections ) - endif() - - if( ${_PAR_REMOVE_DERIVED_ARGS} ) - list( APPEND _ARGS --remove-derived-args ) - endif() - - if( ${_PAR_INLINE_MEMBERS} ) - list( APPEND _ARGS --inline-members ) - endif() - - if( ${_PAR_DERIVE_ARGUMENT_ARRAY_SHAPE} ) - list( APPEND _ARGS --derive-argument-array-shape ) - endif() - - _loki_transform_env_setup() - - add_custom_command( - OUTPUT ${_PAR_OUTPUT} - COMMAND ${_LOKI_TRANSFORM} convert ${_ARGS} - DEPENDS ${_PAR_DEPENDS} ${_LOKI_TRANSFORM_DEPENDENCY} - COMMENT "[Loki] Pre-processing: mode=${_PAR_MODE} frontend=${_PAR_FRONTEND}" + set( oneValueArgs + COMMAND MODE DIRECTIVE FRONTEND CONFIG BUILDDIR ) - -endfunction() - -############################################################################## -# .rst: -# -# loki_transform_transpile -# ======================== -# -# Apply Loki transformation in transpile mode.:: -# -# loki_transform_transpile( -# OUTPUT [ ...] -# DEPENDS [ ...] -# FRONTEND [CPP] -# [DRIVER ] -# [SOURCES [ ...]] -# [OUTPATH ] -# [INCLUDES [ ...]] -# [HEADERS [ ...]] -# [DEFINITIONS [ ...]] -# [XMOD [ ...]] -# ) -# -# Call ``loki-transform.py transpile ...`` with the provided arguments. -# See ``loki-transform.py`` for a description of all options. -# -# Options -# ------- -# -# :OUTPUT: The output files generated by Loki. Providing them here allows -# to declare dependencies on this command later. -# :DEPENDS: The input files or targets this call depends on. -# -############################################################################## - -function( loki_transform_transpile ) - - set( options CPP ) - set( oneValueArgs FRONTEND OUTPATH DRIVER ) - set( multiValueArgs OUTPUT DEPENDS SOURCES SOURCE INCLUDES INCLUDE HEADERS HEADER DEFINITIONS DEFINE XMOD ) - - cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - - set( _ARGS ) - - _loki_transform_parse_convert_args( loki_transform_transpile ) - - if( _PAR_SOURCE ) - foreach( _SRC ${_PAR_SOURCE} ) - list( APPEND _ARGS --source ${_SRC} ) - endforeach() - endif() - - if( _PAR_DRIVER ) - list( APPEND _ARGS --driver ${_PAR_DRIVER} ) - endif() - - _loki_transform_env_setup() - - add_custom_command( - OUTPUT ${_PAR_OUTPUT} - COMMAND ${_LOKI_TRANSFORM} transpile ${_ARGS} - DEPENDS ${_PAR_DEPENDS} ${_LOKI_TRANSFORM_DEPENDENCY} - COMMENT "[Loki] Pre-processing: mode=transpile frontend=${_PAR_FRONTEND}" + set( multiValueArgs + OUTPUT DEPENDS SOURCES HEADERS INCLUDES DEFINITIONS OMNI_INCLUDE XMOD ) -endfunction() - - -############################################################################## -# .rst: -# -# claw_compile -# ============ -# -# Call the CLAW on a file.:: -# -# claw_compile( -# OUTPUT -# SOURCE -# MODEL_CONFIG -# TARGET -# DIRECTIVE -# [INCLUDE [ ...]] -# [XMOD [ ...]] -# [DEPENDS [ ...]] -# ) -# -############################################################################## -function( claw_compile ) - - set( options ) - set( oneValueArgs MODEL_CONFIG TARGET DIRECTIVE SOURCE OUTPUT ) - set( multiValueArgs INCLUDE XMOD DEPENDS ) - cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - if( NOT _PAR_SOURCE ) - ecbuild_critical( "No SOURCE given for claw_compile()" ) - endif() - - if( NOT _PAR_OUTPUT ) - ecbuild_critical( "No OUTPUT given for claw_compile()" ) - endif() - - set( _ARGS ) - - if( _PAR_MODEL_CONFIG ) - list( APPEND _ARGS --model-config=${_PAR_MODEL_CONFIG}) - endif() - - if( NOT _PAR_TARGET ) - ecbuild_critical( "No TARGET given for claw_compile()" ) - endif() - list( APPEND _ARGS --target=${_PAR_TARGET}) - - if( NOT _PAR_DIRECTIVE ) - ecbuild_critical( "No TARGET given for claw_compile()" ) - endif() - list( APPEND _ARGS --directive=${_PAR_DIRECTIVE}) - - if( _PAR_INCLUDE ) - foreach( INCLUDE ${_PAR_INCLUDE} ) - list( APPEND _ARGS -I ${INCLUDE} ) - endforeach() + if( _PAR_UNPARSED_ARGUMENTS ) + ecbuild_critical( "Unknown keywords given to loki_transform(): \"${_PAR_UNPARSED_ARGUMENTS}\"") endif() - if( _PAR_XMOD ) - foreach( XMOD ${_PAR_XMOD} ) - list( APPEND _ARGS -J ${XMOD} ) - endforeach() + # Select command for loki-transform.py + if( NOT _PAR_COMMAND ) + ecbuild_critical( "No COMMAND specified for loki_transform()" ) endif() - - add_custom_command( - OUTPUT ${_PAR_OUTPUT} - COMMAND clawfc -w 132 ${_ARGS} -o ${_PAR_OUTPUT} ${_PAR_SOURCE} - DEPENDS ${_PAR_SOURCE} ${_PAR_DEPENDS} - COMMENT "[clawfc] Pre-processing: target=${_PAR_TARGET} directive=${_PAR_DIRECTIVE}" - ) - -endfunction() - - -############################################################################## -# .rst: -# -# generate_xmod -# ============= -# -# Call OMNI's F_Front on a file to generate its xml-parse tree and, as a -# side effect, xmod-file.:: -# -# generate_xmod( -# OUTPUT -# SOURCE -# [XMOD [ ...]] -# [DEPENDS [ ...]] -# ) -# -# Note that the xmod-file will be located in the first path given to ``XMOD``. -# -############################################################################## -function( generate_xmod ) - - set( options ) - set( oneValueArgs SOURCE OUTPUT ) - set( multiValueArgs XMOD DEPENDS ) - - cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + set( _ARGS ${_PAR_COMMAND} ) if( NOT _PAR_OUTPUT ) - ecbuild_critical( "No OUTPUT given for generate_xmod()" ) + ecbuild_critical( "No OUTPUT specified for loki_transform()" ) endif() - if( NOT _PAR_SOURCE ) - ecbuild_critical( "No SOURCE given for generate_xmod()" ) + if( NOT _PAR_DEPENDS ) + ecbuild_critical( "No DEPENDS specified for loki_transform()" ) endif() - set( _ARGS ) - list( APPEND _ARGS -fleave-comment ) + # Translate function args to arguments for loki-transform.py + _loki_transform_parse_args() - if( _PAR_XMOD ) - foreach( XMOD ${_PAR_XMOD} ) - list( APPEND _ARGS -M ${XMOD} ) - endforeach() - endif() + # Translate function options to arguments for loki-transform.py + _loki_transform_parse_options() - if( TARGET clawfc ) - get_target_property( _CLAWFC_EXECUTABLE clawfc IMPORTED_LOCATION ) - get_filename_component( _CLAWFC_LOCATION ${_CLAWFC_EXECUTABLE} DIRECTORY ) - set( _F_FRONT_EXECUTABLE ${_CLAWFC_LOCATION}/F_Front ) - list( APPEND _PAR_DEPENDS clawfc ) - else() - set( _F_FRONT_EXECUTABLE F_Front ) - endif() + # Ensure transformation script and environment is available + _loki_transform_env_setup() + + ecbuild_debug( "COMMAND ${_LOKI_TRANSFORM} ${_ARGS}" ) add_custom_command( OUTPUT ${_PAR_OUTPUT} - COMMAND ${_F_FRONT_EXECUTABLE} ${_ARGS} -o ${_PAR_OUTPUT} ${_PAR_SOURCE} - DEPENDS ${_PAR_SOURCE} ${_PAR_DEPENDS} - COMMENT "[OMNI] Pre-processing: ${_PAR_SOURCE}" + COMMAND ${_LOKI_TRANSFORM} ${_ARGS} + DEPENDS ${_PAR_DEPENDS} ${_LOKI_TRANSFORM_DEPENDENCY} + COMMENT "[Loki] Pre-processing: command=${_PAR_COMMAND} mode=${_PAR_MODE} directive=${_PAR_DIRECTIVE} frontend=${_PAR_FRONTEND}" ) endfunction() -############################################################################## - -macro( _loki_transform_parse_target_args _func_name ) - - _loki_transform_parse_args( ${_func_name} ) - - if( _PAR_MODE ) - list( APPEND _ARGS --mode ${_PAR_MODE} ) - else() - ecbuild_critical( "No MODE specified for ${_func_name}()" ) - endif() - - if( _PAR_CPP ) - list( APPEND _ARGS --cpp ) - endif() - - if( _PAR_CONFIG ) - list( APPEND _ARGS --config ${_PAR_CONFIG} ) - else() - ecbuild_critical( "No CONFIG specified for ${_func_name}()" ) - endif() - - if( _PAR_BUILDDIR ) - list( APPEND _ARGS --build ${_PAR_BUILDDIR} ) - endif() - - if( _PAR_SOURCES ) - foreach( _SOURCE ${_PAR_SOURCES} ) - list( APPEND _ARGS --source ${_SOURCE} ) - endforeach() - endif() - -endmacro() - ############################################################################## # .rst: # @@ -546,9 +129,17 @@ function( loki_transform_plan ) cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + if( _PAR_UNPARSED_ARGUMENTS ) + ecbuild_critical( "Unknown keywords given to loki_transform_plan(): \"${_PAR_UNPARSED_ARGUMENTS}\"") + endif() + set( _ARGS ) - _loki_transform_parse_target_args( loki_transform_plan ) + # Translate function args to arguments for loki-transform.py + _loki_transform_parse_args() + + # Translate function options to arguments for loki-transform.py + _loki_transform_parse_options() if( NOT _PAR_NO_SOURCEDIR ) if( _PAR_SOURCEDIR ) @@ -562,137 +153,24 @@ function( loki_transform_plan ) list( APPEND _ARGS --callgraph ${_PAR_CALLGRAPH} ) endif() - if( _PAR_PLAN ) - list( APPEND _ARGS --plan-file ${_PAR_PLAN} ) - else() - ecbuild_critical( "No PLAN file specified for loki_transform_plan()" ) - endif() - - _loki_transform_env_setup() - - # Create a source transformation plan to tell CMake which files will be affected - ecbuild_info( "[Loki] Creating plan: mode=${_PAR_MODE} frontend=${_PAR_FRONTEND} config=${_PAR_CONFIG}" ) - ecbuild_debug( "COMMAND ${_LOKI_TRANSFORM_EXECUTABLE} plan ${_ARGS}" ) - - execute_process( - COMMAND ${_LOKI_TRANSFORM_EXECUTABLE} plan ${_ARGS} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND_ERROR_IS_FATAL ANY - ECHO_ERROR_VARIABLE - ) - -endfunction() - -############################################################################## -# .rst: -# -# loki_transform_command -# ====================== -# -# Apply Loki transformation using the chosen ```` mode.:: -# -# loki_transform_ecphys( -# [COMMAND ] -# OUTPUT [ ...] -# DEPENDS [ ...] -# MODE -# CONFIG -# [DIRECTIVE ] -# [CPP] -# [FRONTEND ] -# [INLINE_MEMBERS] -# [BUILDDIR ] -# [SOURCES [ ...]] -# [HEADERS [ ...]] -# ) -# -# Call ``loki-transform.py ...`` with the provided arguments. -# See ``loki-transform.py`` for a description of all options. -# -# Options -# ------- -# -# :OUTPUT: The output files generated by Loki. Providing them here allows -# to declare dependencies on this command later. -# :DEPENDS: The input files or targets this call depends on. -# -############################################################################## - -function( loki_transform_command ) - - set( options CPP INLINE_MEMBERS ) - set( oneValueArgs COMMAND MODE DIRECTIVE FRONTEND CONFIG BUILDDIR ) - set( multiValueArgs OUTPUT DEPENDS SOURCES HEADERS ) - - cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - - if( NOT _PAR_COMMAND ) - ecbuild_critical( "No COMMAND specified for loki_transform_command" ) - endif() - - set( _ARGS ) - - _loki_transform_parse_target_args( loki_transform_command ) - _loki_transform_env_setup() - - ecbuild_debug( "COMMAND ${_LOKI_TRANSFORM} ${_PAR_COMMAND} ${_ARGS}" ) - - add_custom_command( - OUTPUT ${_PAR_OUTPUT} - COMMAND ${_LOKI_TRANSFORM} ${_PAR_COMMAND} ${_ARGS} - DEPENDS ${_PAR_DEPENDS} ${_LOKI_TRANSFORM_DEPENDENCY} - COMMENT "[Loki] Pre-processing: command=${_PAR_COMMAND} mode=${_PAR_MODE} directive=${_PAR_DIRECTIVE} frontend=${_PAR_FRONTEND}" - ) - -endfunction() - -############################################################################## -# .rst: -# -# loki_copy_compile_flags -# ======================= -# -# Copy compile flags from a list of source files to a list of source files.:: -# -# -# loki_copy_compile_flags( ORIG_LIST NEW_LIST ) -# -# ``ORIG_LIST`` and ``NEW_LIST`` must have the same length. Compile flags are -# copied per-entry, this means matching indices between ``ORIG_LIST`` and -# ``NEW_LIST`` is assumed. -# -############################################################################## -function( loki_copy_compile_flags ) - - set( options "" ) - set( single_value_args "" ) - set( multi_value_args ORIG_LIST NEW_LIST ) + if( _PAR_PLAN ) + list( APPEND _ARGS --plan-file ${_PAR_PLAN} ) + else() + ecbuild_critical( "No PLAN file specified for loki_transform_plan()" ) + endif() - cmake_parse_arguments( _PAR "${options}" "${single_value_args}" "${multi_value_args}" ${ARGN} ) + _loki_transform_env_setup() - # Copy over compile flags for generated source. Note that this assumes - # matching indexes between ORIG_LIST and NEW_LIST to encode the source-to-source mapping. - list( LENGTH _PAR_ORIG_LIST nsources ) - math( EXPR maxidx "${nsources} - 1" ) - if ( nsources GREATER 0 ) - foreach( idx RANGE 0 ${maxidx} ) - list( GET _PAR_ORIG_LIST ${idx} orig ) - list( GET _PAR_NEW_LIST ${idx} newsrc ) - - ecbuild_debug( "[Loki] loki_copy_compile_flags: ${orig} -> ${newsrc}" ) - - foreach( _prop COMPILE_FLAGS - COMPILE_FLAGS_${CMAKE_BUILD_TYPE_CAPS} - OVERRIDE_COMPILE_FLAGS - OVERRIDE_COMPILE_FLAGS_${CMAKE_BUILD_TYPE_CAPS} ) - - get_source_file_property( ${orig}_${_prop} ${orig} ${_prop} ) - if( ${orig}_${_prop} ) - set_source_files_properties( ${newsrc} PROPERTIES ${_prop} ${${orig}_${_prop}} ) - endif() - endforeach() - endforeach() - endif() + # Create a source transformation plan to tell CMake which files will be affected + ecbuild_info( "[Loki] Creating plan: mode=${_PAR_MODE} frontend=${_PAR_FRONTEND} config=${_PAR_CONFIG}" ) + ecbuild_debug( "COMMAND ${_LOKI_TRANSFORM_EXECUTABLE} plan ${_ARGS}" ) + + execute_process( + COMMAND ${_LOKI_TRANSFORM_EXECUTABLE} plan ${_ARGS} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND_ERROR_IS_FATAL ANY + ECHO_ERROR_VARIABLE + ) endfunction() @@ -706,28 +184,28 @@ endfunction() # # loki_transform_target( # TARGET -# [COMMAND ] +# [COMMAND ] # MODE # CONFIG # PLAN # [CPP] [CPP_PLAN] # [FRONTEND ] +# [DIRECTIVE ] # [SOURCES [ ...]] # [HEADERS [ ...]] -# [NO_PLAN_SOURCEDIR] +# [NO_PLAN_SOURCEDIR COPY_UNMODIFIED INLINE_MEMBERS] # ) # -# Applies a Loki bulk transformation to the source files belonging to particular +# Applies a Loki bulk transformation to the source files belonging to a particular # CMake target according to the specified entry points in the ``config-file``. # -# This is done via a call to ``loki-transform.py plan ...`` during configure +# This is done via a call to ``loki-transform.py plan ...`` during configure, # from which the specific additions and deletions of source objects within the # target are derived. See ``loki_transform_plan`` for more details. # -# Subsequently, the actual bulk transformation of source -# files (in EC-Physics mode) is scheduled via ``loki-transform.py ``, -# where ```` is provided via ``COMMAND``. If none is given, this defaults -# to ``ecphys``. +# Subsequently, the actual bulk transformation of source files is scheduled +# via ``loki-transform.py ``, where ```` is provided via ``COMMAND``. +# If none is given, this defaults to ``convert``. # # Preprocessing of source files during plan or transformation stage can be # enabled using ``CPP_PLAN`` and ``CPP`` options, respectively. @@ -811,12 +289,12 @@ function( loki_transform_target ) list( APPEND _TRANSFORM_OPTIONS INLINE_MEMBERS ) endif() - loki_transform_command( + loki_transform( COMMAND ${_PAR_COMMAND} OUTPUT ${LOKI_SOURCES_TO_APPEND} MODE ${_PAR_MODE} CONFIG ${_PAR_CONFIG} - DIRECTIVE ${_PAR_DIRECTIVE} + DIRECTIVE ${_PAR_DIRECTIVE} FRONTEND ${_PAR_FRONTEND} BUILDDIR ${CMAKE_CURRENT_BINARY_DIR} SOURCES ${_PAR_SOURCES} @@ -880,3 +358,275 @@ function( loki_transform_target ) endif() endfunction() + +############################################################################## +# .rst: +# +# loki_transform_convert +# ====================== +# +# Deprecated interface to loki-transform.py. Use loki_transform( COMMAND convert ) instead.:: +# +############################################################################## + +function( loki_transform_convert ) + + ecbuild_warn( "\ +loki_transform_convert() is deprecated and will be removed in a future version! +Please use + loki_transform( COMMAND convert [...] ) +or + loki_transform_target( COMMAND convert [...] ). +" + ) + + set( options + CPP DATA_OFFLOAD REMOVE_OPENMP ASSUME_DEVICEPTR GLOBAL_VAR_OFFLOAD + TRIM_VECTOR_SECTIONS REMOVE_DERIVED_ARGS INLINE_MEMBERS + ) + set( oneValueArgs + MODE DIRECTIVE FRONTEND CONFIG PATH OUTPATH + ) + set( multiValueArgs + OUTPUT DEPENDS INCLUDES HEADERS DEFINITIONS OMNI_INCLUDE XMOD + ) + + cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + if( _PAR_UNPARSED_ARGUMENTS ) + ecbuild_critical( "Unknown keywords given to loki_transform_convert(): \"${_PAR_UNPARSED_ARGUMENTS}\"") + endif() + + # + # Rewrite old argument names + # + + # PATH -> SOURCES + list( TRANSFORM ARGV REPLACE "^PATH$" "SOURCES" ) + + # OUTPATH -> BUILDDIR + list( TRANSFORM ARGV REPLACE "^OUTPATH$" "BUILDDIR" ) + + # + # Call loki_transform + # + loki_transform( COMMAND "convert" ${ARGV} ) + +endfunction() + +############################################################################## +# .rst: +# +# loki_transform_transpile +# ======================== +# +# Apply Loki transformation in transpile mode.:: +# +# loki_transform_transpile( +# OUTPUT [ ...] +# DEPENDS [ ...] +# FRONTEND [CPP] +# [DRIVER ] +# [SOURCES [ ...]] +# [OUTPATH ] +# [INCLUDES [ ...]] +# [HEADERS [ ...]] +# [DEFINITIONS [ ...]] +# [XMOD [ ...]] +# ) +# +# Call ``loki-transform.py transpile ...`` with the provided arguments. +# See ``loki-transform.py`` for a description of all options. +# +# Options +# ------- +# +# :OUTPUT: The output files generated by Loki. Providing them here allows +# to declare dependencies on this command later. +# :DEPENDS: The input files or targets this call depends on. +# +############################################################################## + +function( loki_transform_transpile ) + + set( options CPP ) + set( oneValueArgs FRONTEND OUTPATH DRIVER ) + set( multiValueArgs OUTPUT DEPENDS SOURCE SOURCES INCLUDES HEADERS DEFINITIONS XMOD ) + + cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + if( _PAR_UNPARSED_ARGUMENTS ) + ecbuild_critical( "Unknown keywords given to loki_transform_transpile(): \"${_PAR_UNPARSED_ARGUMENTS}\"") + endif() + + set( _ARGS ) + + # Translate function args to arguments for loki-transform.py + _loki_transform_parse_args() + + # Translate function options to arguments for loki-transform.py + _loki_transform_parse_options() + + if( _PAR_OUTPATH ) + file( MAKE_DIRECTORY ${_PAR_OUTPATH} ) + list( APPEND _ARGS --build ${_PAR_OUTPATH} ) + endif() + + if( _PAR_DRIVER ) + list( APPEND _ARGS --driver ${_PAR_DRIVER} ) + endif() + + if( _PAR_SOURCE ) + ecbuild_warn( "loki_transform_transpile: SOURCE is deprecated, please use SOURCES" ) + foreach( _SOURCE ${_PAR_SOURCE} ) + list( APPEND _ARGS --source ${_SOURCE} ) + endforeach() + endif() + + _loki_transform_env_setup() + + add_custom_command( + OUTPUT ${_PAR_OUTPUT} + COMMAND ${_LOKI_TRANSFORM} transpile ${_ARGS} + DEPENDS ${_PAR_DEPENDS} ${_LOKI_TRANSFORM_DEPENDENCY} + COMMENT "[Loki] Pre-processing: mode=transpile frontend=${_PAR_FRONTEND}" + ) + +endfunction() + + +############################################################################## +# .rst: +# +# claw_compile +# ============ +# +# Call the CLAW on a file.:: +# +# claw_compile( +# OUTPUT +# SOURCE +# MODEL_CONFIG +# TARGET +# DIRECTIVE +# [INCLUDE [ ...]] +# [XMOD [ ...]] +# [DEPENDS [ ...]] +# ) +# +############################################################################## +function( claw_compile ) + + set( options ) + set( oneValueArgs MODEL_CONFIG TARGET DIRECTIVE SOURCE OUTPUT ) + set( multiValueArgs INCLUDE XMOD DEPENDS ) + + cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + if( NOT _PAR_SOURCE ) + ecbuild_critical( "No SOURCE given for claw_compile()" ) + endif() + + if( NOT _PAR_OUTPUT ) + ecbuild_critical( "No OUTPUT given for claw_compile()" ) + endif() + + set( _ARGS ) + + if( _PAR_MODEL_CONFIG ) + list( APPEND _ARGS --model-config=${_PAR_MODEL_CONFIG}) + endif() + + if( NOT _PAR_TARGET ) + ecbuild_critical( "No TARGET given for claw_compile()" ) + endif() + list( APPEND _ARGS --target=${_PAR_TARGET}) + + if( NOT _PAR_DIRECTIVE ) + ecbuild_critical( "No TARGET given for claw_compile()" ) + endif() + list( APPEND _ARGS --directive=${_PAR_DIRECTIVE}) + + if( _PAR_INCLUDE ) + foreach( INCLUDE ${_PAR_INCLUDE} ) + list( APPEND _ARGS -I ${INCLUDE} ) + endforeach() + endif() + + if( _PAR_XMOD ) + foreach( XMOD ${_PAR_XMOD} ) + list( APPEND _ARGS -J ${XMOD} ) + endforeach() + endif() + + add_custom_command( + OUTPUT ${_PAR_OUTPUT} + COMMAND clawfc -w 132 ${_ARGS} -o ${_PAR_OUTPUT} ${_PAR_SOURCE} + DEPENDS ${_PAR_SOURCE} ${_PAR_DEPENDS} + COMMENT "[clawfc] Pre-processing: target=${_PAR_TARGET} directive=${_PAR_DIRECTIVE}" + ) + +endfunction() + + +############################################################################## +# .rst: +# +# generate_xmod +# ============= +# +# Call OMNI's F_Front on a file to generate its xml-parse tree and, as a +# side effect, xmod-file.:: +# +# generate_xmod( +# OUTPUT +# SOURCE +# [XMOD [ ...]] +# [DEPENDS [ ...]] +# ) +# +# Note that the xmod-file will be located in the first path given to ``XMOD``. +# +############################################################################## +function( generate_xmod ) + + set( options ) + set( oneValueArgs SOURCE OUTPUT ) + set( multiValueArgs XMOD DEPENDS ) + + cmake_parse_arguments( _PAR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + if( NOT _PAR_OUTPUT ) + ecbuild_critical( "No OUTPUT given for generate_xmod()" ) + endif() + + if( NOT _PAR_SOURCE ) + ecbuild_critical( "No SOURCE given for generate_xmod()" ) + endif() + + set( _ARGS ) + list( APPEND _ARGS -fleave-comment ) + + if( _PAR_XMOD ) + foreach( XMOD ${_PAR_XMOD} ) + list( APPEND _ARGS -M ${XMOD} ) + endforeach() + endif() + + if( TARGET clawfc ) + get_target_property( _CLAWFC_EXECUTABLE clawfc IMPORTED_LOCATION ) + get_filename_component( _CLAWFC_LOCATION ${_CLAWFC_EXECUTABLE} DIRECTORY ) + set( _F_FRONT_EXECUTABLE ${_CLAWFC_LOCATION}/F_Front ) + list( APPEND _PAR_DEPENDS clawfc ) + else() + set( _F_FRONT_EXECUTABLE F_Front ) + endif() + + add_custom_command( + OUTPUT ${_PAR_OUTPUT} + COMMAND ${_F_FRONT_EXECUTABLE} ${_ARGS} -o ${_PAR_OUTPUT} ${_PAR_SOURCE} + DEPENDS ${_PAR_SOURCE} ${_PAR_DEPENDS} + COMMENT "[OMNI] Pre-processing: ${_PAR_SOURCE}" + ) + +endfunction() diff --git a/cmake/loki_transform_helpers.cmake b/cmake/loki_transform_helpers.cmake new file mode 100644 index 000000000..a3a5b344d --- /dev/null +++ b/cmake/loki_transform_helpers.cmake @@ -0,0 +1,230 @@ +# (C) Copyright 2018- ECMWF. +# This software is licensed under the terms of the Apache Licence Version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +# In applying this licence, ECMWF does not waive the privileges and immunities +# granted to it by virtue of its status as an intergovernmental organisation +# nor does it submit to any jurisdiction. + +# +# Utility macro to translate single value and multi value arguments +# in loki_transform to command line arguments for loki-transform.py +# +macro( _loki_transform_parse_args ) + + if( _PAR_MODE ) + list( APPEND _ARGS --mode ${_PAR_MODE} ) + endif() + + if( _PAR_CONFIG ) + list( APPEND _ARGS --config ${_PAR_CONFIG} ) + endif() + + if( _PAR_BUILDDIR ) + file( MAKE_DIRECTORY ${_PAR_BUILDDIR} ) + list( APPEND _ARGS --build ${_PAR_BUILDDIR} ) + endif() + + if( _PAR_DIRECTIVE ) + list( APPEND _ARGS --directive ${_PAR_DIRECTIVE} ) + endif() + + if( _PAR_FRONTEND ) + list( APPEND _ARGS --frontend ${_PAR_FRONTEND} ) + endif() + + if( _PAR_SOURCES ) + foreach( _SOURCE ${_PAR_SOURCES} ) + list( APPEND _ARGS --source ${_SOURCE} ) + endforeach() + endif() + + if( _PAR_HEADERS ) + foreach( _HEADER ${_PAR_HEADERS} ) + list( APPEND _ARGS --header ${_HEADER} ) + endforeach() + endif() + + if( _PAR_INCLUDES ) + foreach( _INCLUDE ${_PAR_INCLUDES} ) + list( APPEND _ARGS --include ${_INCLUDE} ) + endforeach() + endif() + + if( _PAR_DEFINITIONS ) + foreach( _DEFINE ${_PAR_DEFINITIONS} ) + list( APPEND _ARGS --define ${_DEFINE} ) + endforeach() + endif() + + if( _PAR_OMNI_INCLUDE ) + foreach( _OMNI_INCLUDE ${_PAR_OMNI_INCLUDE} ) + list( APPEND _ARGS --omni-include ${_OMNI_INCLUDE} ) + endforeach() + endif() + + if( _PAR_XMOD ) + foreach( _XMOD ${_PAR_XMOD} ) + file( MAKE_DIRECTORY ${XMOD_DIR} ) + list( APPEND _ARGS --xmod ${_XMOD} ) + endforeach() + endif() + +endmacro() + + +############################################################################## + +# +# Utility macro to translate options in loki_transform to command line +# arguments for loki-transform.py +# +macro( _loki_transform_parse_options ) + + if( _PAR_CPP ) + list( APPEND _ARGS --cpp ) + endif() + + if( _PAR_DATA_OFFLOAD ) + list( APPEND _ARGS --data-offload ) + endif() + + if( _PAR_REMOVE_OPENMP ) + list( APPEND _ARGS --remove-openmp ) + endif() + + if( _PAR_ASSUME_DEVICEPTR ) + list( APPEND _ARGS --assume-deviceptr ) + endif() + + if( _PAR_GLOBAL_VAR_OFFLOAD ) + list( APPEND _ARGS --global-var-offload ) + endif() + + if( _PAR_TRIM_VECTOR_SECTIONS ) + list( APPEND _ARGS --trim-vector-sections ) + endif() + + if( _PAR_REMOVE_DERIVED_ARGS ) + list( APPEND _ARGS --remove-derived-args ) + endif() + + if( _PAR_INLINE_MEMBERS ) + list( APPEND _ARGS --inline-members ) + endif() + + if( _PAR_DERIVE_ARGUMENT_ARRAY_SHAPE ) + list( APPEND _ARGS --derive-argument-array-shape ) + endif() + +endmacro() + +############################################################################## + +macro( _loki_transform_env_setup ) + + # The full path of the loki-transform.py executable + get_target_property( _LOKI_TRANSFORM_EXECUTABLE loki-transform.py IMPORTED_LOCATION ) + + set( _LOKI_TRANSFORM_ENV ) + set( _LOKI_TRANSFORM_PATH ) + + if( TARGET clawfc AND ${_PAR_FRONTEND} STREQUAL "omni" ) + # Ugly hack but I don't have a better solution: We need to add F_FRONT + # (which is installed in the same directory as clawfc) to the PATH, if + # OMNI is used as a frontend. Hence we have to update the environment in the below + # add_custom_command calls to loki-transform.py. + get_target_property( _CLAWFC_EXECUTABLE clawfc IMPORTED_LOCATION ) + get_filename_component( _CLAWFC_LOCATION ${_CLAWFC_EXECUTABLE} DIRECTORY ) + list( APPEND _LOKI_TRANSFORM_PATH ${_CLAWFC_LOCATION} ) + endif() + + if( _PAR_OUTPATH AND (${_PAR_FRONTEND} STREQUAL "omni" OR ${_PAR_FRONTEND} STREQUAL "ofp") ) + # With pre-processing, we may end up having a race condition on the preprocessed + # source files in parallel builds. Ensuring we use the outpath of the call to Loki + # should ensure in most cases that parallel builds write to different directories + # Note: this does not affect Fparser as we don't have to write preprocessed files + # to disk there + list( APPEND _LOKI_TRANSFORM_ENV LOKI_TMP_DIR=${_PAR_OUTPATH} ) + endif() + + if( _LOKI_TRANSFORM_ENV OR _LOKI_TRANSFORM_PATH ) + if( TARGET loki-transform.py ) + # Unfortunately, an environment update breaks the CMake feature of recognizing + # the executable in add_custom_command as a previously declared target, which would + # enable choosing the correct path automatically. Therefore, we have to insert also + # loki-transform.py into the PATH variable. + get_filename_component( _LOKI_TRANSFORM_LOCATION ${_LOKI_TRANSFORM_EXECUTABLE} DIRECTORY ) + list( APPEND _LOKI_TRANSFORM_PATH ${_LOKI_TRANSFORM_LOCATION} ) + endif() + + # Join all declared paths + string( REPLACE ";" ":" _LOKI_TRANSFORM_PATH "${_LOKI_TRANSFORM_PATH}" ) + list( APPEND _LOKI_TRANSFORM_ENV PATH=${_LOKI_TRANSFORM_PATH}:$ENV{PATH} ) + + # Run loki-transform.py via the CMake ENV wrapper + set( _LOKI_TRANSFORM ${CMAKE_COMMAND} -E env ${_LOKI_TRANSFORM_ENV} loki-transform.py ) + + # Also, now it breaks the dependency chain and we have to declare manual dependencies on + # loki-transform.py... + set( _LOKI_TRANSFORM_DEPENDENCY loki-transform.py ) + else() + # This is how it is meant to be: We can rely on CMake's ability to set the correct + # path of loki-transform.py if it was declared as an executable before (otherwise it + # will assume it has been already on the path when CMake was called + set( _LOKI_TRANSFORM loki-transform.py ) + set( _LOKI_TRANSFORM_DEPENDENCY "" ) + endif() + +endmacro() + +############################################################################## +# .rst: +# +# loki_copy_compile_flags +# ======================= +# +# Copy compile flags from a list of source files to a list of source files.:: +# +# +# loki_copy_compile_flags( ORIG_LIST NEW_LIST ) +# +# ``ORIG_LIST`` and ``NEW_LIST`` must have the same length. Compile flags are +# copied per-entry, this means matching indices between ``ORIG_LIST`` and +# ``NEW_LIST`` is assumed. +# +############################################################################## +function( loki_copy_compile_flags ) + + set( options "" ) + set( single_value_args "" ) + set( multi_value_args ORIG_LIST NEW_LIST ) + + cmake_parse_arguments( _PAR "${options}" "${single_value_args}" "${multi_value_args}" ${ARGN} ) + + # Copy over compile flags for generated source. Note that this assumes + # matching indexes between ORIG_LIST and NEW_LIST to encode the source-to-source mapping. + list( LENGTH _PAR_ORIG_LIST nsources ) + math( EXPR maxidx "${nsources} - 1" ) + if ( nsources GREATER 0 ) + foreach( idx RANGE 0 ${maxidx} ) + list( GET _PAR_ORIG_LIST ${idx} orig ) + list( GET _PAR_NEW_LIST ${idx} newsrc ) + + ecbuild_debug( "[Loki] loki_copy_compile_flags: ${orig} -> ${newsrc}" ) + + foreach( _prop COMPILE_FLAGS + COMPILE_FLAGS_${CMAKE_BUILD_TYPE_CAPS} + OVERRIDE_COMPILE_FLAGS + OVERRIDE_COMPILE_FLAGS_${CMAKE_BUILD_TYPE_CAPS} ) + + get_source_file_property( ${orig}_${_prop} ${orig} ${_prop} ) + if( ${orig}_${_prop} ) + set_source_files_properties( ${newsrc} PROPERTIES ${_prop} ${${orig}_${_prop}} ) + endif() + endforeach() + endforeach() + endif() + +endfunction() + +############################################################################## diff --git a/scripts/loki_transform.py b/scripts/loki_transform.py index b4afe4c57..1679a66a4 100644 --- a/scripts/loki_transform.py +++ b/scripts/loki_transform.py @@ -284,9 +284,9 @@ def transform_subroutine(self, routine, **kwargs): @cli.command() -@click.option('--out-path', '-out', type=click.Path(), +@click.option('--build', '-b', '--out-path', type=click.Path(), help='Path for generated souce files.') -@click.option('--header', '-I', type=click.Path(), multiple=True, +@click.option('--header', '-h', type=click.Path(), multiple=True, help='Path for additional header file(s).') @click.option('--source', '-s', type=click.Path(), help='Source file to convert.') @@ -296,13 +296,13 @@ def transform_subroutine(self, routine, **kwargs): help='Trigger C-preprocessing of source files.') @click.option('--include', '-I', type=click.Path(), multiple=True, help='Path for additional header file(s)') -@click.option('--define', '-I', multiple=True, +@click.option('--define', '-D', multiple=True, help='Additional symbol definitions for C-preprocessor') @click.option('--xmod', '-M', type=click.Path(), multiple=True, help='Path for additional module file(s)') -@click.option('--frontend', default='omni', type=click.Choice(['fp', 'ofp', 'omni']), +@click.option('--frontend', default='fp', type=click.Choice(['fp', 'ofp', 'omni']), help='Frontend parser to use (default FP)') -def transpile(out_path, header, source, driver, cpp, include, define, frontend, xmod): +def transpile(build, header, source, driver, cpp, include, define, frontend, xmod): """ Convert kernels to C and generate ISO-C bindings and interfaces. """ @@ -340,21 +340,21 @@ def transpile(out_path, header, source, driver, cpp, include, define, frontend, # Now we instantiate our pipeline and apply the changes transformation = FortranCTransformation() - transformation.apply(kernel, role='kernel', path=out_path) + transformation.apply(kernel, role='kernel', path=build) # Traverse header modules to create getter functions for module variables for h in definitions: - transformation.apply(h, role='header', path=out_path) + transformation.apply(h, role='header', path=build) # Housekeeping: Inject our re-named kernel and auto-wrapped it in a module dependency = DependencyTransformation(suffix='_FC', mode='module', module_suffix='_MOD') kernel.apply(dependency, role='kernel', targets=()) - kernel.write(path=Path(out_path)/kernel.path.with_suffix('.c.F90').name) + kernel.write(path=Path(build)/kernel.path.with_suffix('.c.F90').name) # Re-generate the driver that mimicks the original source file, # but imports and calls our re-generated kernel. driver.apply(dependency, role='driver', targets=kernel_name) - driver.write(path=Path(out_path)/driver.path.with_suffix('.c.F90').name) + driver.write(path=Path(build)/driver.path.with_suffix('.c.F90').name) @cli.command('plan') From d3f80bcf527265ccc2c0a7c7a0b7c0aa8db599ad Mon Sep 17 00:00:00 2001 From: Balthasar Reuter Date: Sun, 8 Oct 2023 08:07:30 +0100 Subject: [PATCH 3/3] Remove dangling call to parse_transform_target_args --- cmake/loki_transform.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/loki_transform.cmake b/cmake/loki_transform.cmake index ed107973f..dc14af58e 100644 --- a/cmake/loki_transform.cmake +++ b/cmake/loki_transform.cmake @@ -30,7 +30,7 @@ include( loki_transform_helpers ) # [HEADERS [ ...]] # ) # -# Call ``loki-transform.py ...`` with the provided arguments. +# Call ``loki-transform.py ...`` with the provided arguments. # See ``loki-transform.py`` for a description of all options. # # Options @@ -228,7 +228,9 @@ function( loki_transform_target ) cmake_parse_arguments( _PAR "${options}" "${single_value_args}" "${multi_value_args}" ${ARGN} ) - _loki_transform_parse_target_args( loki_transform_target ) + if( _PAR_UNPARSED_ARGUMENTS ) + ecbuild_critical( "Unknown keywords given to loki_transform_target(): \"${_PAR_UNPARSED_ARGUMENTS}\"") + endif() if( NOT _PAR_TARGET ) ecbuild_critical( "The call to loki_transform_target() doesn't specify the TARGET." )