]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Compiling C# programs in a portable way.
authorBruno Haible <bruno@clisp.org>
Thu, 8 Jan 2004 11:45:41 +0000 (11:45 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:11:34 +0000 (12:11 +0200)
gettext-tools/lib/csharpcomp.c [new file with mode: 0644]
gettext-tools/lib/csharpcomp.h [new file with mode: 0644]
gettext-tools/lib/csharpcomp.sh.in [new file with mode: 0644]
gettext-tools/m4/csharpcomp.m4 [new file with mode: 0644]

diff --git a/gettext-tools/lib/csharpcomp.c b/gettext-tools/lib/csharpcomp.c
new file mode 100644 (file)
index 0000000..560d7c2
--- /dev/null
@@ -0,0 +1,363 @@
+/* Compile a C# program.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <alloca.h>
+
+/* Specification.  */
+#include "csharpcomp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "execute.h"
+#include "sh-quote.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 partially free system but doesn't integrate
+        well with Unix.
+     3. "csc", although it is not free, because it is a kind of "reference
+        implementation" of C#.
+ */
+
+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);
+
+  {
+    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);
+      }
+  }
+
+  {
+    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;
+       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);
+         }
+
+       exitstatus = execute ("mcs", "mcs", 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);
+      }
+  }
+
+  {
+    static bool csc_tested;
+    static bool csc_present;
+
+    if (!csc_tested)
+      {
+       /* Test for presence of csc:
+          "csc -help >/dev/null 2>/dev/null"  */
+       char *argv[3];
+       int exitstatus;
+
+       argv[0] = "csc";
+       argv[1] = "-help";
+       argv[2] = NULL;
+       exitstatus = execute ("csc", "csc", argv, false, false, true, true,
+                             true, false);
+       csc_present = (exitstatus == 0);
+       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);
+      }
+  }
+
+  error (0, 0, _("'C# compiler not found, try installing pnet"));
+  return true;
+}
diff --git a/gettext-tools/lib/csharpcomp.h b/gettext-tools/lib/csharpcomp.h
new file mode 100644 (file)
index 0000000..b209b3c
--- /dev/null
@@ -0,0 +1,41 @@
+/* Compile a C# program.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */
diff --git a/gettext-tools/lib/csharpcomp.sh.in b/gettext-tools/lib/csharpcomp.sh.in
new file mode 100644 (file)
index 0000000..84498ed
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/sh
+# Compile a C# program.
+
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# Written by Bruno Haible <bruno@clisp.org>, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
+
+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
+    test -z "$CSHARP_VERBOSE" || echo mcs $options_mcs $sources
+    exec mcs $options_mcs $sources
+  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
diff --git a/gettext-tools/m4/csharpcomp.m4 b/gettext-tools/m4/csharpcomp.m4
new file mode 100644 (file)
index 0000000..c862365
--- /dev/null
@@ -0,0 +1,49 @@
+# csharpcomp.m4 serial 1 (gettext-0.13.2)
+dnl Copyright (C) 2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+# Prerequisites of csharpcomp.sh.
+# Sets HAVE_CSHARPCOMP to nonempty if csharpcomp.sh will work.
+
+AC_DEFUN([gt_CSHARPCOMP],
+[
+  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
+  if test -n "$HAVE_CSCC_IN_PATH" \
+     && cscc --version >/dev/null 2>/dev/null; then
+    HAVE_CSCC=1
+    ac_result="cscc"
+  else
+    if test -n "$HAVE_MCS_IN_PATH" \
+       && mcs --version >/dev/null 2>/dev/null; then
+      HAVE_MCS=1
+      ac_result="mcs"
+    else
+      if test -n "$HAVE_CSC_IN_PATH" \
+         && csc -help >/dev/null 2>/dev/null; then
+        HAVE_CSC=1
+        ac_result="csc"
+      else
+        HAVE_CSHARPEXEC=
+        ac_result="no"
+      fi
+    fi
+  fi
+  AC_MSG_RESULT([$ac_result])
+  AC_SUBST(HAVE_CSCC)
+  AC_SUBST(HAVE_MCS)
+  AC_SUBST(HAVE_CSC)
+])