Vasili Burdo on Wed, 23 Dec 2009 17:22:50 +0100


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: A patch for native PARI/GP build on Windows (Mingw+Msys)


Please check for any problem on the real thing
Everything is OK. make test-all passed

and please repost the part of the patches I did not apply but you feel are still needed.
See my current patch in attachment.

What's done:
- implemented "~" handling in paths - see pari_get_homedir() in es.c
- implemented unzipping from .zip archives I mentioned in previous post.
  See pari_get_infile(). If this function sees ".zip/" substring in
  file name, it tries to pipe it through "unzip -p".
As result, it's possible it set GPDATADIR to something like "/path/path/gpdata.zip". - removed "-wb" option from diff command in dotest. Instead, "sed -e 's/\r//'" used as you suggested. The same way dotest should be fixed in gp2c sources
- reimplemented -fno-omit-frame-pointer hack. See file config/get_cc
- added mingw support to config/get_modld - it's neccessary for gp2c interoperability

Do you know why DL_DFLT_NAME=$(LIBPARI_DYN) does not work here ? It did not
work with wine and this is strange because LIBPARI_SO is a symlink to
LIBPARI_DYN.
The problem is that Windows does not support symlinks. As result, we should maintain two copies: libpari.dll (because gp-dyn links to it) and libpari-2.4.dll (for install0).
I think keeping two copies is redundant.

You did not quite answer my question. Since LIBPARI_SO is a symlink for
LIBPARI_DYN, I would expect DL_DFLT_NAME="\\\"\$(LIBPARI_DYN)\\\"" to
work better than DL_DFLT_NAME="\\\"\$(LIBPARI_SO)\\\"", but it is not
the case. Do you know why ?
In my setup,
LIBPARI_DYN == "libpari-gmp-2.4.dll" and
LIBPARI_SO == "libpari.dll"

Because Windows does not support symlinks, we have two copies of the same file, but under different names.

"libpari.dll" (i.e LIBPARI_SO) is linked to gp-dyn.exe and thus it must be present. "libpari-gmp-2.4.dll" (i.e. DL_DFLT_NAME, i.e LIBPARI_DYN in your setup) used as default library name for "install" function.

I dont like to keep another copy of the same file (remember, Windows does not support symlinks) just because it's named differently somewhere. So, I use LIBPARI_SO (i.e "libpari.dll") for DL_DFLT_NAME.


What is the purpose of 'CFLAGS="$CFLAGS -fno-omit-frame-pointer"' ?
-fomit-frame-pointer ruins setjmp-based error handling - GP produces a lot of "Segfault" error messages. I dont understand why it happens, but -fno-omit-frame-pointer fixes it.
Probably, there is better place for this option, but I didnt find it yet.

Strange, I did not see any problem with wine.
It's because you're running on Unix :-)
Probably, Windows port of GCC has some subtle differences which cause this bug. I saw it on all GCC versions starting from 4.0.0

I agree with your approach. I suggest to do things a bit differently:
We define a special value DYNDATADIR for GPDATADIR (say DYNDATADIR="" ) and
we test if GPDATADIR is equal to DYNDATADIR, and in that case we set
datadir to win32_GPDATADIR instead of GPDATADIR. We change Configure to set GPDATADIR to DYNDATADIR by default.
I don't quite understand how it will work, so please, do it yourself.
Index: config/get_cc
===================================================================
--- config/get_cc	(revision 12049)
+++ config/get_cc	(working copy)
@@ -17,6 +17,7 @@
 case "$osname-$arch" in
   os2-*)   exe_suff=.exe; extraflag="-Zexe";;
   cygwin*) exe_suff=.exe; extraflag="";;
+  mingw*)  exe_suff=.exe; extraflag="";;
 # On Darwin, by default, the full library search path is searched for a .dylib
 # before a .a can be considered, preventing users to install their libraries
 # in a simple way (e.g. the readline / Editline conflict). Override this.
