There were no comments on csharpexec, no I committed this module. Here comes the module for compiling a C# program.
============================= modules/csharpcomp ============================= Description: Compile a C# program. Files: lib/csharpcomp.h lib/csharpcomp.c lib/csharpcomp.sh.in m4/csharpcomp.m4 m4/csharp.m4 Depends-on: stdbool xallocsa execute pipe wait-process getline sh-quote safe-read error gettext configure.ac: gt_CSHARPCOMP Makefile.am: lib_SOURCES += csharpcomp.h csharpcomp.c EXTRA_DIST += csharpcomp.sh.in Include: "csharpcomp.h" License: GPL Maintainer: Bruno Haible ============================ lib/csharpcomp.sh.in ============================ #!/bin/sh # Compile a C# program. # Copyright (C) 2003-2005 Free Software Foundation, Inc. # Written by Bruno Haible <[EMAIL PROTECTED]>, 2003. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # This uses the same choices as csharpcomp.c, but instead of relying on the # environment settings at run time, it uses the environment variables # present at configuration time. # # This is a separate shell script, because the various C# compilers have # different command line options. # # Usage: /bin/sh csharpcomp.sh [OPTION] SOURCE.cs ... RES.resource ... # Options: # -o PROGRAM.exe or -o LIBRARY.dll # set the output assembly name # -L DIRECTORY search for C# libraries also in DIRECTORY # -l LIBRARY reference the C# library LIBRARY.dll # -O optimize # -g generate debugging information # 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' options_cscc= options_mcs= options_csc="-nologo" sources= while test $# != 0; do case "$1" in -o) case "$2" in *.dll) options_cscc="$options_cscc -shared" options_mcs="$options_mcs -target:library" options_csc="$options_csc -target:library" ;; *.exe) options_csc="$options_csc -target:exe" ;; esac options_cscc="$options_cscc -o "`echo "$2" | sed -e "$sed_quote_subst"` options_mcs="$options_mcs -o "`echo "$2" | sed -e "$sed_quote_subst"` options_csc="$options_csc -out:"`echo "$2" | sed -e "$sed_quote_subst"` shift ;; -L) options_cscc="$options_cscc -L "`echo "$2" | sed -e "$sed_quote_subst"` options_mcs="$options_mcs -L "`echo "$2" | sed -e "$sed_quote_subst"` options_csc="$options_csc -lib:"`echo "$2" | sed -e "$sed_quote_subst"` shift ;; -l) options_cscc="$options_cscc -l "`echo "$2" | sed -e "$sed_quote_subst"` options_mcs="$options_mcs -r "`echo "$2" | sed -e "$sed_quote_subst"` options_csc="$options_csc -reference:"`echo "$2" | sed -e "$sed_quote_subst"` shift ;; -O) options_cscc="$options_cscc -O" options_csc="$options_csc -optimize+" ;; -g) options_cscc="$options_cscc -g" options_mcs="$options_mcs -g" options_csc="$options_csc -debug+" ;; -*) echo "csharpcomp: unknown option '$1'" 1>&2 exit 1 ;; *.resource) options_cscc="$options_cscc -fresources="`echo "$1" | sed -e "$sed_quote_subst"` options_mcs="$options_mcs -resource:"`echo "$1" | sed -e "$sed_quote_subst"` options_csc="$options_csc -resource:"`echo "$1" | sed -e "$sed_quote_subst"` ;; *.cs) sources="$sources "`echo "$1" | sed -e "$sed_quote_subst"` ;; *) echo "csharpcomp: unknown type of argument '$1'" 1>&2 exit 1 ;; esac shift done if test -n "@HAVE_CSCC@"; then test -z "$CSHARP_VERBOSE" || echo cscc $options_cscc $sources exec cscc $options_cscc $sources else if test -n "@HAVE_MCS@"; then # mcs prints it errors and warnings to stdout, not stderr. Furthermore it # adds a useless line "Compilation succeeded..." at the end. Correct both. sed_drop_success_line='${ /^Compilation succeeded/d }' func_tmpdir trap 'rm -rf "$tmp"' 1 2 3 15 test -z "$CSHARP_VERBOSE" || echo mcs $options_mcs $sources mcs $options_mcs $sources > "$tmp"/mcs.err result=$? sed -e "$sed_drop_success_line" < "$tmp"/mcs.err >&2 rm -rf "$tmp" exit $result else if test -n "@HAVE_CSC@"; then test -z "$CSHARP_VERBOSE" || echo csc $options_csc $sources exec csc $options_csc $sources else echo 'C# compiler not found, try installing pnet, then reconfigure' 1>&2 exit 1 fi fi fi ============================== lib/csharpcomp.h ============================== /* Compile a C# program. Copyright (C) 2003 Free Software Foundation, Inc. Written by Bruno Haible <[EMAIL PROTECTED]>, 2003. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _CSHARPCOMP_H #define _CSHARPCOMP_H #include <stdbool.h> /* Compile a set of C# source files to bytecode. sources is an array of source file names, including resource files. libdirs is a list of directories to be searched for libraries. libraries is a list of libraries on which the program depends. output_file is the name of the output file; it should end in .exe or .dll. If verbose, the command to be executed will be printed. Return false if OK, true on error. */ extern bool compile_csharp_class (const char * const *sources, unsigned int sources_count, const char * const *libdirs, unsigned int libdirs_count, const char * const *libraries, unsigned int libraries_count, const char *output_file, bool optimize, bool debug, bool verbose); #endif /* _CSHARPCOMP_H */ ============================== lib/csharpcomp.c ============================== /* Compile a C# program. Copyright (C) 2003-2005 Free Software Foundation, Inc. Written by Bruno Haible <[EMAIL PROTECTED]>, 2003. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <alloca.h> /* Specification. */ #include "csharpcomp.h" #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "execute.h" #include "pipe.h" #include "wait-process.h" #include "getline.h" #include "sh-quote.h" #include "safe-read.h" #include "xallocsa.h" #include "error.h" #include "gettext.h" #define _(str) gettext (str) /* Survey of C# compilers. Program from cscc pnet mcs mono csc sscli We try the CIL interpreters in the following order: 1. "cscc", because it is a completely free system. 2. "mcs", because it is a free system but doesn't integrate so well with Unix. (Command line options start with / instead of -. Errors go to stdout instead of stderr. Source references are printed as "file(lineno)" instead of "file:lineno:".) 3. "csc", although it is not free, because it is a kind of "reference implementation" of C#. But the order can be changed through the --enable-csharp configuration option. */ static int compile_csharp_using_pnet (const char * const *sources, unsigned int sources_count, const char * const *libdirs, unsigned int libdirs_count, const char * const *libraries, unsigned int libraries_count, const char *output_file, bool output_is_library, bool optimize, bool debug, bool verbose) { static bool cscc_tested; static bool cscc_present; if (!cscc_tested) { /* Test for presence of cscc: "cscc --version >/dev/null 2>/dev/null" */ char *argv[3]; int exitstatus; argv[0] = "cscc"; argv[1] = "--version"; argv[2] = NULL; exitstatus = execute ("cscc", "cscc", argv, false, false, true, true, true, false); cscc_present = (exitstatus == 0); cscc_tested = true; } if (cscc_present) { unsigned int argc; char **argv; char **argp; int exitstatus; unsigned int i; argc = 1 + (output_is_library ? 1 : 0) + 2 + 2 * libdirs_count + 2 * libraries_count + (optimize ? 1 : 0) + (debug ? 1 : 0) + sources_count; argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); argp = argv; *argp++ = "cscc"; if (output_is_library) *argp++ = "-shared"; *argp++ = "-o"; *argp++ = (char *) output_file; for (i = 0; i < libdirs_count; i++) { *argp++ = "-L"; *argp++ = (char *) libdirs[i]; } for (i = 0; i < libraries_count; i++) { *argp++ = "-l"; *argp++ = (char *) libraries[i]; } if (optimize) *argp++ = "-O"; if (debug) *argp++ = "-g"; for (i = 0; i < sources_count; i++) { const char *source_file = sources[i]; if (strlen (source_file) >= 9 && memcmp (source_file + strlen (source_file) - 9, ".resource", 9) == 0) { char *option = (char *) xallocsa (12 + strlen (source_file) + 1); memcpy (option, "-fresources=", 12); strcpy (option + 12, source_file); *argp++ = option; } else *argp++ = (char *) source_file; } *argp = NULL; /* Ensure argv length was correctly calculated. */ if (argp - argv != argc) abort (); if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } exitstatus = execute ("cscc", "cscc", argv, false, false, false, false, true, true); for (i = 0; i < sources_count; i++) if (argv[argc - sources_count + i] != sources[i]) freesa (argv[argc - sources_count + i]); freesa (argv); return (exitstatus != 0); } else return -1; } static int compile_csharp_using_mono (const char * const *sources, unsigned int sources_count, const char * const *libdirs, unsigned int libdirs_count, const char * const *libraries, unsigned int libraries_count, const char *output_file, bool output_is_library, bool optimize, bool debug, bool verbose) { static bool mcs_tested; static bool mcs_present; if (!mcs_tested) { /* Test for presence of mcs: "mcs --version >/dev/null 2>/dev/null" */ char *argv[3]; int exitstatus; argv[0] = "mcs"; argv[1] = "--version"; argv[2] = NULL; exitstatus = execute ("mcs", "mcs", argv, false, false, true, true, true, false); mcs_present = (exitstatus == 0); mcs_tested = true; } if (mcs_present) { unsigned int argc; char **argv; char **argp; pid_t child; int fd[1]; FILE *fp; char *line[2]; size_t linesize[2]; size_t linelen[2]; unsigned int l; int exitstatus; unsigned int i; argc = 1 + (output_is_library ? 1 : 0) + 2 + 2 * libdirs_count + 2 * libraries_count + (debug ? 1 : 0) + sources_count; argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); argp = argv; *argp++ = "mcs"; if (output_is_library) *argp++ = "-target:library"; *argp++ = "-o"; *argp++ = (char *) output_file; for (i = 0; i < libdirs_count; i++) { *argp++ = "-L"; *argp++ = (char *) libdirs[i]; } for (i = 0; i < libraries_count; i++) { *argp++ = "-r"; *argp++ = (char *) libraries[i]; } if (debug) *argp++ = "-g"; for (i = 0; i < sources_count; i++) { const char *source_file = sources[i]; if (strlen (source_file) >= 9 && memcmp (source_file + strlen (source_file) - 9, ".resource", 9) == 0) { char *option = (char *) xallocsa (10 + strlen (source_file) + 1); memcpy (option, "-resource:", 10); strcpy (option + 10, source_file); *argp++ = option; } else *argp++ = (char *) source_file; } *argp = NULL; /* Ensure argv length was correctly calculated. */ if (argp - argv != argc) abort (); if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } child = create_pipe_in ("mcs", "mcs", argv, NULL, false, true, true, fd); /* Read the subprocess output, copying it to stderr. Drop the last line if it starts with "Compilation succeeded". */ fp = fdopen (fd[0], "r"); if (fp == NULL) error (EXIT_FAILURE, errno, _("fdopen() failed")); line[0] = NULL; linesize[0] = 0; line[1] = NULL; linesize[1] = 0; l = 0; for (;;) { linelen[l] = getline (&line[l], &linesize[l], fp); if (linelen[l] == (size_t)(-1)) break; l = (l + 1) % 2; if (line[l] != NULL) fwrite (line[l], 1, linelen[l], stderr); } l = (l + 1) % 2; if (line[l] != NULL && !(linelen[l] >= 21 && memcmp (line[l], "Compilation succeeded", 21) == 0)) fwrite (line[l], 1, linelen[l], stderr); if (line[0] != NULL) free (line[0]); if (line[1] != NULL) free (line[1]); fclose (fp); /* Remove zombie process from process list, and retrieve exit status. */ exitstatus = wait_subprocess (child, "mcs", false, false, true, true); for (i = 0; i < sources_count; i++) if (argv[argc - sources_count + i] != sources[i]) freesa (argv[argc - sources_count + i]); freesa (argv); return (exitstatus != 0); } else return -1; } static int compile_csharp_using_sscli (const char * const *sources, unsigned int sources_count, const char * const *libdirs, unsigned int libdirs_count, const char * const *libraries, unsigned int libraries_count, const char *output_file, bool output_is_library, bool optimize, bool debug, bool verbose) { static bool csc_tested; static bool csc_present; if (!csc_tested) { /* Test for presence of csc: "csc -help >/dev/null 2>/dev/null \ && ! { csc -help 2>/dev/null | grep -i chicken > /dev/null; }" */ char *argv[3]; pid_t child; int fd[1]; int exitstatus; argv[0] = "csc"; argv[1] = "-help"; argv[2] = NULL; child = create_pipe_in ("csc", "csc", argv, DEV_NULL, true, true, false, fd); csc_present = false; if (child != -1) { /* Read the subprocess output, and test whether it contains the string "chicken". */ char c[7]; size_t count = 0; csc_present = true; while (safe_read (fd[0], &c[count], 1) > 0) { if (c[count] >= 'A' && c[count] <= 'Z') c[count] += 'a' - 'A'; count++; if (count == 7) { if (memcmp (c, "chicken", 7) == 0) csc_present = false; c[0] = c[1]; c[1] = c[2]; c[2] = c[3]; c[3] = c[4]; c[4] = c[5]; c[5] = c[6]; count--; } } close (fd[0]); /* Remove zombie process from process list, and retrieve exit status. */ exitstatus = wait_subprocess (child, "csc", false, true, true, false); if (exitstatus != 0) csc_present = false; } csc_tested = true; } if (csc_present) { unsigned int argc; char **argv; char **argp; int exitstatus; unsigned int i; argc = 1 + 1 + 1 + libdirs_count + libraries_count + (optimize ? 1 : 0) + (debug ? 1 : 0) + sources_count; argv = (char **) xallocsa ((argc + 1) * sizeof (char *)); argp = argv; *argp++ = "csc"; *argp++ = (output_is_library ? "-target:library" : "-target:exe"); { char *option = (char *) xallocsa (5 + strlen (output_file) + 1); memcpy (option, "-out:", 5); strcpy (option + 5, output_file); *argp++ = option; } for (i = 0; i < libdirs_count; i++) { char *option = (char *) xallocsa (5 + strlen (libdirs[i]) + 1); memcpy (option, "-lib:", 5); strcpy (option + 5, libdirs[i]); *argp++ = option; } for (i = 0; i < libraries_count; i++) { char *option = (char *) xallocsa (11 + strlen (libraries[i]) + 1); memcpy (option, "-reference:", 11); strcpy (option + 11, libraries[i]); *argp++ = option; } if (optimize) *argp++ = "-optimize+"; if (debug) *argp++ = "-debug+"; for (i = 0; i < sources_count; i++) { const char *source_file = sources[i]; if (strlen (source_file) >= 9 && memcmp (source_file + strlen (source_file) - 9, ".resource", 9) == 0) { char *option = (char *) xallocsa (10 + strlen (source_file) + 1); memcpy (option, "-resource:", 10); strcpy (option + 10, source_file); *argp++ = option; } else *argp++ = (char *) source_file; } *argp = NULL; /* Ensure argv length was correctly calculated. */ if (argp - argv != argc) abort (); if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } exitstatus = execute ("csc", "csc", argv, false, false, false, false, true, true); for (i = 2; i < 3 + libdirs_count + libraries_count; i++) freesa (argv[i]); for (i = 0; i < sources_count; i++) if (argv[argc - sources_count + i] != sources[i]) freesa (argv[argc - sources_count + i]); freesa (argv); return (exitstatus != 0); } else return -1; } bool compile_csharp_class (const char * const *sources, unsigned int sources_count, const char * const *libdirs, unsigned int libdirs_count, const char * const *libraries, unsigned int libraries_count, const char *output_file, bool optimize, bool debug, bool verbose) { bool output_is_library = (strlen (output_file) >= 4 && memcmp (output_file + strlen (output_file) - 4, ".dll", 4) == 0); int result; /* First try the C# implementation specified through --enable-csharp. */ #if CSHARP_CHOICE_PNET result = compile_csharp_using_pnet (sources, sources_count, libdirs, libdirs_count, libraries, libraries_count, output_file, output_is_library, optimize, debug, verbose); if (result >= 0) return (bool) result; #endif #if CSHARP_CHOICE_MONO result = compile_csharp_using_mono (sources, sources_count, libdirs, libdirs_count, libraries, libraries_count, output_file, output_is_library, optimize, debug, verbose); if (result >= 0) return (bool) result; #endif /* Then try the remaining C# implementations in our standard order. */ #if !CSHARP_CHOICE_PNET result = compile_csharp_using_pnet (sources, sources_count, libdirs, libdirs_count, libraries, libraries_count, output_file, output_is_library, optimize, debug, verbose); if (result >= 0) return (bool) result; #endif #if !CSHARP_CHOICE_MONO result = compile_csharp_using_mono (sources, sources_count, libdirs, libdirs_count, libraries, libraries_count, output_file, output_is_library, optimize, debug, verbose); if (result >= 0) return (bool) result; #endif result = compile_csharp_using_sscli (sources, sources_count, libdirs, libdirs_count, libraries, libraries_count, output_file, output_is_library, optimize, debug, verbose); if (result >= 0) return (bool) result; error (0, 0, _("C# compiler not found, try installing pnet")); return true; } ============================== m4/csharpcomp.m4 ============================== # csharpcomp.m4 serial 5 (gettext-0.15) dnl Copyright (C) 2003-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # Prerequisites of csharpcomp.sh. # Sets HAVE_CSHARPCOMP to nonempty if csharpcomp.sh will work. AC_DEFUN([gt_CSHARPCOMP], [ AC_REQUIRE([gt_CSHARP_CHOICE]) AC_MSG_CHECKING([for C[#] compiler]) HAVE_CSHARPCOMP=1 pushdef([AC_MSG_CHECKING],[:])dnl pushdef([AC_CHECKING],[:])dnl pushdef([AC_MSG_RESULT],[:])dnl AC_CHECK_PROG(HAVE_CSCC_IN_PATH, cscc, yes) AC_CHECK_PROG(HAVE_MCS_IN_PATH, mcs, yes) AC_CHECK_PROG(HAVE_CSC_IN_PATH, csc, yes) popdef([AC_MSG_RESULT])dnl popdef([AC_CHECKING])dnl popdef([AC_MSG_CHECKING])dnl for impl in "$CSHARP_CHOICE" pnet mono sscli no; do case "$impl" in pnet) if test -n "$HAVE_CSCC_IN_PATH" \ && cscc --version >/dev/null 2>/dev/null \ && ( # See if pnetlib is well installed. echo 'class ConfTest { static void Main() { } }' > conftest.cs cscc -o conftest.exe conftest.cs 2>/dev/null error=$? rm -f conftest.cs conftest.exe exit $error ); then HAVE_CSCC=1 ac_result="cscc" break fi ;; mono) if test -n "$HAVE_MCS_IN_PATH" \ && mcs --version >/dev/null 2>/dev/null; then HAVE_MCS=1 ac_result="mcs" break fi ;; sscli) if test -n "$HAVE_CSC_IN_PATH" \ && csc -help >/dev/null 2>/dev/null \ && { if csc -help 2>/dev/null | grep -i chicken > /dev/null; then false; else true; fi; }; then HAVE_CSC=1 ac_result="csc" break fi ;; no) HAVE_CSHARPCOMP= ac_result="no" break ;; esac done AC_MSG_RESULT([$ac_result]) AC_SUBST(HAVE_CSCC) AC_SUBST(HAVE_MCS) AC_SUBST(HAVE_CSC) ]) ============================================================================== _______________________________________________ bug-gnulib mailing list bug-gnulib@gnu.org http://lists.gnu.org/mailman/listinfo/bug-gnulib