diff --git a/bin/dune b/bin/dune index fcb02ca1875c5cb8ee96640a75302a745c1f3261..7e3bb9f33bdda4cb426fda2c8128a406b985c95b 100644 --- a/bin/dune +++ b/bin/dune @@ -27,5 +27,6 @@ (frama-c-script as frama-c-script) (frama-c-config as frama-c-config) (test.sh as frama-c-test.sh) + (frama-c-build-scripts.sh as frama-c-build-scripts.sh) ) ) diff --git a/bin/frama-c-build-scripts.sh b/bin/frama-c-build-scripts.sh new file mode 100755 index 0000000000000000000000000000000000000000..d0698b6bf81350bf0bdde2431dbe4446e2a54f6e --- /dev/null +++ b/bin/frama-c-build-scripts.sh @@ -0,0 +1,194 @@ +#!/bin/bash +########################################################################## +# # +# This file is part of Frama-C. # +# # +# Copyright (C) 2007-2022 # +# CEA (Commissariat à l'énergie atomique et aux énergies # +# alternatives) # +# # +# you can redistribute it and/or modify it under the terms of the GNU # +# Lesser General Public License as published by the Free Software # +# Foundation, version 2.1. # +# # +# It is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Lesser General Public License for more details. # +# # +# See the GNU Lesser General Public License version 2.1 # +# for more details (enclosed in the file licenses/LGPLv2.1). # +# # +########################################################################## + +PACKAGE="frama-c-scripts" + +CMD="init" + +THIS_SCRIPT="$0" +Usage () { + echo "Usage: $(basename ${THIS_SCRIPT}) [<command>] [options] <script-dir> [<modules>]" + echo " Build a script library to be used by Frama-C kernel." + echo "" + echo "Commands:" + echo "- init: generates dune files (default command)" + echo "- build: performs the compilation of the script libraries via \"dune build @install\"" + echo "- install: performs the installation of the script libraries via \"dune install\"" + echo "" + echo "Options:" + echo " -help: prints usage information" + echo " -package-name <name>: set the <name> of the package of the libraries (defaults to \"${PACKAGE}\")." + echo " note: once the dune-project file has been created, don't set another name." + echo "" + echo "Arguments:" + echo " <script-dir>: directory that contents the script files:" + echo " - the basename of this directory fixes the name of the script library: ${PACKAGE}.<basename>" + echo " - a 'dune' file is created (if it does not exists before) into this directory" + echo " - a 'dune-project' file is created (if it does not exists before) into the parent directory" + echo " - note: the parent directory is './' when the script directory is also './'" + echo " <modules>: names of the OCaml modules that compose the script (default to all OCaml modules of the script directory)" +} + +Error () { + echo "Error: $@" + Usage + exit 1 +} + +############### +# Command line processing + +case "$1" in + "init"|"build"|"install") CMD="$1"; shift;; + *) ;; +esac + +while [ "$1" != "" ]; do + case "$1" in + "-package-name") shift ; PACKAGE="$1";; + "-h"|"-help"|"--help") Usage; exit 0;; + *) break ;; + esac + shift +done + +[ "$PACKAGE" != "" ] || Error "Missing option value: no package name" +[ "$1" != "" ] || Error "Missing argument: no script directory" + +SCRIPT_DIR="$1" +shift +SCRIPT_FILES="$@" +SCRIPT_LIBS="" + +[ -d "${SCRIPT_DIR}" ] || Error "Missing script directory: ${SCRIPT_DIR})" + +############### + +DuneProject () { + echo "(lang dune 3.0)" + echo "(generate_opam_files true)" + echo "(name ${PACKAGE})" + echo "(maintainers \"anonymous\")" + echo "(package (name ${PACKAGE})" + echo " (depends" + echo " (\"frama-c\" (>= 26.0))" + echo " )" + echo " (tags (\"Frama-C scripts\"))" + echo ")" +} + +Dune () { + echo "(rule" + echo " (alias ${PACKAGE})" + echo " (deps (universe))" + echo " (action (echo \"- Script ${SCRIPT_NAME}:\" %{lib-available:${PACKAGE}.${SCRIPT_NAME}} \"\\\\n\"))" + echo ")" + echo "" + echo "(library" + echo " (name ${SCRIPT_NAME})" + echo " (optional)" + echo " (public_name ${PACKAGE}.${SCRIPT_NAME})" + [ "${SCRIPT_FILES}" = "" ] || echo " (modules ${SCRIPT_FILES})" + echo " (flags -open Frama_c_kernel :standard -w -9)" + echo " (libraries frama-c.kernel ${SCRIPT_LIBS})" + echo ")" +} + +############### + +GenerateFile () { + if [ -e "$2" ]; then + echo "$1 file exists already: $2" + else + echo "- Creating $1 file: $2" + $1 | while read p; do + echo "$p" >> "$2" + done + fi +} + +############### + +SCRIPT_NAME="$(basename "${SCRIPT_DIR}")" +DUNE_PROJECT_DIR="$(dirname "${SCRIPT_DIR}")" +DUNE_PROJECT="${DUNE_PROJECT_DIR}/dune-project" +case "${SCRIPT_DIR}" in + */) DUNE_FILE="${SCRIPT_DIR}dune" ;; + *) DUNE_FILE="${SCRIPT_DIR}/dune" ;; +esac + +############### + +EchoDuneCmd() { + if [ "${DUNE_PROJECT_DIR}" = "." ]; then + echo " > $@" + else + echo " > (cd ${DUNE_PROJECT_DIR} && $@)" + fi +} + +DuneBuild() { + echo "" + echo "- Compiling the script library \"${PACKAGE}.${SCRIPT_NAME}\" via \"dune build @install\" command..." + dune build @install + [ "$?" = "0" ] || Error "the compilation fails!" +} + +DuneInstall() { + echo "" + echo "- Install the script library \"${PACKAGE}.${SCRIPT_NAME}\" via \"dune install\" command..." + dune install +} + +############### + +[ "$(basename "${DUNE_FILE}")" = "dune" ] || Error "Wrong basename for a dune file: ${DUNE_FILE}" +[ "$(basename "${DUNE_PROJECT}")" = "dune-project" ] || Error "Wrong basename for a dune-project file: ${DUNE_PROJECT}" + +GenerateFile DuneProject "${DUNE_PROJECT}" +GenerateFile Dune "${DUNE_FILE}" + +if [ "$CMD" = "init" ]; then + echo "" + echo "To compile the all scripts defined inside this 'dune project' \"${PACKAGE}\", runs the following command:" + EchoDuneCmd "dune build @install" +else + DuneBuild +fi +echo "" +echo "So, the script libraries, are compiled and installed into the local '_build' directory." +echo "That also create or update the 'opam' file \"${PACKAGE}.opam\" allowing a global installation of all script libraries." +echo "" +echo "To load this script library from Frama-C, runs the following command:" +EchoDuneCmd "dune exec -- frama-c -load-library ${PACKAGE}.${SCRIPT_NAME} ..." + +if [ "$CMD" = "install" ]; then + DuneInstall +else + echo "" + echo "All libraries of this 'dune project' \"${PACKAGE}\" can also be installed via 'dune' using from the generated 'opam' file: \"${PACKAGE}.opam\"" + EchoDuneCmd "dune install" +fi +echo "" +echo "Then, this script library can directly be loaded by Frama-C from the following command:" +echo " > frama-c -load-library ${PACKAGE}.${SCRIPT_NAME} ..." diff --git a/src/kernel_services/plugin_entry_points/dynamic.ml b/src/kernel_services/plugin_entry_points/dynamic.ml index faf704b58d7f19724efc38cd906013b9ebefb140..a57e0d3ed55d8bf6a0b5e6723a1478d09ae32319 100644 --- a/src/kernel_services/plugin_entry_points/dynamic.ml +++ b/src/kernel_services/plugin_entry_points/dynamic.ml @@ -133,7 +133,7 @@ let load_module m = let base,ext = split_ext m in match ext with | ".ml" -> - Klog.error "Script loading as been deprecated in favor of the command frama-c-init-plugin" + Klog.error "Script loading as been deprecated in favor of the load of script libraries (see shell script `frama-c-build-scripts.sh` to build such a script library that can be loaded via the Frama-C option `-load-library`)." | _ -> begin (* load object or compile script or find package *) diff --git a/src/kernel_services/plugin_entry_points/kernel.ml b/src/kernel_services/plugin_entry_points/kernel.ml index b78902d70ec4d0111ba1d7dcf03900a09e8fef4b..a45fb58818fb1880d2fffdf7e4db4fe74d6b460c 100644 --- a/src/kernel_services/plugin_entry_points/kernel.ml +++ b/src/kernel_services/plugin_entry_points/kernel.ml @@ -868,11 +868,23 @@ module LoadModule = let option_name = "-load-module" let module_name = "LoadModule" let arg_name = "SPEC,..." - let help = "Dynamically load modules and scripts. \ - Each <SPEC> can be an OCaml source or object file, with \ + let help = "Dynamically load modules. \ + Each <SPEC> can be object file, with \ or without extension, or a Findlib package. \ - Loading order is preserved and \ - additional dependencies can be listed in *.depend files." + Loading order is preserved, but after plugins and libraries." + end) + +let () = Parameter_customize.set_group saveload +let () = Parameter_customize.set_cmdline_stage Cmdline.Extending +let () = Parameter_customize.do_not_projectify () +module LoadLibrary = + String_list + (struct + let option_name = "-load-library" + let module_name = "LoadLibrary" + let arg_name = "<libname,..." + let help = "Dynamically load libraries. \ + Loading order is preserved, but the load is done between the plugins and the modules." end) let () = Parameter_customize.set_group saveload @@ -903,6 +915,7 @@ let bootstrap_loader () = begin if AutoLoadPlugins.get () then Dynamic.load_plugin_path () ; List.iter Dynamic.load_plugin (LoadPlugin.get()) ; + Dynamic.load_packages (LoadLibrary.get()) ; List.iter Dynamic.load_module (LoadModule.get()) ; end diff --git a/src/kernel_services/plugin_entry_points/kernel.mli b/src/kernel_services/plugin_entry_points/kernel.mli index fbf977acbe0b2309ae4df4f109cff9273b77a780..4937534d6ea3de301c5c750b460441872f34ec98 100644 --- a/src/kernel_services/plugin_entry_points/kernel.mli +++ b/src/kernel_services/plugin_entry_points/kernel.mli @@ -372,6 +372,11 @@ module LoadState: Parameter_sig.Filepath module LoadModule: Parameter_sig.String_list (** Behavior of option "-load-module" *) +module LoadLibrary: Parameter_sig.String_list +(** Behavior of option "-load-library" + @since Frama-C+dev +*) + module AutoLoadPlugins: Parameter_sig.Bool (** Behavior of option "-autoload-plugins" *)