RptCleanup - Add cmake command to generated compat modules for deprecated guile modules

The function accepts the name of a deprecated module and optionally a
replacement module.
With that info it will generate a stub guile module that
- will be installed in the gnucash guile load path
- emits a deprecation warning when the old module is used
- if a replacement module is given, will automatically load that module instead

This allows us to gently deprecate complete guile modules without
the burden of manually maintaining their module files.
This commit is contained in:
Geert Janssens 2019-06-15 10:13:42 +02:00
parent 528bbff8da
commit f39275be32
4 changed files with 114 additions and 15 deletions

View File

@ -95,10 +95,12 @@ macro(find_guile_dirs)
"{GNC_HOME}/${GUILE_REL_UNIX_LIBDIR}"
"{GNC_HOME}/${GUILE_REL_UNIX_SITEDIR}"
"{GNC_HOME}/${GUILE_REL_UNIX_TOP_SITEDIR}"
"{GNC_HOME}/${GUILE_REL_UNIX_SITEDIR}/gnucash/deprecated" # Path to gnucash' deprecated modules
"{GNC_HOME}/${GUILE_REL_UNIX_DATADIR}")
set (GNC_GUILE_LOAD_COMPILED_PATH
"{GNC_HOME}/${GUILE_REL_UNIX_CCACHEDIR}"
"{GNC_HOME}/${GUILE_REL_UNIX_CCACHEDIR}/gnucash/deprecated"
"{GNC_HOME}/${GUILE_REL_UNIX_SITECCACHEDIR}")
endmacro(find_guile_dirs)
@ -154,7 +156,7 @@ function(make_scheme_targets _TARGET _SOURCE_FILES _OUTPUT_DIR _GUILE_DEPENDS
endif(MAKE_LINKS)
# Construct the guile source and compiled load paths
set(_GUILE_LOAD_PATH "${current_srcdir}" "${current_bindir}")
set(_GUILE_LOAD_PATH "${current_srcdir}" "${current_bindir}" "${current_bindir}/deprecated")
set(_GUILE_LOAD_COMPILED_PATH "${current_bindir}")
# VERSION_GREATER_EQUAL introduced in CMake 3.7.
if(MINGW64 AND (${GUILE_EFFECTIVE_VERSION} VERSION_GREATER 2.2 OR
@ -164,9 +166,10 @@ function(make_scheme_targets _TARGET _SOURCE_FILES _OUTPUT_DIR _GUILE_DEPENDS
list(APPEND _GUILE_LOAD_PATH ${guile_load_path})
list(APPEND _GUILE_LOAD_COMPILED_PATH ${guile_load_compiled_path})
endif()
set(_GUILE_CACHE_DIR ${CMAKE_BINARY_DIR}/${GUILE_REL_UNIX_SITECCACHEDIR})
set(_GUILE_CACHE_DIR "${CMAKE_BINARY_DIR}/${GUILE_REL_UNIX_SITECCACHEDIR}")
list(APPEND _GUILE_LOAD_PATH "${CMAKE_BINARY_DIR}/${GUILE_REL_UNIX_SITEDIR}")
list(APPEND _GUILE_LOAD_COMPILED_PATH ${_GUILE_CACHE_DIR})
list(APPEND _GUILE_LOAD_COMPILED_PATH ${_GUILE_CACHE_DIR}
"${CMAKE_BINARY_DIR}/${GUILE_REL_UNIX_SITECCACHEDIR}/gnucash/deprecated")
set(_TARGET_FILES "")
@ -253,3 +256,68 @@ function(gnc_add_scheme_test_targets _TARGET _SOURCE_FILES _OUTPUT_DIR _GUILE_DE
"${_GUILE_DEPENDS}" "${MAKE_LINKS}")
add_dependencies(check ${_TARGET})
endfunction(gnc_add_scheme_test_targets)
# Function to write boilerplate code for deprecated guile modules
# All but the _OLDMOD parameter are optional
# It will emit a deprecation warning and if _NEWMOD is also given
# that module will be loaded instead.
# If _NEWMOD is given, _DEPENDS should be set to the target for which
# that module is a source file.
# For example module (gnucash reports standard transaction)
# is defined in transaction.scm, which is a source file for
# cmake target scm-reports-standard so that should be set as _DEPENDS.
# The function expects module names in the form "gnucash mod parts"
# If _DEPMSG is left blank, the module will emit a generic message,
# otherswise _DEPMSG will be emitted.
function(gnc_add_scheme_deprecated_module _OLDMOD _NEWMOD _DEPENDS _DEPMSG)
string(STRIP _OLDMOD "${_OLDMOD}")
string(REPLACE " " "-" _TARGET ${_OLDMOD})
set(_TARGET "scm-deprecated-${_TARGET}")
string(REPLACE " " ";" MODPARTS "${_OLDMOD}")
list(GET MODPARTS -1 DEPFILENAME)
set(SOURCEFILE "${CMAKE_CURRENT_BINARY_DIR}/deprecated/${DEPFILENAME}.scm")
string(FIND "${_OLDMOD}" ${DEPFILENAME} POS REVERSE)
if (${POS} LESS 2)
set(MODPATH "gnucash/deprecated")
else()
list(REMOVE_AT MODPARTS -1)
string(REPLACE ";" "/" MODPATH "${MODPARTS}")
set(MODPATH "gnucash/deprecated/${MODPATH}")
endif()
set(DEPPREFIX "* WARN <gnc-guile-deprecation> *: ")
if (_DEPMSG)
set(DEPWARNING "(issue-deprecation-warning \"${DEPPREFIX}${_DEPMSG}\")")
else()
set(DEPWARNING
"(issue-deprecation-warning \"${DEPPREFIX}Module '(${_OLDMOD})' has been deprecated and will be removed in the future.\")")
if (_NEWMOD)
set(DEPWARNING "${DEPWARNING}
(issue-deprecation-warning \"${DEPPREFIX}Use module '(${_NEWMOD})' instead.\")")
endif()
endif()
# Write the stub file
file(WRITE ${SOURCEFILE} "
;; ${DEPFILENAME}.scm
;; Compatibility module for deprecated (${_OLDMOD}).
;; This file is autogenerated, do not modify by hand.
(define-module (${_OLDMOD}))
${DEPWARNING}
")
if (_NEWMOD)
file(APPEND ${SOURCEFILE} "
(use-modules (${_NEWMOD}))
(let ((i (module-public-interface (current-module))))
(module-use! i (resolve-interface '(${_NEWMOD}))))")
endif()
gnc_add_scheme_targets("${_TARGET}" "${SOURCEFILE}" "${MODPATH}" "${_DEPENDS}" FALSE)
endfunction(gnc_add_scheme_deprecated_module)

View File

@ -31,17 +31,20 @@ function(get_guile_env)
list(APPEND env "GNC_MODULE_PATH=${_GNC_MODULE_PATH}")
list(APPEND env "GUILE=${GUILE_EXECUTABLE}")
if (NOT WIN32)
list(APPEND env "GUILE_LOAD_COMPILED_PATH=${CMAKE_BINARY_DIR}/${GUILE_REL_SITECCACHEDIR}:${CMAKE_BINARY_DIR}/${GUILE_REL_SITECCACHEDIR}/tests")
endif()
set(guile_load_paths "")
list(APPEND guile_load_paths ${CMAKE_CURRENT_SOURCE_DIR}/mod-foo)
list(APPEND guile_load_paths ${CMAKE_CURRENT_SOURCE_DIR}/mod-bar)
list(APPEND guile_load_paths ${CMAKE_CURRENT_SOURCE_DIR}/mod-baz)
if (WIN32)
list(APPEND guile_load_paths ${CMAKE_BINARY_DIR}/share/gnucash/scm)
endif()
list(APPEND guile_load_paths "${CMAKE_CURRENT_SOURCE_DIR}/mod-foo")
list(APPEND guile_load_paths "${CMAKE_CURRENT_SOURCE_DIR}/mod-bar")
list(APPEND guile_load_paths "${CMAKE_CURRENT_SOURCE_DIR}/mod-baz")
#list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}")
list(APPEND guile_load_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITEDIR}/gnucash/deprecated") # Path to gnucash' deprecated modules
set(guile_load_path "${guile_load_paths}")
set(guile_load_compiled_paths "")
list(APPEND guile_load_compiled_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITECCACHEDIR}")
list(APPEND guile_load_compiled_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITECCACHEDIR}/gnucash/deprecated")
list(APPEND guile_load_compiled_paths "${CMAKE_BINARY_DIR}/${GUILE_REL_SITECCACHEDIR}/tests")
set(guile_load_compiled_path "${guile_load_compiled_paths}")
if (MINGW64)
set(new_path "")
foreach(load_item ${guile_load_path})
@ -49,13 +52,24 @@ function(get_guile_env)
list(APPEND new_path ${load_item})
endforeach(load_item)
set(guile_load_path ${new_path})
set(new_path "")
foreach(load_item ${guile_load_compiled_path})
string(REGEX REPLACE "^([A-Za-z]):" "/\\1" load_item ${load_item})
list(APPEND new_path ${load_item})
endforeach(load_item)
set(guile_load_compiled_path ${new_path})
endif (MINGW64)
if (WIN32 AND NOT MINGW64)
string(REPLACE ";" "\\\\;" GUILE_LOAD_PATH "${guile_load_path}")
string(REPLACE ";" "\\\\;" GUILE_LOAD_PATH "${guile_load_path}")
string(REPLACE ";" "\\\\;" GUILE_LOAD_COMPILED_PATH "${guile_load_compiled_path}")
else()
string(REPLACE ";" ":" GUILE_LOAD_PATH "${guile_load_path}")
string(REPLACE ";" ":" GUILE_LOAD_PATH "${guile_load_path}")
string(REPLACE ";" ":" GUILE_LOAD_COMPILED_PATH "${guile_load_compiled_path}")
endif()
list(APPEND env GUILE_LOAD_PATH=${GUILE_LOAD_PATH})
list(APPEND env "GUILE_LOAD_PATH=${GUILE_LOAD_PATH}")
list(APPEND env "GUILE_LOAD_COMPILED_PATH=${GUILE_LOAD_COMPILED_PATH}")
list(APPEND env "GUILE_WARN_DEPRECATED=detailed")
set(GUILE_ENV ${env} PARENT_SCOPE)
endfunction()

View File

@ -1,5 +1,6 @@
set(scm_test_SCHEME
test-libgnucash-scm-utilities.scm
test-module-deprecation.scm
)
set(GUILE_DEPENDS
@ -25,3 +26,7 @@ set_dist_list(test_scm_DIST
CMakeLists.txt
${scm_test_SCHEME}
)
# Define two imaginary deprecated guile modules to test the compat file generation code
gnc_add_scheme_deprecated_module ("gnucash deprecated-module" "" "" "")
gnc_add_scheme_deprecated_module ("gnucash superseded-module" "gnucash utilities" "scm-scm" "")

View File

@ -0,0 +1,12 @@
(use-modules (srfi srfi-64))
(use-modules (tests srfi64-extras))
(define (run-test)
(test-runner-factory gnc:test-runner)
(test-begin "test gnc-guile module deprecation")
(test-read-eval-string "(use-modules (gnucash deprecated-module))")
(test-end "test gnc-guile module deprecation")
(test-begin "test gnc-guile module deprecation with replacement module")
(test-read-eval-string "(begin (use-modules (gnucash superseded-module))(gnc:warn \"Successfully redirected to replacement module\"))")
(test-end "test gnc-guile module deprecation with replacement module"))