From: Bruno Haible Date: Wed, 9 Oct 2024 01:12:42 +0000 (+0200) Subject: csharpexec-script: Add support for dotnet. X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=36f4a649f52d1eeb1ff25aa43aa90faaf20897e8;p=gnulib.git csharpexec-script: Add support for dotnet. * m4/csharpexec.m4 (gt_CSHARPEXEC): Support 'dotnet' as implementation. Set HAVE_DOTNET. * build-aux/csharpexec.sh.in (func_tmpdir): New function, copied from build-aux/csharpcomp.sh.in. Add implementation for the case $HAVE_DOTNET = 1. --- diff --git a/ChangeLog b/ChangeLog index b1c83c199e..a1e92dd257 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2024-10-08 Bruno Haible + + csharpexec-script: Add support for dotnet. + * m4/csharpexec.m4 (gt_CSHARPEXEC): Support 'dotnet' as implementation. + Set HAVE_DOTNET. + * build-aux/csharpexec.sh.in (func_tmpdir): New function, copied from + build-aux/csharpcomp.sh.in. + Add implementation for the case $HAVE_DOTNET = 1. + 2024-10-08 Bruno Haible csharpexec-script, csharpcomp-script: Prepare support for dotnet. diff --git a/build-aux/csharpexec.sh.in b/build-aux/csharpexec.sh.in index 83d60ca870..45c95b4b5f 100644 --- a/build-aux/csharpexec.sh.in +++ b/build-aux/csharpexec.sh.in @@ -28,13 +28,46 @@ # Options: # -L DIRECTORY search for C# libraries also in DIRECTORY +# func_tmpdir +# creates a temporary directory. +# Sets variable +# - tmp pathname of freshly created temporary directory +func_tmpdir () +{ + # Use the environment variable TMPDIR, falling back to /tmp. This allows + # users to specify a different temporary directory, for example, if their + # /tmp is filled up or too small. + : "${TMPDIR=/tmp}" + { + # Use the mktemp program if available. If not available, hide the error + # message. + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/gtXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" + } || + { + # Use a simple mkdir command. It is guaranteed to fail if the directory + # already exists. $RANDOM is bash specific and expands to empty in shells + # other than bash, ksh and zsh. Its use does not increase security; + # rather, it minimizes the probability of failure in a very cluttered /tmp + # directory. + tmp=$TMPDIR/gt$$-$RANDOM + (umask 077 && mkdir "$tmp") + } || + { + echo "$0: cannot create a temporary directory in $TMPDIR" >&2 + { (exit 1); exit 1; } + } +} + sed_quote_subst='s/\([|&;<>()$`"'"'"'*?[#~=% \\]\)/\\\1/g' libdirs_mono= +libdirs_dotnet= prog= while test $# != 0; do case "$1" in -L) libdirs_mono="${libdirs_mono:+$libdirs_mono@MONO_PATH_SEPARATOR@}$2" + libdirs_dotnet="${libdirs_dotnet:+$libdirs_dotnet|}$2" shift ;; -*) @@ -71,26 +104,111 @@ if test -n "@HAVE_MONO@"; then test -z "$CSHARP_VERBOSE" || echo mono "$@" exec mono "$@" else - if test -n "@HAVE_CLIX@"; then - CONF_CLIX_PATH='@CLIX_PATH@' - if test -n "$libdirs_mono"; then - @CLIX_PATH_VAR@="$libdirs_mono${CONF_CLIX_PATH:+@MONO_PATH_SEPARATOR@$CONF_CLIX_PATH}" - else - @CLIX_PATH_VAR@="$CONF_CLIX_PATH" - fi - export @CLIX_PATH_VAR@ + if test -n "@HAVE_DOTNET@"; then + # Invoke 'dotnet $prog ...'. + # Documentation: + # + # This could be optimized on Windows platforms, because C# .exe files are + # directly executable there. But there's no point in optimizing specifically + # a non-free platform, especially since it would increase the test matrix. shift - # On Windows, assume that 'clix' is a native Windows program, - # not a Cygwin program. + # On Windows, assume that 'dotnet' is a native Windows program, not a Cygwin program. + prog_arg="$prog" case "@build_os@" in cygwin*) - prog=`cygpath -w "$prog"` + prog_arg=`cygpath -w "$prog"` ;; esac - test -z "$CSHARP_VERBOSE" || echo clix "$prog" "$@" - exec clix "$prog" "$@" + # Handle the -L options. + # The way this works is that we have to copy (or symlink) the DLLs into the + # directory where FOO.exe resides. + # Maybe there is another way to do this, but I haven't found it, trying + # - the --additionalprobingpath command-line option, + # - the additionalProbingPaths property in runtimeconfig.json, + # - adding a --deps deps.json option, + # cf. + # and . + tmpfiles= + if test -n "$libdirs_dotnet"; then + # Make sure the added DLLs are removed when this script terminates. + func_cleanup_tmpfiles() + { + saved_IFS="$IFS" + IFS='|' + for file in $tmpfiles; do + IFS="$saved_IFS" + rm -f "$file" + done + IFS="$saved_IFS" + } + trap func_cleanup_tmpfiles HUP INT QUIT PIPE TERM + trap 'exit_status=$?; func_cleanup_tmpfiles; exit $exit_status' EXIT + # Copy the DLLs. + prog_dir=`dirname "$prog"` + saved_IFS="$IFS" + IFS='|' + for dir in $libdirs_dotnet; do + IFS="$saved_IFS" + for file in `cd "$dir" && echo *.dll`; do + if test -f "$prog_dir/$file"; then + # A DLL of this name is already at the expected location. + : + else + tmpfiles="${tmpfiles:+$tmpfiles|}$prog_dir/$file" + cp "$dir/$file" "$prog_dir/$file" || exit 1 + fi + done + done + IFS="$saved_IFS" + fi + if test -f "${prog%.exe}.runtimeconfig.json"; then + # There is already a FOO.runtimeconfig.json alongside FOO.exe. + dotnet exec "$prog_arg" "$@" + result=$? + else + # dotnet needs a FOO.runtimeconfig.json alongside FOO.exe in order to + # execute FOO.exe. Create a dummy one in a temporary directory + # (because the directory where FOO.exe sits is not necessarily writable). + # Documentation of this file format: + # + func_tmpdir + runtimeconfig="$tmp"/runtimeconfig.json + dotnet --list-runtimes | sed -n -e 's/Microsoft.NETCore.App \([^ ]*\) .*/{ "runtimeOptions": { "framework": { "name": "Microsoft.NETCore.App", "version": "\1" } } }/p' > "$runtimeconfig" + runtimeconfig_arg="$runtimeconfig" + case "@build_os@" in + cygwin*) + runtimeconfig_arg=`cygpath -w "$runtimeconfig"` + ;; + esac + test -z "$CSHARP_VERBOSE" || echo dotnet exec --runtimeconfig "$runtimeconfig_arg" "$prog_arg" "$@" + dotnet exec --runtimeconfig "$runtimeconfig_arg" "$prog_arg" "$@" + result=$? + rm -f "$runtimeconfig" + rmdir "$tmp" + fi + exit $result else - echo 'C# virtual machine not found, try installing mono, then reconfigure' 1>&2 - exit 1 + if test -n "@HAVE_CLIX@"; then + CONF_CLIX_PATH='@CLIX_PATH@' + if test -n "$libdirs_mono"; then + @CLIX_PATH_VAR@="$libdirs_mono${CONF_CLIX_PATH:+@MONO_PATH_SEPARATOR@$CONF_CLIX_PATH}" + else + @CLIX_PATH_VAR@="$CONF_CLIX_PATH" + fi + export @CLIX_PATH_VAR@ + shift + # On Windows, assume that 'clix' is a native Windows program, + # not a Cygwin program. + case "@build_os@" in + cygwin*) + prog=`cygpath -w "$prog"` + ;; + esac + test -z "$CSHARP_VERBOSE" || echo clix "$prog" "$@" + exec clix "$prog" "$@" + else + echo 'C# virtual machine not found, try installing mono or dotnet, then reconfigure' 1>&2 + exit 1 + fi fi fi diff --git a/m4/csharpexec.m4 b/m4/csharpexec.m4 index 079c5723fd..5d7a0e8899 100644 --- a/m4/csharpexec.m4 +++ b/m4/csharpexec.m4 @@ -1,4 +1,4 @@ -# csharpexec.m4 serial 9 +# csharpexec.m4 serial 10 dnl Copyright (C) 2003-2005, 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -7,7 +7,7 @@ dnl with or without modifications, as long as this notice is preserved. # Prerequisites of csharpexec.sh. # Checks for a C# execution engine. # gt_CSHARPEXEC or gt_CSHARPEXEC(testexecutable, its-directory) -# Sets at most one of HAVE_MONO, HAVE_CLIX. +# Sets at most one of HAVE_MONO, HAVE_DOTNET, HAVE_CLIX. # Sets HAVE_CSHARPEXEC to nonempty if csharpexec.sh will work. AC_DEFUN([gt_CSHARPEXEC], [ @@ -24,11 +24,12 @@ AC_DEFUN([gt_CSHARPEXEC], pushdef([AC_CHECKING],[:])dnl pushdef([AC_MSG_RESULT],[:])dnl AC_CHECK_PROG([HAVE_MONO_IN_PATH], [mono], [yes]) + AC_CHECK_PROG([HAVE_DOTNET_IN_PATH], [dotnet], [yes]) AC_CHECK_PROG([HAVE_CLIX_IN_PATH], [clix], [yes]) popdef([AC_MSG_RESULT])dnl popdef([AC_CHECKING])dnl popdef([AC_MSG_CHECKING])dnl - for impl in "$CSHARP_CHOICE" mono no; do + for impl in "$CSHARP_CHOICE" mono dotnet no; do case "$impl" in mono) if test -n "$HAVE_MONO_IN_PATH" \ @@ -39,6 +40,14 @@ AC_DEFUN([gt_CSHARPEXEC], break fi ;; + dotnet) + if test -n "$HAVE_DOTNET_IN_PATH" \ + && dotnet --list-runtimes >/dev/null 2>/dev/null; then + HAVE_DOTNET=1 + ac_result="dotnet" + break + fi + ;; sscli) if test -n "$HAVE_CLIX_IN_PATH" \ m4_if([$1], , , [&& clix $2/$1 >/dev/null 2>/dev/null]); then @@ -72,5 +81,6 @@ AC_DEFUN([gt_CSHARPEXEC], AC_SUBST([CLIX_PATH_VAR]) AC_SUBST([CLIX_PATH]) AC_SUBST([HAVE_MONO]) + AC_SUBST([HAVE_DOTNET]) AC_SUBST([HAVE_CLIX]) ])