@@ -147,7 +148,9 @@
   # omit-frame-pointer incompatible with -pg
   PRFFLAGS="-pg $OPTFLAGS"
   case "$optimization" in
-    full) OPTFLAGS="$OPTFLAGS -fomit-frame-pointer";;
+    full) if "$osname" ne "mingw"; then
+            OPTFLAGS="$OPTFLAGS -fomit-frame-pointer"
+          fi;;
   esac
 else
   DBGFLAGS=${DBGFLAGS:-'-g'}
Index: config/get_graphic_lib
===================================================================
--- config/get_graphic_lib	(revision 12049)
+++ config/get_graphic_lib	(working copy)
@@ -58,4 +58,9 @@
 esac
 case $which_graphic_lib in auto) which_graphic_lib=none;; esac
 
+if test "$which_graphic_lib" == none; then
+  if test "$osname" == "mingw"; then
+    which_graphic_lib=win32
+  fi
+fi
 echo "Hi-Res Graphics: $which_graphic_lib"
Index: config/get_modld
===================================================================
--- config/get_modld	(revision 12049)
+++ config/get_modld	(working copy)
@@ -6,6 +6,10 @@
 if test "$static" = n; then LIBS="$LIBS $LDDYN"; fi
 case $osname in
 cygwin) EXTRAMODLDFLAGS="-L$libdir -lpari.dll";;
+mingw)  CC=`basename $CC`
+        DLLD=`basename $DLLD`
+        EXTRAMODLDFLAGS="-lpari"
+        ;;
 *)      EXTRAMODLDFLAGS=`eval echo $EXTRADLLDFLAGS`;;
 esac;
 LIBS=$__LIBS
@@ -17,7 +21,8 @@
 *)      MODLD="$DLLD";
         MODLDFLAGS=`echo "$DLLDFLAGS" | \
    sed -e 's/,*-[^ \t-]*[ \t,=]*\\$(LIBPARI_SONAME)//' \
-       -e 's/--out-implib=\$(LIBPARI_SO)\$(_A),\?//'`;;
+       -e 's/--out-implib=\$(LIBPARI_SO)\$(_A),\?//' \
+       -e 's/-Wl,[ \t]*$//'`;;
 esac;
 
 modules_build=`echo "$CC -c -o %s.o $CFLAGS $DLCFLAGS -I\"$includedir\" %s.c \
Index: config/paricfg.h.SH
===================================================================
--- config/paricfg.h.SH	(revision 12049)
+++ config/paricfg.h.SH	(working copy)
@@ -73,13 +73,23 @@
   fi
 fi
 
+if test -n "$unzip"; then
+  cat >> $file << EOT
+#define UNZIP "$unzip -p"
+EOT
+fi
+
 if test "$osname" = "mingw"; then
 cat >> $file << EOT
 
 #undef UNIX
 #define GNUZCAT
-#undef ZCAT 
+#undef ZCAT
 #define ZCAT "gzip.exe -dc"
+#undef UNZIP
+#define UNZIP "unzip.exe -p"
+#undef GPDATADIR
+#define GPDATADIR win32_GPDATADIR()
 
 EOT
 fi
Index: Configure
===================================================================
--- Configure	(revision 12049)
+++ Configure	(working copy)
@@ -36,7 +36,7 @@
 . ./get_PATH
 #  We might need the following :
 echo Looking for some tools first ...
-list='ld zcat gzip ranlib perl'
+list='ld zcat gzip unzip ranlib perl'
 pathspace=`echo $PATH | sed -e "s/$dir_sep/ /g" | sed -e 's,\\\\,/,g'`
 
 for file in $list; do
Index: src/language/es.c
===================================================================
--- src/language/es.c	(revision 12049)
+++ src/language/es.c	(working copy)
@@ -3348,6 +3348,31 @@
   if (!dir) pari_warn(warner,"can't expand ~%s", user? user: "");
   return dir;
 }
