Search code examples
c++windowscygwinmingwlibreadline

Statically linked, correctly working readline library under Windows?


We're developing a C++ software package which depends on the GNU readline library and we usually build using gcc (requiring at least version 4). Now we would like to port this to Windows, obtaining a statically linked version which we can redistribute without requiring compilation by users.

I've tried several approaches:

  • Building using Cygwin (no go with the provided readline combined with -mno-cygwin or a MinGW compiler),
  • Building using MinGW and readline from GnuWin32 (unresolved dependencies to stat64, which I could not resolve),
  • Building using MinGW and building readline and required pdcurses from source (most promising approach, got to a static binary! But the obtained interactive shell behaved incorrectly, e.g. backspace was not visualized).

Any ideas how we might get one of the approaches to work?


Solution

  • After similar frustrations, I have just now compiled both a 32bit and 64bit version of libreadline 6.2 using MinGW-w64. Here's my how I did it:

    Layout of my dev directory:

    c:\dev\msys
    c:\dev\mingw32
    c:\dev\local32
    c:\dev\mingw64
    c:\dev\local64
    

    Set some environment variables for the 32 bit build:

    export CPPFLAGS=-I/c/dev/local32/include
    export LDFLAGS=-L/c/dev/local32/lib
    

    termcap 1.3.1.
    Run the configure script:

    ./configure --host=i686-w64_mingw32 --prefix=/c/dev/local32
    

    Edit termcap.c and fix up a few lines at the top. Mine looks like this:

    /* Emacs config.h may rename various library functions such as malloc.  */
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #ifdef emacs
    
    #include <lisp.h>       /* xmalloc is here */
    /* Get the O_* definitions for open et al.  */
    #include <sys/file.h>
    #ifdef HAVE_FCNTL_H
    #include <fcntl.h>
    #endif
    //#ifdef HAVE_UNISTD_H
    #include <unistd.h>
    //#endif
    
    #else /* not emacs */
    
    //#ifdef STDC_HEADERS
    #include <stdlib.h>
    #include <string.h>
    #define bcopy(b1,b2,len) (memmove((b2), (b1), (len)), (void) 0)
    //#else
    //char *getenv ();
    //char *malloc ();
    //char *realloc ();
    //#endif
    

    and tparam.c

    /* Emacs config.h may rename various library functions such as malloc.  */
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #ifdef emacs
    #include "lisp.h"       /* for xmalloc */
    #else
    
    //#ifdef STDC_HEADERS
    #include <stdlib.h>
    #include <string.h>
    //#else
    //char *malloc ();
    //char *realloc ();
    //#endif
    
    /* Do this after the include, in case string.h prototypes bcopy.  */
    //#if (defined(HAVE_STRING_H) || defined(STDC_HEADERS)) && !defined(bcopy)
    #define bcopy(s, d, n) memcpy ((d), (s), (n))
    //#endif
    
    #endif /* not emacs */
    

    Modify the Makefile:

    Line 23: CC = i686-w64-mingw32-gcc
    Line 24: AR = i686-w64-mingw32-ar
    Line 36: prefix = /c/dev/local32
    Line 49: #oldincludedir = /usr/local
    

    After that call make install and it should compile without warnings or errors.

    readline 6.2
    Set the same CPPFLAGS and LDFLAGS variables as with termcap before calling:

    ./configure --prefix=/c/dev/local32 --host=i686-w64-mingw32 --enable-static --enable-shared
    

    Edit the Makefile:

    Line 40: AR = i686-w64-mingw32-ar
    

    make install should now compile and install readline!
    If you want a 64bit library, replace i686-w64-mingw32 with x86_64-w64-mingw32 and local32 with local64.