diff --git a/CMAKE/ExtendedAPIHelpers.cmake b/CMAKE/ExtendedAPIHelpers.cmake index 08890ef8d..8ddb98d8d 100644 --- a/CMAKE/ExtendedAPIHelpers.cmake +++ b/CMAKE/ExtendedAPIHelpers.cmake @@ -1,22 +1,34 @@ include_guard(GLOBAL) set(EXTENDED_API_GENERATOR - "${CMAKE_CURRENT_LIST_DIR}/Generate64BitSuffixedSource.cmake" CACHE INTERNAL - "Script that generates 64-bit suffixed sources for the extended API") + "${CMAKE_CURRENT_LIST_DIR}/GenerateSuffixedSource.cmake" CACHE INTERNAL + "Script that generates suffixed sources for extended APIs") if(BUILD_INDEX64_EXT_API) add_custom_target(64bit_codegen ALL COMMENT "Generating 64-bit suffixed sources for extended API") endif() -# Generate 64-bit suffixed sources for the extended API. The generation happens -# at build time in the Generate64BitSuffixedSource.cmake script. -function(generate_64bit_suffixed_sources target source_list generated_sources) +# Generate suffixed sources for an extended API. The generation happens at +# build time in the GenerateSuffixedSource.cmake script. Arguments: +# SUFFIX -- suffix appended to symbols and file names +# (required) +# SYMBOL_ALLOWLIST ... -- only rename the listed symbols +# (case-insensitive); by default every symbol +# defined in the sources is renamed +# NO_STRING_REPLACEMENTS -- do not rename symbols inside string literals +function(generate_suffixed_sources target source_list generated_sources) set(options NO_STRING_REPLACEMENTS) - cmake_parse_arguments(PARSE_ARGV 3 extended_api "${options}" "" "") + set(oneValueArgs SUFFIX) + set(multiValueArgs SYMBOL_ALLOWLIST) + cmake_parse_arguments(PARSE_ARGV 3 extended_api "${options}" "${oneValueArgs}" "${multiValueArgs}") - get_filename_component(destination "${target}_64_sources" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}") - get_property(_generated_64bit_source_files GLOBAL PROPERTY EXTENDED_API_GENERATED_SOURCE_FILES) + if(NOT DEFINED extended_api_SUFFIX) + message(FATAL_ERROR "generate_suffixed_sources: SUFFIX is required") + endif() + + get_filename_component(destination "${target}${extended_api_SUFFIX}_sources" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}") + get_property(_generated_suffixed_source_files GLOBAL PROPERTY EXTENDED_API_GENERATED_SOURCE_FILES) set(new_generated_source_files) set(generated_source_files) @@ -24,7 +36,7 @@ function(generate_64bit_suffixed_sources target source_list generated_sources) get_filename_component(source_abs "${_source}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") get_filename_component(source_name "${_source}" NAME_WLE) get_filename_component(source_ext "${_source}" EXT) - set(output_file "${destination}/${source_name}_64${source_ext}") + set(output_file "${destination}/${source_name}${extended_api_SUFFIX}${source_ext}") set(_fortran_extensions ".f" ".F" ".f90" ".F90") if(NOT source_ext IN_LIST _fortran_extensions) @@ -33,13 +45,21 @@ function(generate_64bit_suffixed_sources target source_list generated_sources) endif() # Make sure we only have one custom command generating a given output file - if(NOT "${output_file}" IN_LIST _generated_64bit_source_files) + if(NOT "${output_file}" IN_LIST _generated_suffixed_source_files) set(generator_args "-DINPUT_FILE=${source_abs}" - "-DOUTPUT_FILE=${output_file}") + "-DOUTPUT_FILE=${output_file}" + "-DSUFFIX=${extended_api_SUFFIX}") if(extended_api_NO_STRING_REPLACEMENTS) list(APPEND generator_args "-DREPLACE_IN_STRINGS=OFF") endif() + if(DEFINED extended_api_SYMBOL_ALLOWLIST) + # Join with $ so that the allowlist stays one -D argument + # on the command line but still reaches the script as a CMake list. + # An allowlist change re-runs the generation (the command changes). + list(JOIN extended_api_SYMBOL_ALLOWLIST "$" _symbol_allowlist) + list(APPEND generator_args "-DSYMBOL_ALLOWLIST=${_symbol_allowlist}") + endif() add_custom_command( OUTPUT "${output_file}" @@ -50,7 +70,7 @@ function(generate_64bit_suffixed_sources target source_list generated_sources) DEPENDS "${source_abs}" "${EXTENDED_API_GENERATOR}" - COMMENT "Generating 64-bit extended API source for ${_source}" + COMMENT "Generating ${extended_api_SUFFIX} extended API source for ${_source}" VERBATIM) list(APPEND new_generated_source_files "${output_file}") @@ -62,13 +82,32 @@ function(generate_64bit_suffixed_sources target source_list generated_sources) # Make sure each generated source file is only part of one target to # avoid multiple targets trying to generate the same file if(new_generated_source_files) - add_custom_target("${target}_64bit_codegen" ALL + add_custom_target("${target}${extended_api_SUFFIX}_codegen" ALL DEPENDS ${new_generated_source_files} - COMMENT "Generating 64-bit suffixed sources for target ${target}") - add_dependencies(64bit_codegen "${target}_64bit_codegen") + COMMENT "Generating ${extended_api_SUFFIX} suffixed sources for target ${target}") + if(extended_api_SUFFIX STREQUAL "_64" AND TARGET 64bit_codegen) + add_dependencies(64bit_codegen "${target}${extended_api_SUFFIX}_codegen") + endif() set_property(GLOBAL APPEND PROPERTY EXTENDED_API_GENERATED_SOURCE_FILES ${new_generated_source_files}) endif() set(${generated_sources} ${generated_source_files} PARENT_SCOPE) endfunction() + +# Generate 64-bit suffixed sources for the extended API. Kept as a thin +# wrapper around generate_suffixed_sources for the Index-64 extended API. +function(generate_64bit_suffixed_sources target source_list generated_sources) + set(options NO_STRING_REPLACEMENTS) + cmake_parse_arguments(PARSE_ARGV 3 extended_api "${options}" "" "") + + set(_forwarded_options) + if(extended_api_NO_STRING_REPLACEMENTS) + list(APPEND _forwarded_options NO_STRING_REPLACEMENTS) + endif() + + generate_suffixed_sources("${target}" "${source_list}" _generated_source_files + SUFFIX "_64" ${_forwarded_options}) + + set(${generated_sources} ${_generated_source_files} PARENT_SCOPE) +endfunction() diff --git a/CMAKE/Generate64BitSuffixedSource.cmake b/CMAKE/GenerateSuffixedSource.cmake similarity index 91% rename from CMAKE/Generate64BitSuffixedSource.cmake rename to CMAKE/GenerateSuffixedSource.cmake index b9f44b7d6..c343244fb 100644 --- a/CMAKE/Generate64BitSuffixedSource.cmake +++ b/CMAKE/GenerateSuffixedSource.cmake @@ -10,6 +10,22 @@ if(NOT DEFINED REPLACE_IN_STRINGS) set(REPLACE_IN_STRINGS ON) endif() +if(NOT DEFINED SUFFIX) + message(FATAL_ERROR "SUFFIX must be set") +endif() + +# Optional allowlist: if given, only the listed symbols (case-insensitive) +# are suffixed. Used to route a subset of the routines to alternative +# implementations (e.g. LAPACKE test wrappers) while all other references +# keep resolving to their default implementation. +if(DEFINED SYMBOL_ALLOWLIST) + set(_symbol_allowlist) + foreach(_allowlist_entry IN LISTS SYMBOL_ALLOWLIST) + string(TOLOWER "${_allowlist_entry}" _allowlist_entry) + list(APPEND _symbol_allowlist "${_allowlist_entry}") + endforeach() +endif() + # Check whether the input file is fixed or free form based on its extension. get_filename_component(input_extension "${INPUT_FILE}" LAST_EXT) string(TOLOWER "${input_extension}" input_extension_lower) @@ -279,7 +295,7 @@ function(_protect_fortran_string_literals input_text result count_result) string(REGEX MATCHALL "${string_literal_regex}" string_literals "${current_line}") foreach(string_literal IN LISTS string_literals) - set(placeholder "@@LAPACK_64_STRING_LITERAL_${literal_count}@@") + set(placeholder "@@LAPACK_SUFFIX_STRING_LITERAL_${literal_count}@@") string(REPLACE "${string_literal}" "${placeholder}" current_line "${current_line}") set(protected_string_literal_${literal_count} "${string_literal}" @@ -304,7 +320,7 @@ function(_restore_fortran_string_literals input_text literal_count result) if(literal_count GREATER 0) math(EXPR last_literal_index "${literal_count} - 1") foreach(index RANGE 0 ${last_literal_index}) - set(placeholder "@@LAPACK_64_STRING_LITERAL_${index}@@") + set(placeholder "@@LAPACK_SUFFIX_STRING_LITERAL_${index}@@") string(REPLACE "${placeholder}" "${protected_string_literal_${index}}" output_text "${output_text}") endforeach() @@ -382,6 +398,19 @@ endwhile() list(REMOVE_DUPLICATES symbol_names) list(REMOVE_ITEM symbol_names ETIME etime ETIME_ etime_) +# Restrict the renaming to allowlisted symbols if an allowlist was given +if(DEFINED SYMBOL_ALLOWLIST) + set(_filtered_symbol_names) + foreach(symbol_name IN LISTS symbol_names) + string(TOLOWER "${symbol_name}" _symbol_name_lower) + list(FIND _symbol_allowlist "${_symbol_name_lower}" _symbol_allowlist_index) + if(NOT _symbol_allowlist_index EQUAL -1) + list(APPEND _filtered_symbol_names "${symbol_name}") + endif() + endforeach() + set(symbol_names ${_filtered_symbol_names}) +endif() + # If string literals should not be modified, protect them before performing replacements if(NOT REPLACE_IN_STRINGS) _protect_fortran_string_literals( @@ -394,7 +423,7 @@ foreach(symbol_name IN LISTS symbol_names) string(TOUPPER "${symbol_name}" symbol_upper) foreach(symbol_variant "${symbol_name}" "${symbol_lower}" "${symbol_upper}") set(match_regex "(^|[^A-Za-z0-9_])${symbol_variant}([^A-Za-z0-9_]|$)") - set(replacement "\\1${symbol_variant}_64\\2") + set(replacement "\\1${symbol_variant}${SUFFIX}\\2") string(REGEX REPLACE "${match_regex}" "${replacement}" rewritten_content "${rewritten_content}")