+#elif defined(_WIN32)
+char *
+pari_get_homedir(const char *user)
+{
+  char *drv, *pth;
+  
+  if (user && *user) {
+    pari_warn(warner,"can't expand ~%s", user ? user: "");
+    return NULL;
+  }
+  
+  if (homedir)
+    return homedir;
+
+  pth = os_getenv("HOME");
+  if (pth) return pth;
+  
+  if ((drv = os_getenv("HOMEDRIVE"))
+   && (pth = os_getenv("HOMEPATH")))
+  { /* looks like WinNT */
+    char *homedir = (char*)pari_malloc(strlen(pth) + strlen(drv) + 1);
+    sprintf(homedir, "%s%s",drv,pth);
+  }
+  return homedir;
+}
 #else
 char *
 pari_get_homedir(const char *user) { return NULL; }
@@ -3588,6 +3613,21 @@
     return try_pipe(cmd, mf_IN);
   }
 #endif
+#ifdef UNZIP
+  if ((end = strstr(name, ".zip/"))) {
+    char *cmd;
+
+    end = end + 4;
+    cmd = stackmalloc(strlen(name) + strlen(UNZIP) + 32);
+    strcpy(cmd, UNZIP);
+    strcat(cmd, " ");
+    strncat(cmd, name, (end-name));
+    strcat(cmd, " ");
+    strcat(cmd, end+1);
+    return try_pipe(cmd, mf_IN);
+  }
+#endif
+
   return newfile(file, name, mf_IN);
 }
 
@@ -3600,7 +3640,8 @@
   FILE *f = fopen(s, "r");
   pariFILE *pf;
 
-  if (f) return pari_get_infile(s, f);
+  if (f || strstr(s, ".zip/"))
+    return pari_get_infile(s, f);
 
   l = strlen(s);
   name = stackmalloc(l + 3 + 1);
Index: src/systems/mingw/mingw.c
===================================================================
--- src/systems/mingw/mingw.c	(revision 12049)
+++ src/systems/mingw/mingw.c	(working copy)
@@ -17,6 +17,8 @@
 
 #include <windows.h>
 #include <stdio.h>
+#include <io.h>
+#include "paricfg.h"
 #include "mingw.h"
 
 static WORD
@@ -93,3 +95,24 @@
       return 0;
   return (sbi.srWindow.Bottom - sbi.srWindow.Top);
 }
+
+const char* win32_GPDATADIR()
+{
+    static char datadir[1024] = {0};
+    if( 0 == *datadir ) {
+        char* slash;
+        GetModuleFileNameA(0, datadir, sizeof(datadir) );
+        slash = strrchr(datadir, '\\');
+        if( slash ) *(slash+1) = 0;
+#ifdef UNZIP
+        strcat(datadir, "gp.zip");
+		if( access(datadir,04) ) {
+			*(slash+1) = 0;
+			strcat(datadir, "gp-data");
+		}
+#else
+        strcat(datadir, "gp-data");
+#endif
+    }
+    return datadir;
+}
Index: src/test/dotest
===================================================================
--- src/test/dotest	(revision 12049)
+++ src/test/dotest	(working copy)
@@ -73,7 +73,7 @@
       *)   file_diff=$testname-$suf.dif
            gp=$execdir/gp-$suf;;
     esac
-    (cat $file_in; echo 'print("Total time spent: ",gettime);') | $RUNTEST $gp -q --test  > $file_test 2>&1
+    (cat $file_in; echo 'print("Total time spent: ",gettime);') | $RUNTEST $gp -q --test | sed -e 's/\r//g' > $file_test 2>&1
     diff -c $file_out $file_test > $file_diff
     pat=`grep "^[-+!] " $file_diff | grep -v "Total time"`
     time=`${tail}1 $file_test | sed -n 's,.*Total time spent: \(.*\),\1,p'`